summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics
diff options
context:
space:
mode:
authorIain Merrick <husky@google.com>2010-09-13 16:35:48 +0100
committerIain Merrick <husky@google.com>2010-09-16 12:10:42 +0100
commit5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306 (patch)
treeddce1aa5e3b6967a69691892e500897558ff8ab6 /WebCore/platform/graphics
parent12bec63ec71e46baba27f0bd9bd9d8067683690a (diff)
downloadexternal_webkit-5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306.zip
external_webkit-5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306.tar.gz
external_webkit-5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306.tar.bz2
Merge WebKit at r67178 : Initial merge by git.
Change-Id: I57e01163b6866cb029cdadf405a0394a3918bc18
Diffstat (limited to 'WebCore/platform/graphics')
-rw-r--r--WebCore/platform/graphics/Font.cpp10
-rw-r--r--WebCore/platform/graphics/GraphicsContext.cpp29
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h8
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.h12
-rw-r--r--WebCore/platform/graphics/MediaPlayer.cpp6
-rw-r--r--WebCore/platform/graphics/MediaPlayer.h6
-rw-r--r--WebCore/platform/graphics/Path.cpp2
-rw-r--r--WebCore/platform/graphics/Path.h5
-rw-r--r--WebCore/platform/graphics/cairo/FontCacheCairo.cpp8
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp2
-rw-r--r--WebCore/platform/graphics/cairo/OwnPtrCairo.cpp (renamed from WebCore/platform/graphics/cairo/GOwnPtrCairo.cpp)8
-rw-r--r--WebCore/platform/graphics/cairo/OwnPtrCairo.h (renamed from WebCore/platform/graphics/cairo/GOwnPtrCairo.h)12
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp1
-rw-r--r--WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp112
-rw-r--r--WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h65
-rw-r--r--WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp43
-rw-r--r--WebCore/platform/graphics/chromium/CanvasLayerChromium.h28
-rw-r--r--WebCore/platform/graphics/chromium/ContentLayerChromium.cpp35
-rw-r--r--WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp142
-rw-r--r--WebCore/platform/graphics/chromium/FontChromiumWin.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/FontLinux.cpp33
-rw-r--r--WebCore/platform/graphics/chromium/GLES2Canvas.cpp166
-rw-r--r--WebCore/platform/graphics/chromium/GLES2Canvas.h29
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp13
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.h2
-rw-r--r--WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp10
-rw-r--r--WebCore/platform/graphics/chromium/ImageLayerChromium.cpp10
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.cpp18
-rw-r--r--WebCore/platform/graphics/chromium/VideoLayerChromium.cpp7
-rw-r--r--WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp85
-rw-r--r--WebCore/platform/graphics/chromium/WebGLLayerChromium.h60
-rw-r--r--WebCore/platform/graphics/gpu/DrawingBuffer.cpp60
-rw-r--r--WebCore/platform/graphics/gpu/DrawingBuffer.h84
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnClassifier.cpp122
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnClassifier.h84
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnConstants.h40
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp565
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnMathUtils.h108
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.cpp171
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.h82
-rw-r--r--WebCore/platform/graphics/gpu/PODArena.h211
-rw-r--r--WebCore/platform/graphics/gpu/PODInterval.h155
-rw-r--r--WebCore/platform/graphics/gpu/PODIntervalTree.h217
-rw-r--r--WebCore/platform/graphics/gpu/PODRedBlackTree.h750
-rw-r--r--WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp296
-rw-r--r--WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h124
-rw-r--r--WebCore/platform/graphics/gpu/Texture.cpp68
-rw-r--r--WebCore/platform/graphics/gpu/Texture.h3
-rw-r--r--WebCore/platform/graphics/gpu/TilingData.h1
-rw-r--r--WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp3
-rw-r--r--WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h3
-rw-r--r--WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp2
-rw-r--r--WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h2
-rw-r--r--WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp4
-rw-r--r--WebCore/platform/graphics/gstreamer/GStreamerGWorld.h3
-rw-r--r--WebCore/platform/graphics/gstreamer/ImageGStreamer.h4
-rw-r--r--WebCore/platform/graphics/gstreamer/ImageGStreamerCG.mm3
-rw-r--r--WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp6
-rw-r--r--WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp36
-rw-r--r--WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h4
-rw-r--r--WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h4
-rw-r--r--WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp3
-rw-r--r--WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp3
-rw-r--r--WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp2
-rw-r--r--WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h3
-rw-r--r--WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp3
-rw-r--r--WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h2
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContext3DMac.mm31
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm43
-rw-r--r--WebCore/platform/graphics/qt/GraphicsLayerQt.cpp37
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp8
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h1
-rw-r--r--WebCore/platform/graphics/qt/PathQt.cpp30
-rw-r--r--WebCore/platform/graphics/skia/FontCustomPlatformData.cpp (renamed from WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp)0
-rw-r--r--WebCore/platform/graphics/skia/FontCustomPlatformData.h (renamed from WebCore/platform/graphics/chromium/FontCustomPlatformData.h)0
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextSkia.cpp29
-rw-r--r--WebCore/platform/graphics/skia/ImageBufferSkia.cpp22
-rw-r--r--WebCore/platform/graphics/skia/ImageSkia.cpp5
-rwxr-xr-x[-rw-r--r--]WebCore/platform/graphics/skia/PlatformContextSkia.cpp139
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.h28
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCGWin.cpp56
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp3
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextWin.cpp2
-rw-r--r--WebCore/platform/graphics/win/IconWin.cpp8
-rwxr-xr-xWebCore/platform/graphics/win/LocalWindowsContext.h61
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp1
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp5
87 files changed, 4205 insertions, 504 deletions
diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp
index 0e93d4f..a0cf5a4 100644
--- a/WebCore/platform/graphics/Font.cpp
+++ b/WebCore/platform/graphics/Font.cpp
@@ -277,6 +277,8 @@ Font::CodePath Font::codePath(const TextRun& run) const
return Complex;
#endif
+ CodePath result = Simple;
+
// Start from 0 since drawing and highlighting also measure the characters before run->from
for (int i = 0; i < run.length(); i++) {
const UChar c = run[i];
@@ -312,8 +314,10 @@ Font::CodePath Font::codePath(const TextRun& run) const
if (c < 0x1E00) // U+1E00 through U+2000 characters with diacritics and stacked diacritics
continue;
- if (c <= 0x2000)
- return SimpleWithGlyphOverflow;
+ if (c <= 0x2000) {
+ result = SimpleWithGlyphOverflow;
+ continue;
+ }
if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
continue;
@@ -329,7 +333,7 @@ Font::CodePath Font::codePath(const TextRun& run) const
if (typesettingFeatures())
return Complex;
- return Simple;
+ return result;
}
}
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
index 94f3424..3dfdb20 100644
--- a/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -467,7 +467,7 @@ void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorS
{
if (paintingDisabled() || !image)
return;
-
+
float tsw = src.width();
float tsh = src.height();
float tw = dest.width();
@@ -489,7 +489,7 @@ void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorS
}
image->draw(this, styleColorSpace, dest, src, op, useLowQualityScale);
-
+
if (useLowQualityScale)
restore();
}
@@ -571,6 +571,21 @@ void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle&)
}
#endif
+#if !PLATFORM(SKIA)
+void GraphicsContext::setSharedGraphicsContext3D(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&)
+{
+}
+
+void GraphicsContext::syncSoftwareCanvas()
+{
+}
+
+void GraphicsContext::markDirtyRect(const IntRect&)
+{
+}
+#endif
+
+
void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, const StrokeStyle& penStyle)
{
// For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
@@ -600,14 +615,4 @@ void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2
}
}
-#if !PLATFORM(SKIA)
-void GraphicsContext::setGraphicsContext3D(GraphicsContext3D*, const IntSize&)
-{
-}
-
-void GraphicsContext::syncSoftwareCanvas()
-{
-}
-#endif
-
}
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index c5440f3..7863b95 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -21,7 +21,7 @@
* 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GraphicsContext_h
@@ -131,16 +131,17 @@ namespace WebCore {
const int cMisspellingLinePatternGapWidth = 1;
class AffineTransform;
+ class DrawingBuffer;
class Font;
class Generator;
class Gradient;
- class GraphicsContext3D;
class GraphicsContextPlatformPrivate;
class GraphicsContextPrivate;
class ImageBuffer;
class KURL;
class Path;
class Pattern;
+ class SharedGraphicsContext3D;
class TextRun;
// These bits can be ORed together for a total of 8 possible text drawing modes.
@@ -456,8 +457,9 @@ namespace WebCore {
pattern getHaikuStrokeStyle();
#endif
- void setGraphicsContext3D(GraphicsContext3D*, const IntSize&);
+ void setSharedGraphicsContext3D(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&);
void syncSoftwareCanvas();
+ void markDirtyRect(const IntRect&); // Hints that a portion of the backing store is dirty.
private:
void savePlatformState();
diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h
index 0f74cd5..68a580e 100644
--- a/WebCore/platform/graphics/GraphicsLayer.h
+++ b/WebCore/platform/graphics/GraphicsLayer.h
@@ -85,18 +85,18 @@ class FloatPoint3D;
class GraphicsContext;
class Image;
class TextStream;
-struct TimingFunction;
+class TimingFunction;
// Base class for animation values (also used for transitions). Here to
// represent values for properties being animated via the GraphicsLayer,
// without pulling in style-related data from outside of the platform directory.
class AnimationValue : public Noncopyable {
public:
- AnimationValue(float keyTime, const TimingFunction* timingFunction = 0)
+ AnimationValue(float keyTime, PassRefPtr<TimingFunction> timingFunction = 0)
: m_keyTime(keyTime)
{
if (timingFunction)
- m_timingFunction = adoptPtr(new TimingFunction(*timingFunction));
+ m_timingFunction = timingFunction;
}
virtual ~AnimationValue() { }
@@ -106,13 +106,13 @@ public:
private:
float m_keyTime;
- OwnPtr<TimingFunction> m_timingFunction;
+ RefPtr<TimingFunction> m_timingFunction;
};
// Used to store one float value of an animation.
class FloatAnimationValue : public AnimationValue {
public:
- FloatAnimationValue(float keyTime, float value, const TimingFunction* timingFunction = 0)
+ FloatAnimationValue(float keyTime, float value, PassRefPtr<TimingFunction> timingFunction = 0)
: AnimationValue(keyTime, timingFunction)
, m_value(value)
{
@@ -127,7 +127,7 @@ private:
// Used to store one transform value in a keyframe list.
class TransformAnimationValue : public AnimationValue {
public:
- TransformAnimationValue(float keyTime, const TransformOperations* value = 0, const TimingFunction* timingFunction = 0)
+ TransformAnimationValue(float keyTime, const TransformOperations* value = 0, PassRefPtr<TimingFunction> timingFunction = 0)
: AnimationValue(keyTime, timingFunction)
{
if (value)
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
index a5db85f..2588d8d 100644
--- a/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -699,6 +699,12 @@ void MediaPlayer::rateChanged()
m_mediaPlayerClient->mediaPlayerRateChanged(this);
}
+void MediaPlayer::playbackStateChanged()
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerPlaybackStateChanged(this);
+}
+
}
#endif
diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h
index 643f17f..bf445e3 100644
--- a/WebCore/platform/graphics/MediaPlayer.h
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -70,6 +70,7 @@ struct PlatformMedia {
QTMovieVisualContextType,
GStreamerGWorldType,
ChromiumMediaPlayerType,
+ QtMediaPlayerType,
} type;
union {
@@ -78,6 +79,7 @@ struct PlatformMedia {
QTMovieVisualContext* qtMovieVisualContext;
GStreamerGWorld* gstreamerGWorld;
MediaPlayerPrivateInterface* chromiumMediaPlayer;
+ MediaPlayerPrivateInterface* qtMediaPlayer;
} media;
};
@@ -119,6 +121,9 @@ public:
// the playback rate has changed
virtual void mediaPlayerRateChanged(MediaPlayer*) { }
+ // the play/pause status changed
+ virtual void mediaPlayerPlaybackStateChanged(MediaPlayer*) { }
+
// The MediaPlayer has found potentially problematic media content.
// This is used internally to trigger swapping from a <video>
// element to an <embed> in standalone documents
@@ -244,6 +249,7 @@ public:
void timeChanged();
void sizeChanged();
void rateChanged();
+ void playbackStateChanged();
void durationChanged();
void repaint();
diff --git a/WebCore/platform/graphics/Path.cpp b/WebCore/platform/graphics/Path.cpp
index 333afcb..4e2de53 100644
--- a/WebCore/platform/graphics/Path.cpp
+++ b/WebCore/platform/graphics/Path.cpp
@@ -39,7 +39,7 @@ static const float QUARTER = 0.552f; // approximation of control point positions
// to simulate a quarter of a circle.
namespace WebCore {
-#if !PLATFORM(OPENVG)
+#if !PLATFORM(OPENVG) && !PLATFORM(QT)
static void pathLengthApplierFunction(void* info, const PathElement* element)
{
PathTraversalState& traversalState = *static_cast<PathTraversalState*>(info);
diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h
index 61ea328..9896713 100644
--- a/WebCore/platform/graphics/Path.h
+++ b/WebCore/platform/graphics/Path.h
@@ -133,6 +133,11 @@ namespace WebCore {
void addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint);
void addArcTo(const FloatPoint&, const FloatPoint&, float radius);
void closeSubpath();
+#if PLATFORM(QT)
+ void closeCanvasSubpath();
+#else
+ void closeCanvasSubpath() { closeSubpath(); }
+#endif
void addArc(const FloatPoint&, float radius, float startAngle, float endAngle, bool anticlockwise);
void addRect(const FloatRect&);
diff --git a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp
index cb54549..5d3263e 100644
--- a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp
+++ b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp
@@ -23,7 +23,7 @@
#include "CString.h"
#include "Font.h"
-#include "GOwnPtrCairo.h"
+#include "OwnPtrCairo.h"
#include "SimpleFontData.h"
#include <wtf/Assertions.h>
@@ -115,15 +115,15 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
CString familyNameString = family.string().utf8();
const char* fcfamily = familyNameString.data();
- GOwnPtr<FcPattern> pattern(FcPatternCreate());
+ OwnPtr<FcPattern> pattern(FcPatternCreate());
if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily)))
return 0;
- GOwnPtr<FcObjectSet> objectSet(FcObjectSetCreate());
+ OwnPtr<FcObjectSet> objectSet(FcObjectSetCreate());
if (!FcObjectSetAdd(objectSet.get(), FC_FAMILY))
return 0;
- GOwnPtr<FcFontSet> fontSet(FcFontList(0, pattern.get(), objectSet.get()));
+ OwnPtr<FcFontSet> fontSet(FcFontList(0, pattern.get(), objectSet.get()));
if (!fontSet)
return 0;
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 19cc518..283e75a 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -562,7 +562,7 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
cairo_antialias_t savedAntialiasRule = cairo_get_antialias(cr);
- cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
+ cairo_set_antialias(cr, antialiased ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
addConvexPolygonToContext(cr, numPoints, points);
cairo_clip(cr);
diff --git a/WebCore/platform/graphics/cairo/GOwnPtrCairo.cpp b/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp
index 12df3cf..9be8670 100644
--- a/WebCore/platform/graphics/cairo/GOwnPtrCairo.cpp
+++ b/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp
@@ -18,7 +18,7 @@
*/
#include "config.h"
-#include "GOwnPtrCairo.h"
+#include "OwnPtrCairo.h"
#if defined(USE_FREETYPE)
#include <cairo-ft.h>
@@ -28,19 +28,19 @@
namespace WTF {
#if defined(USE_FREETYPE)
-template <> void freeOwnedGPtr<FcPattern>(FcPattern* ptr)
+template <> void deleteOwnedPtr<FcPattern>(FcPattern* ptr)
{
if (ptr)
FcPatternDestroy(ptr);
}
-template <> void freeOwnedGPtr<FcObjectSet>(FcObjectSet* ptr)
+template <> void deleteOwnedPtr<FcObjectSet>(FcObjectSet* ptr)
{
if (ptr)
FcObjectSetDestroy(ptr);
}
-template <> void freeOwnedGPtr<FcFontSet>(FcFontSet* ptr)
+template <> void deleteOwnedPtr<FcFontSet>(FcFontSet* ptr)
{
if (ptr)
FcFontSetDestroy(ptr);
diff --git a/WebCore/platform/graphics/cairo/GOwnPtrCairo.h b/WebCore/platform/graphics/cairo/OwnPtrCairo.h
index b099707..29f4562 100644
--- a/WebCore/platform/graphics/cairo/GOwnPtrCairo.h
+++ b/WebCore/platform/graphics/cairo/OwnPtrCairo.h
@@ -17,10 +17,10 @@
* Boston, MA 02110-1301 USA
*/
-#ifndef GOwnPtrCairo_h
-#define GOwnPtrCairo_h
+#ifndef OwnPtrCairo_h
+#define OwnPtrCairo_h
-#include "GOwnPtr.h"
+#include "OwnPtr.h"
#if defined(USE_FREETYPE)
typedef struct _FcPattern FcPattern;
@@ -31,9 +31,9 @@ typedef struct _FcFontSet FcFontSet;
namespace WTF {
#if defined(USE_FREETYPE)
-template <> void freeOwnedGPtr<FcPattern>(FcPattern*);
-template <> void freeOwnedGPtr<FcObjectSet>(FcObjectSet*);
-template <> void freeOwnedGPtr<FcFontSet>(FcFontSet*);
+template <> void deleteOwnedPtr<FcPattern>(FcPattern*);
+template <> void deleteOwnedPtr<FcObjectSet>(FcObjectSet*);
+template <> void deleteOwnedPtr<FcFontSet>(FcFontSet*);
#endif
} // namespace WTF
diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
index c4008cc..fadc385 100644
--- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
@@ -119,6 +119,7 @@ bool GraphicsContext3D::getImageData(Image* image,
default:
return false;
}
+ break;
case kCGImageAlphaNone:
switch (componentsPerPixel) {
case 1:
diff --git a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
new file mode 100644
index 0000000..9826c3e
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "Canvas2DLayerChromium.h"
+
+#include "DrawingBuffer.h"
+
+#include <GLES2/gl2.h>
+
+namespace WebCore {
+
+PassRefPtr<Canvas2DLayerChromium> Canvas2DLayerChromium::create(DrawingBuffer* drawingBuffer, GraphicsLayerChromium* owner)
+{
+ return adoptRef(new Canvas2DLayerChromium(drawingBuffer, owner));
+}
+
+Canvas2DLayerChromium::Canvas2DLayerChromium(DrawingBuffer* drawingBuffer, GraphicsLayerChromium* owner)
+ : CanvasLayerChromium(owner)
+ , m_drawingBuffer(drawingBuffer)
+{
+}
+
+Canvas2DLayerChromium::~Canvas2DLayerChromium()
+{
+ if (m_textureId)
+ glDeleteTextures(1, &m_textureId);
+}
+
+void Canvas2DLayerChromium::updateContents()
+{
+ if (!m_drawingBuffer)
+ return;
+ if (m_textureChanged) { // We have to generate a new backing texture.
+ if (m_textureId)
+ glDeleteTextures(1, &m_textureId);
+ glGenTextures(1, &m_textureId);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_textureId);
+ IntSize size = m_drawingBuffer->size();
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ // Set the min-mag filters to linear and wrap modes to GL_CLAMP_TO_EDGE
+ // to get around NPOT texture limitations of GLES.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_textureChanged = false;
+ // FIXME: The glFinish() here is required because we have to make sure that the texture created in this
+ // context (the compositor context) is actually created by the service side before the child context
+ // attempts to use it (in publishToPlatformLayer). glFinish() is currently the only call with strong
+ // enough semantics to promise this, but is actually much stronger. Ideally we'd do something like
+ // inserting a fence here and waiting for it before trying to publish.
+ glFinish();
+ }
+ // Update the contents of the texture used by the compositor.
+ if (m_contentsDirty) {
+ m_drawingBuffer->publishToPlatformLayer();
+ m_contentsDirty = false;
+ }
+}
+
+void Canvas2DLayerChromium::setTextureChanged()
+{
+ m_textureChanged = true;
+}
+
+unsigned Canvas2DLayerChromium::textureId() const
+{
+ return m_textureId;
+}
+
+void Canvas2DLayerChromium::setDrawingBuffer(DrawingBuffer* drawingBuffer)
+{
+ if (drawingBuffer != m_drawingBuffer) {
+ m_drawingBuffer = drawingBuffer;
+ m_textureChanged = true;
+ }
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
new file mode 100644
index 0000000..0031229
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef Canvas2DLayerChromium_h
+#define Canvas2DLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "CanvasLayerChromium.h"
+
+namespace WebCore {
+
+class DrawingBuffer;
+
+// A layer containing an accelerated 2d canvas
+class Canvas2DLayerChromium : public CanvasLayerChromium {
+public:
+ static PassRefPtr<Canvas2DLayerChromium> create(DrawingBuffer*, GraphicsLayerChromium* owner);
+ virtual ~Canvas2DLayerChromium();
+ virtual bool drawsContent() { return true; }
+ virtual void updateContents();
+
+ void setTextureChanged();
+ unsigned textureId() const;
+ void setDrawingBuffer(DrawingBuffer*);
+
+private:
+ explicit Canvas2DLayerChromium(DrawingBuffer*, GraphicsLayerChromium* owner);
+ DrawingBuffer* m_drawingBuffer;
+
+ static unsigned m_shaderProgramId;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp b/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
index bbf091c..56a7262 100644
--- a/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
@@ -34,12 +34,14 @@
#include "CanvasLayerChromium.h"
-#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
+
#include <GLES2/gl2.h>
namespace WebCore {
+unsigned CanvasLayerChromium::m_shaderProgramId = 0;
+
CanvasLayerChromium::SharedValues::SharedValues()
: m_canvasShaderProgram(0)
, m_shaderSamplerLocation(-1)
@@ -93,49 +95,15 @@ CanvasLayerChromium::SharedValues::~SharedValues()
GLC(glDeleteProgram(m_canvasShaderProgram));
}
-PassRefPtr<CanvasLayerChromium> CanvasLayerChromium::create(GraphicsLayerChromium* owner)
-{
- return adoptRef(new CanvasLayerChromium(owner));
-}
-
CanvasLayerChromium::CanvasLayerChromium(GraphicsLayerChromium* owner)
: LayerChromium(owner)
- , m_context(0)
+ , m_textureChanged(true)
, m_textureId(0)
- , m_textureChanged(false)
-{
-}
-
-void CanvasLayerChromium::updateContents()
{
- ASSERT(m_context);
- if (m_textureChanged) {
- glBindTexture(GL_TEXTURE_2D, m_textureId);
- // Set the min-mag filters to linear and wrap modes to GL_CLAMP_TO_EDGE
- // to get around NPOT texture limitations of GLES.
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- m_textureChanged = false;
- }
- // Update the contents of the texture used by the compositor.
- if (m_contentsDirty) {
- if (m_prepareTextureCallback)
- m_prepareTextureCallback->willPrepareTexture();
- m_context->prepareTexture();
- m_contentsDirty = false;
- }
}
-void CanvasLayerChromium::setContext(const GraphicsContext3D* context)
+CanvasLayerChromium::~CanvasLayerChromium()
{
- m_context = const_cast<GraphicsContext3D*>(context);
-
- unsigned int textureId = m_context->platformTexture();
- if (textureId != m_textureId)
- m_textureChanged = true;
- m_textureId = textureId;
}
void CanvasLayerChromium::draw()
@@ -150,6 +118,7 @@ void CanvasLayerChromium::draw()
drawTexturedQuad(layerRenderer()->projectionMatrix(), drawTransform(),
bounds().width(), bounds().height(), drawOpacity(),
sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+
}
}
diff --git a/WebCore/platform/graphics/chromium/CanvasLayerChromium.h b/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
index 053efff..d591c73 100644
--- a/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
@@ -38,17 +38,12 @@
namespace WebCore {
-class GraphicsContext3D;
-
-// A Layer containing a WebGL or accelerated 2d canvas
+// Base class for WebGL and accelerated 2d canvases.
class CanvasLayerChromium : public LayerChromium {
public:
- static PassRefPtr<CanvasLayerChromium> create(GraphicsLayerChromium* owner = 0);
- virtual bool drawsContent() { return m_context; }
- virtual void updateContents();
- virtual void draw();
+ virtual ~CanvasLayerChromium();
- void setContext(const GraphicsContext3D* context);
+ virtual void draw();
class SharedValues {
public:
@@ -69,21 +64,16 @@ public:
bool m_initialized;
};
- class PrepareTextureCallback : public Noncopyable {
- public:
- virtual void willPrepareTexture() = 0;
- };
- void setPrepareTextureCallback(PassOwnPtr<PrepareTextureCallback> callback) { m_prepareTextureCallback = callback; }
-
-private:
+protected:
explicit CanvasLayerChromium(GraphicsLayerChromium* owner);
- GraphicsContext3D* m_context;
- unsigned m_textureId;
bool m_textureChanged;
- OwnPtr<PrepareTextureCallback> m_prepareTextureCallback;
+ unsigned m_textureId;
+
+private:
+ static unsigned m_shaderProgramId;
};
}
#endif // USE(ACCELERATED_COMPOSITING)
-#endif
+#endif // CanvasLayerChromium_h
diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
index 974933d..48119bb 100644
--- a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -42,6 +42,8 @@
#include "PlatformContextSkia.h"
#include "skia/ext/platform_canvas.h"
#elif PLATFORM(CG)
+#include "LocalCurrentGraphicsContext.h"
+
#include <CoreGraphics/CGBitmapContext.h>
#endif
@@ -152,12 +154,6 @@ void ContentLayerChromium::updateContents()
IntSize requiredTextureSize;
IntSize bitmapSize;
-#if PLATFORM(SKIA)
- const SkBitmap* skiaBitmap = 0;
- OwnPtr<skia::PlatformCanvas> canvas;
- OwnPtr<PlatformContextSkia> skiaContext;
- OwnPtr<GraphicsContext> graphicsContext;
-
requiredTextureSize = m_bounds;
IntRect boundsRect(IntPoint(0, 0), m_bounds);
@@ -171,17 +167,18 @@ void ContentLayerChromium::updateContents()
dirtyRect.intersect(boundsRect);
}
+#if PLATFORM(SKIA)
+ const SkBitmap* skiaBitmap = 0;
+ OwnPtr<skia::PlatformCanvas> canvas;
+ OwnPtr<PlatformContextSkia> skiaContext;
+ OwnPtr<GraphicsContext> graphicsContext;
+
canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false));
skiaContext.set(new PlatformContextSkia(canvas.get()));
-#if OS(WINDOWS)
- // This is needed to get text to show up correctly. Without it,
- // GDI renders with zero alpha and the text becomes invisible.
- // Unfortunately, setting this to true disables cleartype.
+ // This is needed to get text to show up correctly.
// FIXME: Does this take us down a very slow text rendering path?
- // FIXME: why is this is a windows-only call ?
skiaContext->setDrawingToImageBuffer(true);
-#endif
graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get())));
@@ -201,19 +198,6 @@ void ContentLayerChromium::updateContents()
bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
}
#elif PLATFORM(CG)
- requiredTextureSize = m_bounds;
- IntRect boundsRect(IntPoint(0, 0), m_bounds);
-
- // If the texture needs to be reallocated then we must redraw the entire
- // contents of the layer.
- if (requiredTextureSize != m_allocatedTextureSize)
- 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);
- }
-
Vector<uint8_t> tempVector;
int rowBytes = 4 * dirtyRect.width();
tempVector.resize(rowBytes * dirtyRect.height());
@@ -225,6 +209,7 @@ void ContentLayerChromium::updateContents()
kCGImageAlphaPremultipliedLast));
GraphicsContext graphicsContext(contextCG.get());
+ LocalCurrentGraphicsContext scopedNSGraphicsContext(&graphicsContext);
// Translate the graphics contxt into the coordinate system of the dirty rect.
graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y());
diff --git a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
new file mode 100644
index 0000000..64981ee
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "DrawingBuffer.h"
+
+#include "GraphicsContext3D.h"
+#include "SharedGraphicsContext3D.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "Canvas2DLayerChromium.h"
+#endif
+
+#include <GLES2/gl2.h>
+#ifndef GL_GLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES 1
+#endif
+#include <GLES2/gl2ext.h>
+
+namespace WebCore {
+
+struct DrawingBufferInternal {
+ unsigned offscreenColorTexture;
+#if USE(ACCELERATED_COMPOSITING)
+ RefPtr<Canvas2DLayerChromium> platformLayer;
+#endif
+};
+
+static unsigned generateColorTexture(SharedGraphicsContext3D* context, const IntSize& size)
+{
+ unsigned offscreenColorTexture = context->createTexture();
+ if (!offscreenColorTexture)
+ return 0;
+
+ context->bindTexture(GraphicsContext3D::TEXTURE_2D, offscreenColorTexture);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST);
+ 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->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
+ context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, offscreenColorTexture, 0);
+
+ return offscreenColorTexture;
+}
+
+
+DrawingBuffer::DrawingBuffer(SharedGraphicsContext3D* context, const IntSize& size, unsigned framebuffer)
+ : m_context(context)
+ , m_size(size)
+ , m_framebuffer(framebuffer)
+ , m_internal(new DrawingBufferInternal)
+{
+ context->bindFramebuffer(framebuffer);
+ m_internal->offscreenColorTexture = generateColorTexture(context, size);
+}
+
+DrawingBuffer::~DrawingBuffer()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_internal->platformLayer)
+ m_internal->platformLayer->setDrawingBuffer(0);
+#endif
+ m_context->bindFramebuffer(m_framebuffer);
+ m_context->deleteTexture(m_internal->offscreenColorTexture);
+ m_context->deleteFramebuffer(m_framebuffer);
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+void DrawingBuffer::publishToPlatformLayer()
+{
+ if (m_callback)
+ m_callback->willPublish();
+ unsigned parentTexture = m_internal->platformLayer->textureId();
+ // FIXME: We do the copy in the canvas' (child) context so that it executes in the correct order relative to
+ // other commands in the child context. This ensures that the parent texture always contains a complete
+ // frame and not some intermediate result. However, there is no synchronization to ensure that this copy
+ // happens before the compositor draws. This means we might draw stale frames sometimes. Ideally this
+ // would insert a fence into the child command stream that the compositor could wait for.
+ m_context->makeContextCurrent();
+ glCopyTextureToParentTexture(m_internal->offscreenColorTexture, parentTexture);
+ glFlush();
+}
+#endif
+
+void DrawingBuffer::reset(const IntSize& newSize)
+{
+ if (m_size == newSize)
+ return;
+ m_size = newSize;
+
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_internal->offscreenColorTexture);
+ m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_size.width(), m_size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_internal->platformLayer)
+ m_internal->platformLayer->setTextureChanged();
+#endif
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+PlatformLayer* DrawingBuffer::platformLayer()
+{
+ if (!m_internal->platformLayer)
+ m_internal->platformLayer = Canvas2DLayerChromium::create(this, 0);
+ return m_internal->platformLayer.get();
+}
+#endif
+
+unsigned DrawingBuffer::getRenderingResultsAsTexture()
+{
+ return m_internal->offscreenColorTexture;
+}
+
+}
diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index 78b7517..8a77501 100644
--- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -372,6 +372,8 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext,
int numGlyphs,
const FloatPoint& point) const
{
+ graphicsContext->platformContext()->prepareForSoftwareDraw();
+
SkColor color = graphicsContext->platformContext()->effectiveFillColor();
unsigned char alpha = SkColorGetA(color);
// Skip 100% transparent text; no need to draw anything.
diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp
index ec79b82..696cd9c 100644
--- a/WebCore/platform/graphics/chromium/FontLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -65,13 +65,13 @@ static bool isCanvasMultiLayered(SkCanvas* canvas)
return !layerIterator.done();
}
-static void adjustTextRenderMode(SkPaint* paint, bool isCanvasMultiLayered)
+static void adjustTextRenderMode(SkPaint* paint, PlatformContextSkia* skiaContext)
{
// Our layers only have a single alpha channel. This means that subpixel
// rendered text cannot be compositied correctly when the layer is
// collapsed. Therefore, subpixel text is disabled when we are drawing
- // onto a layer.
- if (isCanvasMultiLayered)
+ // onto a layer or when the compositor is being used.
+ if (isCanvasMultiLayered(skiaContext->canvas()) || skiaContext->isDrawingToImageBuffer())
paint->setLCDRenderText(false);
}
@@ -100,16 +100,17 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
y += SkFloatToScalar(adv[i].height());
}
+ gc->platformContext()->prepareForSoftwareDraw();
+
SkCanvas* canvas = gc->platformContext()->canvas();
int textMode = gc->platformContext()->getTextDrawingMode();
- bool haveMultipleLayers = isCanvasMultiLayered(canvas);
// We draw text up to two times (once for fill, once for stroke).
if (textMode & cTextFill) {
SkPaint paint;
gc->platformContext()->setupPaintForFilling(&paint);
font->platformData().setupPaint(&paint);
- adjustTextRenderMode(&paint, haveMultipleLayers);
+ adjustTextRenderMode(&paint, gc->platformContext());
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setColor(gc->fillColor().rgb());
canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
@@ -122,7 +123,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
SkPaint paint;
gc->platformContext()->setupPaintForStroking(&paint, 0, 0);
font->platformData().setupPaint(&paint);
- adjustTextRenderMode(&paint, haveMultipleLayers);
+ adjustTextRenderMode(&paint, gc->platformContext());
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setColor(gc->strokeColor().rgb());
@@ -499,7 +500,11 @@ private:
// We overflowed our arrays. Resize and retry.
// HB_ShapeItem fills in m_item.num_glyphs with the needed size.
deleteGlyphArrays();
- createGlyphArrays(m_item.num_glyphs);
+ // The |+ 1| here is a workaround for a bug in Harfbuzz: the Khmer
+ // shaper (at least) can fail because of insufficient glyph buffers
+ // and request 0 additional glyphs: throwing us into an infinite
+ // loop.
+ createGlyphArrays(m_item.num_glyphs + 1);
}
}
@@ -522,8 +527,11 @@ private:
m_xPositions[i] = m_offsetX + position + offsetX;
double advance = truncateFixedPointToInteger(m_item.advances[i]);
- unsigned glyphIndex = m_item.item.pos + logClustersIndex;
- if (isWordBreak(glyphIndex, isRTL)) {
+ // The first half of the conjuction works around the case where
+ // output glyphs aren't associated with any codepoints by the
+ // clusters log.
+ if (logClustersIndex < m_item.item.length
+ && isWordBreak(m_item.item.pos + logClustersIndex, isRTL)) {
advance += m_wordSpacingAdjustment;
if (m_padding > 0) {
@@ -547,7 +555,7 @@ private:
while (logClustersIndex > 0 && logClusters()[logClustersIndex] == i)
logClustersIndex--;
} else {
- while (logClustersIndex < m_item.num_glyphs && logClusters()[logClustersIndex] == i)
+ while (logClustersIndex < m_item.item.length && logClusters()[logClustersIndex] == i)
logClustersIndex++;
}
@@ -637,7 +645,6 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
}
TextRunWalker walker(run, point.x(), this);
- bool haveMultipleLayers = isCanvasMultiLayered(canvas);
walker.setWordSpacingAdjustment(wordSpacing());
walker.setLetterSpacingAdjustment(letterSpacing());
walker.setPadding(run.padding());
@@ -645,13 +652,13 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
while (walker.nextScriptRun()) {
if (fill) {
walker.fontPlatformDataForScriptRun()->setupPaint(&fillPaint);
- adjustTextRenderMode(&fillPaint, haveMultipleLayers);
+ adjustTextRenderMode(&fillPaint, gc->platformContext());
canvas->drawPosTextH(walker.glyphs(), walker.length() << 1, walker.xPositions(), point.y(), fillPaint);
}
if (stroke) {
walker.fontPlatformDataForScriptRun()->setupPaint(&strokePaint);
- adjustTextRenderMode(&strokePaint, haveMultipleLayers);
+ adjustTextRenderMode(&strokePaint, gc->platformContext());
canvas->drawPosTextH(walker.glyphs(), walker.length() << 1, walker.xPositions(), point.y(), strokePaint);
}
}
diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
index 82d4c0b..46aecf4 100644
--- a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
+++ b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
@@ -32,10 +32,12 @@
#include "GLES2Canvas.h"
+#include "DrawingBuffer.h"
#include "FloatRect.h"
#include "GraphicsContext3D.h"
#include "IntRect.h"
#include "PlatformString.h"
+#include "SharedGraphicsContext3D.h"
#include "SolidFillShader.h"
#include "TexShader.h"
#include "Texture.h"
@@ -61,37 +63,35 @@ struct GLES2Canvas::State {
AffineTransform m_ctm;
};
-GLES2Canvas::GLES2Canvas(GraphicsContext3D* context, const IntSize& size)
- : m_context(context)
+GLES2Canvas::GLES2Canvas(SharedGraphicsContext3D* context, DrawingBuffer* drawingBuffer, const IntSize& size)
+ : m_size(size)
+ , m_context(context)
+ , m_drawingBuffer(drawingBuffer)
, m_state(0)
- , m_quadVertices(0)
- , m_solidFillShader(SolidFillShader::create(context))
- , m_texShader(TexShader::create(context))
{
m_flipMatrix.translate(-1.0f, 1.0f);
m_flipMatrix.scale(2.0f / size.width(), -2.0f / size.height());
- m_context->reshape(size.width(), size.height());
- m_context->viewport(0, 0, size.width(), size.height());
-
m_stateStack.append(State());
m_state = &m_stateStack.last();
-
- // Force the source over composite mode to be applied.
- m_lastCompositeOp = CompositeClear;
- applyCompositeOperator(CompositeSourceOver);
}
GLES2Canvas::~GLES2Canvas()
{
- m_context->deleteBuffer(m_quadVertices);
+}
+
+void GLES2Canvas::bindFramebuffer()
+{
+ m_drawingBuffer->bind();
}
void GLES2Canvas::clearRect(const FloatRect& rect)
{
+ bindFramebuffer();
if (m_state->m_ctm.isIdentity()) {
- m_context->scissor(rect.x(), rect.y(), rect.width(), rect.height());
+ m_context->scissor(rect);
m_context->enable(GraphicsContext3D::SCISSOR_TEST);
+ m_context->clearColor(Color(RGBA32(0)));
m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
m_context->disable(GraphicsContext3D::SCISSOR_TEST);
} else {
@@ -104,16 +104,17 @@ void GLES2Canvas::clearRect(const FloatRect& rect)
void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
- applyCompositeOperator(m_state->m_compositeOp);
-
- m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, getQuadVertices());
+ m_context->applyCompositeOperator(m_state->m_compositeOp);
+ m_context->useQuadVertices();
AffineTransform matrix(m_flipMatrix);
matrix.multLeft(m_state->m_ctm);
matrix.translate(rect.x(), rect.y());
matrix.scale(rect.width(), rect.height());
- m_solidFillShader->use(matrix, color);
+ m_context->useFillSolidProgram(matrix, color);
+
+ bindFramebuffer();
m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4);
}
@@ -165,21 +166,33 @@ void GLES2Canvas::restore()
m_state = &m_stateStack.last();
}
+void GLES2Canvas::drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp)
+{
+ m_context->applyCompositeOperator(compositeOp);
+
+ m_context->useQuadVertices();
+ m_context->setActiveTexture(GraphicsContext3D::TEXTURE0);
+
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture);
+
+ drawQuad(textureSize, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha);
+}
+
void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp)
{
drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp);
}
+
void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp)
{
- applyCompositeOperator(compositeOp);
-
- m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, getQuadVertices());
- checkGLError("glBindBuffer");
-
+ m_context->applyCompositeOperator(compositeOp);
const TilingData& tiles = texture->tiles();
IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect);
+ m_context->useQuadVertices();
+ m_context->setActiveTexture(GraphicsContext3D::TEXTURE0);
+
for (int y = tileIdxRect.y(); y <= tileIdxRect.bottom(); y++) {
for (int x = tileIdxRect.x(); x <= tileIdxRect.right(); x++)
drawTexturedRectTile(texture, tiles.tileIndex(x, y), srcRect, dstRect, transform, alpha);
@@ -193,7 +206,6 @@ void GLES2Canvas::drawTexturedRectTile(Texture* texture, int tile, const FloatRe
const TilingData& tiles = texture->tiles();
- m_context->activeTexture(GraphicsContext3D::TEXTURE0);
texture->bindTile(tile);
FloatRect srcRectClippedInTileSpace;
@@ -202,18 +214,24 @@ void GLES2Canvas::drawTexturedRectTile(Texture* texture, int tile, const FloatRe
IntRect tileBoundsWithBorder = tiles.tileBoundsWithBorder(tile);
+ drawQuad(tileBoundsWithBorder.size(), srcRectClippedInTileSpace, dstRectIntersected, transform, alpha);
+}
+
+void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha)
+{
AffineTransform matrix(m_flipMatrix);
matrix.multLeft(transform);
- matrix.translate(dstRectIntersected.x(), dstRectIntersected.y());
- matrix.scale(dstRectIntersected.width(), dstRectIntersected.height());
+ matrix.translate(dstRect.x(), dstRect.y());
+ matrix.scale(dstRect.width(), dstRect.height());
AffineTransform texMatrix;
- texMatrix.scale(1.0f / tileBoundsWithBorder.width(), 1.0f / tileBoundsWithBorder.height());
- texMatrix.translate(srcRectClippedInTileSpace.x(), srcRectClippedInTileSpace.y());
- texMatrix.scale(srcRectClippedInTileSpace.width(), srcRectClippedInTileSpace.height());
+ texMatrix.scale(1.0f / textureSize.width(), 1.0f / textureSize.height());
+ texMatrix.translate(srcRect.x(), srcRect.y());
+ texMatrix.scale(srcRect.width(), srcRect.height());
- m_texShader->use(matrix, texMatrix, 0, alpha);
+ bindFramebuffer();
+ m_context->useTextureProgram(matrix, texMatrix, alpha);
m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4);
checkGLError("glDrawArrays");
}
@@ -223,98 +241,14 @@ void GLES2Canvas::setCompositeOperation(CompositeOperator op)
m_state->m_compositeOp = op;
}
-void GLES2Canvas::applyCompositeOperator(CompositeOperator op)
-{
- if (op == m_lastCompositeOp)
- return;
-
- switch (op) {
- case CompositeClear:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::ZERO);
- break;
- case CompositeCopy:
- m_context->disable(GraphicsContext3D::BLEND);
- break;
- case CompositeSourceOver:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
- break;
- case CompositeSourceIn:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::DST_ALPHA, GraphicsContext3D::ZERO);
- break;
- case CompositeSourceOut:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ZERO);
- break;
- case CompositeSourceAtop:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::DST_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
- break;
- case CompositeDestinationOver:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ONE);
- break;
- case CompositeDestinationIn:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::SRC_ALPHA);
- break;
- case CompositeDestinationOut:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
- break;
- case CompositeDestinationAtop:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::SRC_ALPHA);
- break;
- case CompositeXOR:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
- break;
- case CompositePlusDarker:
- case CompositeHighlight:
- // unsupported
- m_context->disable(GraphicsContext3D::BLEND);
- break;
- case CompositePlusLighter:
- m_context->enable(GraphicsContext3D::BLEND);
- m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE);
- break;
- }
- m_lastCompositeOp = op;
-}
-
-unsigned GLES2Canvas::getQuadVertices()
-{
- 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 };
- 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);
- }
- return m_quadVertices;
-}
-
Texture* GLES2Canvas::createTexture(NativeImagePtr ptr, Texture::Format format, int width, int height)
{
- PassRefPtr<Texture> texture = m_textures.get(ptr);
- if (texture)
- return texture.get();
-
- texture = Texture::create(m_context, format, width, height);
- Texture* t = texture.get();
- m_textures.set(ptr, texture);
- return t;
+ return m_context->createTexture(ptr, format, width, height);
}
Texture* GLES2Canvas::getTexture(NativeImagePtr ptr)
{
- PassRefPtr<Texture> texture = m_textures.get(ptr);
- return texture ? texture.get() : 0;
+ return m_context->getTexture(ptr);
}
void GLES2Canvas::checkGLError(const char* header)
diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.h b/WebCore/platform/graphics/chromium/GLES2Canvas.h
index f49ac8b..6fc1a0e 100644
--- a/WebCore/platform/graphics/chromium/GLES2Canvas.h
+++ b/WebCore/platform/graphics/chromium/GLES2Canvas.h
@@ -45,16 +45,14 @@
namespace WebCore {
class Color;
+class DrawingBuffer;
class FloatRect;
class GraphicsContext3D;
-class SolidFillShader;
-class TexShader;
-
-typedef HashMap<NativeImagePtr, RefPtr<Texture> > TextureHashMap;
+class SharedGraphicsContext3D;
class GLES2Canvas : public Noncopyable {
public:
- GLES2Canvas(GraphicsContext3D*, const IntSize&);
+ GLES2Canvas(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&);
~GLES2Canvas();
void fillRect(const FloatRect&, const Color&, ColorSpace);
@@ -74,28 +72,33 @@ public:
// non-standard functions
// These are not standard GraphicsContext functions, and should be pushed
// down into a PlatformContextGLES2 at some point.
+ void drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator);
void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator);
void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator);
- GraphicsContext3D* context() { return m_context; }
Texture* createTexture(NativeImagePtr, Texture::Format, int width, int height);
Texture* getTexture(NativeImagePtr);
+ SharedGraphicsContext3D* context() const { return m_context; }
+
+ void bindFramebuffer();
+
+ DrawingBuffer* drawingBuffer() const { return m_drawingBuffer; }
+
private:
void drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
+ void drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
void applyCompositeOperator(CompositeOperator);
void checkGLError(const char* header);
- unsigned getQuadVertices();
- GraphicsContext3D* m_context;
+ IntSize m_size;
+
+ SharedGraphicsContext3D* m_context;
+ DrawingBuffer* m_drawingBuffer;
+
struct State;
WTF::Vector<State> m_stateStack;
State* m_state;
- unsigned m_quadVertices;
- OwnPtr<SolidFillShader> m_solidFillShader;
- OwnPtr<TexShader> m_texShader;
AffineTransform m_flipMatrix;
- TextureHashMap m_textures;
- CompositeOperator m_lastCompositeOp; // This is the one last set, not necessarily the one in the state stack.
};
}
diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
index 648e35f..bbae72a 100644
--- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
@@ -45,7 +45,9 @@
#include "GraphicsLayerChromium.h"
+#include "Canvas2DLayerChromium.h"
#include "ContentLayerChromium.h"
+#include "DrawingBuffer.h"
#include "FloatConversion.h"
#include "FloatRect.h"
#include "Image.h"
@@ -104,6 +106,12 @@ GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
GraphicsLayerChromium::~GraphicsLayerChromium()
{
+ if (m_layer)
+ m_layer->setOwner(0);
+ if (m_contentsLayer)
+ m_contentsLayer->setOwner(0);
+ if (m_transformLayer)
+ m_transformLayer->setOwner(0);
}
void GraphicsLayerChromium::setName(const String& inName)
@@ -290,6 +298,7 @@ void GraphicsLayerChromium::setContentsNeedsDisplay()
if (m_contentsLayer)
m_contentsLayer->setNeedsDisplay();
}
+
void GraphicsLayerChromium::setNeedsDisplay()
{
if (drawsContent())
@@ -344,13 +353,13 @@ void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* platformLayer)
bool childrenChanged = false;
if (platformLayer) {
platformLayer->setOwner(this);
- if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForCanvas) {
+ if (m_contentsLayer.get() != platformLayer) {
setupContentsLayer(platformLayer);
m_contentsLayer = platformLayer;
m_contentsLayerPurpose = ContentsLayerForCanvas;
childrenChanged = true;
}
- platformLayer->setNeedsDisplay();
+ m_contentsLayer->setNeedsDisplay();
updateContentsRect();
} else {
if (m_contentsLayer) {
diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
index 9dff66a..dde443d 100644
--- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
@@ -138,7 +138,7 @@ private:
NoContentsLayer = 0,
ContentsLayerForImage,
ContentsLayerForVideo,
- ContentsLayerForCanvas
+ ContentsLayerForCanvas,
};
ContentsLayerPurpose m_contentsLayerPurpose;
diff --git a/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp b/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp
index 4fd3ba0..59e8122 100644
--- a/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp
+++ b/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp
@@ -38,6 +38,7 @@
#include "SkPath.h"
#include "SkPoint.h"
#include "SkRect.h"
+#include "SkUtils.h"
extern "C" {
#include "harfbuzz-shaper.h"
@@ -61,6 +62,15 @@ static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, hb_u
font->setupPaint(&paint);
paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+
+ unsigned codepoints = 0;
+ for (hb_uint32 i = 0; i < length; i++) {
+ if (!SkUTF16_IsHighSurrogate(characters[i]))
+ codepoints++;
+ if (codepoints > *glyphsSize)
+ return 0;
+ }
+
int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), reinterpret_cast<uint16_t*>(glyphs));
// HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our
diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
index 09b388d..060bb46 100644
--- a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
@@ -108,8 +108,9 @@ void ImageLayerChromium::updateContents()
// completely overwrite its contents with the image below.
// Try to reuse the color space from the image to preserve its colors.
// Some images use a color space (such as indexed) unsupported by the bitmap context.
- RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGImageGetColorSpace(cgImage));
- CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace.get());
+ RetainPtr<CGColorSpaceRef> colorSpaceReleaser;
+ CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage);
+ CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
switch (colorSpaceModel) {
case kCGColorSpaceModelMonochrome:
case kCGColorSpaceModelRGB:
@@ -118,12 +119,13 @@ void ImageLayerChromium::updateContents()
case kCGColorSpaceModelDeviceN:
break;
default:
- colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
+ colorSpaceReleaser.adoptCF(CGColorSpaceCreateDeviceRGB());
+ colorSpace = colorSpaceReleaser.get();
break;
}
RetainPtr<CGContextRef> tempContext(AdoptCF, CGBitmapContextCreate(tempVector.data(),
width, height, 8, tempRowBytes,
- colorSpace.get(),
+ colorSpace,
kCGImageAlphaPremultipliedLast));
CGContextSetBlendMode(tempContext.get(), kCGBlendModeCopy);
CGContextDrawImage(tempContext.get(),
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index 50338d2..4708310 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -34,11 +34,11 @@
#if USE(ACCELERATED_COMPOSITING)
#include "LayerRendererChromium.h"
-#include "CanvasLayerChromium.h"
-#include "ContentLayerChromium.h"
+#include "Canvas2DLayerChromium.h"
#include "GLES2Context.h"
#include "LayerChromium.h"
#include "NotImplemented.h"
+#include "WebGLLayerChromium.h"
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
@@ -77,7 +77,14 @@ static inline bool compareLayerZ(const LayerChromium* a, const LayerChromium* b)
PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(PassOwnPtr<GLES2Context> gles2Context)
{
- return new LayerRendererChromium(gles2Context);
+ if (!gles2Context)
+ return 0;
+
+ OwnPtr<LayerRendererChromium> layerRenderer(new LayerRendererChromium(gles2Context));
+ if (!layerRenderer->hardwareCompositing())
+ return 0;
+
+ return layerRenderer.release();
}
LayerRendererChromium::LayerRendererChromium(PassOwnPtr<GLES2Context> gles2Context)
@@ -91,7 +98,7 @@ LayerRendererChromium::LayerRendererChromium(PassOwnPtr<GLES2Context> gles2Conte
, m_currentShader(0)
, m_gles2Context(gles2Context)
{
- m_hardwareCompositing = (m_gles2Context && initializeSharedObjects());
+ m_hardwareCompositing = initializeSharedObjects();
}
LayerRendererChromium::~LayerRendererChromium()
@@ -118,10 +125,7 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size)
// the old ones.
m_rootLayerCanvas = new skia::PlatformCanvas(size.width(), size.height(), false);
m_rootLayerSkiaContext = new PlatformContextSkia(m_rootLayerCanvas.get());
-#if OS(WINDOWS)
- // FIXME: why is this is a windows-only call ?
m_rootLayerSkiaContext->setDrawingToImageBuffer(true);
-#endif
m_rootLayerGraphicsContext = new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_rootLayerSkiaContext.get()));
#elif PLATFORM(CG)
// Release the previous CGBitmapContext before reallocating the backing store as a precaution.
diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
index 7ff98b9..c0da285 100644
--- a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -96,14 +96,9 @@ void VideoLayerChromium::updateContents()
m_canvas = new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), true);
m_skiaContext = new PlatformContextSkia(m_canvas.get());
-#if OS(WINDOWS)
- // This is needed to get text to show up correctly. Without it,
- // GDI renders with zero alpha and the text becomes invisible.
- // Unfortunately, setting this to true disables cleartype.
+ // This is needed to get text to show up correctly.
// FIXME: Does this take us down a very slow text rendering path?
- // FIXME: Why is this is a windows-only call?
m_skiaContext->setDrawingToImageBuffer(true);
-#endif
m_graphicsContext = new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_skiaContext.get()));
}
diff --git a/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
new file mode 100644
index 0000000..411f416
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "WebGLLayerChromium.h"
+
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+#include <GLES2/gl2.h>
+
+namespace WebCore {
+
+PassRefPtr<WebGLLayerChromium> WebGLLayerChromium::create(GraphicsLayerChromium* owner)
+{
+ return adoptRef(new WebGLLayerChromium(owner));
+}
+
+WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner)
+ : CanvasLayerChromium(owner)
+ , m_context(0)
+{
+}
+
+void WebGLLayerChromium::updateContents()
+{
+ ASSERT(m_context);
+ if (m_textureChanged) {
+ glBindTexture(GL_TEXTURE_2D, m_textureId);
+ // Set the min-mag filters to linear and wrap modes to GL_CLAMP_TO_EDGE
+ // to get around NPOT texture limitations of GLES.
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_textureChanged = false;
+ }
+ // Update the contents of the texture used by the compositor.
+ if (m_contentsDirty) {
+ m_context->prepareTexture();
+ m_contentsDirty = false;
+ }
+}
+
+void WebGLLayerChromium::setContext(const GraphicsContext3D* context)
+{
+ m_context = const_cast<GraphicsContext3D*>(context);
+
+ unsigned int textureId = m_context->platformTexture();
+ if (textureId != m_textureId)
+ m_textureChanged = true;
+ m_textureId = textureId;
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
new file mode 100644
index 0000000..11b8db7
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef WebGLLayerChromium_h
+#define WebGLLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "CanvasLayerChromium.h"
+
+namespace WebCore {
+
+class GraphicsContext3D;
+
+// A Layer containing a WebGL canvas
+class WebGLLayerChromium : public CanvasLayerChromium {
+public:
+ static PassRefPtr<WebGLLayerChromium> create(GraphicsLayerChromium* owner = 0);
+ virtual bool drawsContent() { return m_context; }
+ virtual void updateContents();
+
+ void setContext(const GraphicsContext3D* context);
+
+private:
+ explicit WebGLLayerChromium(GraphicsLayerChromium* owner);
+ GraphicsContext3D* m_context;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
new file mode 100644
index 0000000..dc80954
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "DrawingBuffer.h"
+
+#include "GraphicsContext3D.h"
+#include "SharedGraphicsContext3D.h"
+
+namespace WebCore {
+
+PassOwnPtr<DrawingBuffer> DrawingBuffer::create(SharedGraphicsContext3D* context, const IntSize& size)
+{
+ unsigned framebuffer = context->createFramebuffer();
+ ASSERT(framebuffer);
+ if (!framebuffer)
+ return 0;
+ return adoptPtr(new DrawingBuffer(context, size, framebuffer));
+}
+
+void DrawingBuffer::bind()
+{
+ m_context->bindFramebuffer(m_framebuffer);
+ m_context->setViewport(m_size);
+}
+
+void DrawingBuffer::setWillPublishCallback(PassOwnPtr<WillPublishCallback> callback)
+{
+ m_callback = callback;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/gpu/DrawingBuffer.h b/WebCore/platform/graphics/gpu/DrawingBuffer.h
new file mode 100644
index 0000000..23e6f4a
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/DrawingBuffer.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DrawingBuffer_h
+#define DrawingBuffer_h
+
+#include "GraphicsLayer.h"
+#include "IntSize.h"
+
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class SharedGraphicsContext3D;
+
+struct DrawingBufferInternal;
+
+// Manages a rendering target (framebuffer + attachment) for a canvas. Can publish its rendering
+// results to a PlatformLayer for compositing.
+class DrawingBuffer : public Noncopyable {
+public:
+ static PassOwnPtr<DrawingBuffer> create(SharedGraphicsContext3D*, const IntSize&);
+ ~DrawingBuffer();
+
+ void reset(const IntSize&);
+ void bind();
+ IntSize size() const { return m_size; }
+
+#if USE(ACCELERATED_COMPOSITING)
+ PlatformLayer* platformLayer();
+ void publishToPlatformLayer();
+#endif
+
+ unsigned getRenderingResultsAsTexture();
+
+ class WillPublishCallback : public Noncopyable {
+ public:
+ virtual void willPublish() = 0;
+ };
+
+ void setWillPublishCallback(PassOwnPtr<WillPublishCallback>);
+private:
+ DrawingBuffer(SharedGraphicsContext3D*, const IntSize&, unsigned framebuffer);
+
+ SharedGraphicsContext3D* m_context;
+ IntSize m_size;
+ unsigned m_framebuffer;
+
+ OwnPtr<WillPublishCallback> m_callback;
+ OwnPtr<DrawingBufferInternal> m_internal;
+};
+
+} // namespace WebCore
+
+#endif // DrawingBuffer_h
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnClassifier.cpp b/WebCore/platform/graphics/gpu/LoopBlinnClassifier.cpp
new file mode 100644
index 0000000..e43dc37
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/LoopBlinnClassifier.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "LoopBlinnClassifier.h"
+
+#include "LoopBlinnMathUtils.h"
+
+namespace WebCore {
+
+using LoopBlinnMathUtils::approxEqual;
+using LoopBlinnMathUtils::roundToZero;
+
+LoopBlinnClassifier::Result LoopBlinnClassifier::classify(const FloatPoint& c0,
+ const FloatPoint& c1,
+ const FloatPoint& c2,
+ const FloatPoint& c3)
+{
+ // Consult the chapter for the definitions of the following
+ // (terse) variable names. Note that the b0..b3 coordinates are
+ // homogeneous, so the "z" value (actually the w coordinate) must
+ // be 1.0.
+ FloatPoint3D b0(c0.x(), c0.y(), 1.0f);
+ FloatPoint3D b1(c1.x(), c1.y(), 1.0f);
+ FloatPoint3D b2(c2.x(), c2.y(), 1.0f);
+ FloatPoint3D b3(c3.x(), c3.y(), 1.0f);
+
+ // Compute a1..a3.
+ float a1 = b0 * b3.cross(b2);
+ float a2 = b1 * b0.cross(b3);
+ float a3 = b2 * b1.cross(b0);
+
+ // Compute d1..d3.
+ float d1 = a1 - 2 * a2 + 3 * a3;
+ float d2 = -a2 + 3 * a3;
+ float d3 = 3 * a3;
+
+ // Experimentation has shown that the texture coordinates computed
+ // from these values quickly become huge, leading to roundoff errors
+ // and artifacts in the shader. It turns out that if we normalize
+ // the vector defined by (d1, d2, d3), this fixes the problem of the
+ // texture coordinates getting too large without affecting the
+ // classification results.
+ FloatPoint3D nd(d1, d2, d3);
+ nd.normalize();
+ d1 = nd.x();
+ d2 = nd.y();
+ d3 = nd.z();
+
+ // Compute the discriminant.
+ // term0 is a common term in the computation which helps decide
+ // which way to classify the cusp case: as serpentine or loop.
+ float term0 = (3 * d2 * d2 - 4 * d1 * d3);
+ float discriminant = d1 * d1 * term0;
+
+ // Experimentation has also shown that when the classification is
+ // near the boundary between one curve type and another, the shader
+ // becomes numerically unstable, particularly with the cusp case.
+ // Correct for this by rounding d1..d3 and the discriminant to zero
+ // when they get near it.
+ d1 = roundToZero(d1);
+ d2 = roundToZero(d2);
+ d3 = roundToZero(d3);
+ discriminant = roundToZero(discriminant);
+
+ // Do the classification.
+ if (approxEqual(b0, b1) && approxEqual(b0, b2) && approxEqual(b0, b3))
+ return Result(kPoint, d1, d2, d3);
+
+ if (!discriminant) {
+ if (!d1 && !d2) {
+ if (!d3)
+ return Result(kLine, d1, d2, d3);
+ return Result(kQuadratic, d1, d2, d3);
+ }
+
+ if (!d1)
+ return Result(kCusp, d1, d2, d3);
+
+ // This is the boundary case described in Loop and Blinn's
+ // SIGGRAPH '05 paper of a cusp with inflection at infinity.
+ // Because term0 might not be exactly 0, we decide between using
+ // the serpentine and loop cases depending on its sign to avoid
+ // taking the square root of a negative number when computing the
+ // cubic texture coordinates.
+ if (term0 < 0)
+ return Result(kLoop, d1, d2, d3);
+
+ return Result(kSerpentine, d1, d2, d3);
+ }
+
+ if (discriminant > 0)
+ return Result(kSerpentine, d1, d2, d3);
+
+ // discriminant < 0
+ return Result(kLoop, d1, d2, d3);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnClassifier.h b/WebCore/platform/graphics/gpu/LoopBlinnClassifier.h
new file mode 100644
index 0000000..c665844
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/LoopBlinnClassifier.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Cubic curve classification algorithm from "Rendering Vector Art on
+// the GPU" by Loop and Blinn, GPU Gems 3, Chapter 25:
+// http://http.developer.nvidia.com/GPUGems3/gpugems3_ch25.html .
+
+#ifndef LoopBlinnClassifier_h
+#define LoopBlinnClassifier_h
+
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class FloatPoint;
+
+// Classifies cubic curves into specific types.
+class LoopBlinnClassifier : public Noncopyable {
+public:
+ // The types of cubic curves.
+ enum CurveType {
+ kSerpentine,
+ kCusp,
+ kLoop,
+ kQuadratic,
+ kLine,
+ kPoint
+ };
+
+ // The result of the classifier.
+ struct Result {
+ public:
+ Result(CurveType inputCurveType, float inputD1, float inputD2, float inputD3)
+ : curveType(inputCurveType)
+ , d1(inputD1)
+ , d2(inputD2)
+ , d3(inputD3) { }
+
+ CurveType curveType;
+
+ // These are coefficients used later in the computation of
+ // texture coordinates per vertex.
+ float d1;
+ float d2;
+ float d3;
+ };
+
+ // Classifies the given cubic bezier curve starting at c0, ending
+ // at c3, and affected by control points c1 and c2.
+ static Result classify(const FloatPoint& c0,
+ const FloatPoint& c1,
+ const FloatPoint& c2,
+ const FloatPoint& c3);
+
+private:
+ // This class does not need to be instantiated.
+ LoopBlinnClassifier() { }
+};
+
+} // namespace WebCore
+
+#endif // LoopBlinnClassifier_h
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnConstants.h b/WebCore/platform/graphics/gpu/LoopBlinnConstants.h
new file mode 100644
index 0000000..1997d9f
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/LoopBlinnConstants.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LoopBlinnConstants_h
+#define LoopBlinnConstants_h
+
+namespace WebCore {
+namespace LoopBlinnConstants {
+
+enum FillSide {
+ LeftSide,
+ RightSide
+};
+
+} // namespace LoopBlinnConstants
+} // namespace WebCore
+
+#endif // LoopBlinnConstants_h
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp b/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp
new file mode 100644
index 0000000..61ebc9b
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "LoopBlinnMathUtils.h"
+
+#include "FloatPoint.h"
+#include "MathExtras.h"
+#include <algorithm>
+#include <string.h> // for memcpy
+
+namespace WebCore {
+namespace LoopBlinnMathUtils {
+
+namespace {
+
+// Utility functions local to this file.
+int orientation(const FloatPoint& p1,
+ const FloatPoint& p2,
+ const FloatPoint& p3)
+{
+ float crossProduct = (p2.y() - p1.y()) * (p3.x() - p2.x()) - (p3.y() - p2.y()) * (p2.x() - p1.x());
+ return (crossProduct < 0.0f) ? -1 : ((crossProduct > 0.0f) ? 1 : 0);
+}
+
+bool edgeEdgeTest(const FloatSize& v0Delta,
+ const FloatPoint& v0,
+ const FloatPoint& u0,
+ const FloatPoint& u1)
+{
+ // This edge to edge test is based on Franlin Antonio's gem: "Faster
+ // Line Segment Intersection", in Graphics Gems III, pp. 199-202.
+ float ax = v0Delta.width();
+ float ay = v0Delta.height();
+ float bx = u0.x() - u1.x();
+ float by = u0.y() - u1.y();
+ float cx = v0.x() - u0.x();
+ float cy = v0.y() - u0.y();
+ float f = ay * bx - ax * by;
+ float d = by * cx - bx * cy;
+ if ((f > 0 && d >= 0 && d <= f) || (f < 0 && d <= 0 && d >= f)) {
+ float e = ax * cy - ay * cx;
+
+ // This additional test avoids reporting coincident edges, which
+ // is the behavior we want.
+ if (approxEqual(e, 0) || approxEqual(f, 0) || approxEqual(e, f))
+ return false;
+
+ if (f > 0)
+ return e >= 0 && e <= f;
+
+ return e <= 0 && e >= f;
+ }
+ return false;
+}
+
+bool edgeAgainstTriangleEdges(const FloatPoint& v0,
+ const FloatPoint& v1,
+ const FloatPoint& u0,
+ const FloatPoint& u1,
+ const FloatPoint& u2)
+{
+ FloatSize delta = v1 - v0;
+ // Test edge u0, u1 against v0, v1.
+ if (edgeEdgeTest(delta, v0, u0, u1))
+ return true;
+ // Test edge u1, u2 against v0, v1.
+ if (edgeEdgeTest(delta, v0, u1, u2))
+ return true;
+ // Test edge u2, u1 against v0, v1.
+ if (edgeEdgeTest(delta, v0, u2, u0))
+ return true;
+ return false;
+}
+
+// A roundoff factor in the cubic classification and texture coordinate
+// generation algorithms. It primarily determines the handling of corner
+// cases during the classification process. Be careful when adjusting it;
+// it has been determined empirically to work well. When changing it, you
+// should look in particular at shapes that contain quadratic curves and
+// ensure they still look smooth. Once pixel tests are running against this
+// algorithm, they should provide sufficient coverage to ensure that
+// adjusting the constant won't break anything.
+const float Epsilon = 5.0e-4f;
+
+} // anonymous namespace
+
+// Exported routines
+
+float roundToZero(float val)
+{
+ if (val < Epsilon && val > -Epsilon)
+ return 0;
+ return val;
+}
+
+bool approxEqual(const FloatPoint& v0, const FloatPoint& v1)
+{
+ return (v0 - v1).diagonalLengthSquared() < Epsilon * Epsilon;
+}
+
+bool approxEqual(const FloatPoint3D& v0, const FloatPoint3D& v1)
+{
+ return (v0 - v1).lengthSquared() < Epsilon * Epsilon;
+}
+
+bool approxEqual(float f0, float f1)
+{
+ return fabsf(f0 - f1) < Epsilon;
+}
+
+bool linesIntersect(const FloatPoint& p1,
+ const FloatPoint& q1,
+ const FloatPoint& p2,
+ const FloatPoint& q2)
+{
+ return (orientation(p1, q1, p2) != orientation(p1, q1, q2)
+ && orientation(p2, q2, p1) != orientation(p2, q2, q1));
+}
+
+bool pointInTriangle(const FloatPoint& point,
+ const FloatPoint& a,
+ const FloatPoint& b,
+ const FloatPoint& c)
+{
+ // Algorithm from http://www.blackpawn.com/texts/pointinpoly/default.html
+ float x0 = c.x() - a.x();
+ float y0 = c.y() - a.y();
+ float x1 = b.x() - a.x();
+ float y1 = b.y() - a.y();
+ float x2 = point.x() - a.x();
+ float y2 = point.y() - a.y();
+
+ float dot00 = x0 * x0 + y0 * y0;
+ float dot01 = x0 * x1 + y0 * y1;
+ float dot02 = x0 * x2 + y0 * y2;
+ float dot11 = x1 * x1 + y1 * y1;
+ float dot12 = x1 * x2 + y1 * y2;
+ float denominator = dot00 * dot11 - dot01 * dot01;
+ if (!denominator)
+ // Triangle is zero-area. Treat query point as not being inside.
+ return false;
+ // Compute
+ float inverseDenominator = 1.0f / denominator;
+ float u = (dot11 * dot02 - dot01 * dot12) * inverseDenominator;
+ float v = (dot00 * dot12 - dot01 * dot02) * inverseDenominator;
+
+ return (u > 0.0f) && (v > 0.0f) && (u + v < 1.0f);
+}
+
+bool trianglesOverlap(const FloatPoint& a1,
+ const FloatPoint& b1,
+ const FloatPoint& c1,
+ const FloatPoint& a2,
+ const FloatPoint& b2,
+ const FloatPoint& c2)
+{
+ // Derived from coplanar_tri_tri() at
+ // http://jgt.akpeters.com/papers/ShenHengTang03/tri_tri.html ,
+ // simplified for the 2D case and modified so that overlapping edges
+ // do not report overlapping triangles.
+
+ // Test all edges of triangle 1 against the edges of triangle 2.
+ if (edgeAgainstTriangleEdges(a1, b1, a2, b2, c2)
+ || edgeAgainstTriangleEdges(b1, c1, a2, b2, c2)
+ || edgeAgainstTriangleEdges(c1, a1, a2, b2, c2))
+ return true;
+ // Finally, test if tri1 is totally contained in tri2 or vice versa.
+ // The paper above only performs the first two point-in-triangle tests.
+ // Because we define that triangles sharing a vertex or edge don't
+ // overlap, we must perform additional tests to see whether one
+ // triangle is contained in the other.
+ if (pointInTriangle(a1, a2, b2, c2)
+ || pointInTriangle(a2, a1, b1, c1)
+ || pointInTriangle(b1, a2, b2, c2)
+ || pointInTriangle(b2, a1, b1, c1)
+ || pointInTriangle(c1, a2, b2, c2)
+ || pointInTriangle(c2, a1, b1, c1))
+ return true;
+ return false;
+}
+
+namespace {
+
+// Helper routines for public XRay queries below. All of this code
+// originated in Skia; see include/core/ and src/core/, SkScalar.h and
+// SkGeometry.{cpp,h}.
+
+const float NearlyZeroConstant = (1.0f / (1 << 12));
+
+bool nearlyZero(float x, float tolerance = NearlyZeroConstant)
+{
+ ASSERT(tolerance > 0.0f);
+ return ::fabsf(x) < tolerance;
+}
+
+// Linearly interpolate between a and b, based on t.
+// If t is 0, return a; if t is 1, return b; else interpolate.
+// t must be [0..1].
+float interpolate(float a, float b, float t)
+{
+ ASSERT(t >= 0 && t <= 1);
+ return a + (b - a) * t;
+}
+
+float evaluateCubic(float controlPoint0, float controlPoint1, float controlPoint2, float controlPoint3, float t)
+{
+ ASSERT(t >= 0 && t <= 1);
+
+ if (!t)
+ return controlPoint0;
+
+ float ab = interpolate(controlPoint0, controlPoint1, t);
+ float bc = interpolate(controlPoint1, controlPoint2, t);
+ float cd = interpolate(controlPoint2, controlPoint3, t);
+ float abc = interpolate(ab, bc, t);
+ float bcd = interpolate(bc, cd, t);
+ return interpolate(abc, bcd, t);
+}
+
+// Evaluates the point on the source cubic specified by t, 0 <= t <= 1.0.
+FloatPoint evaluateCubicAt(const FloatPoint cubic[4], float t)
+{
+ return FloatPoint(evaluateCubic(cubic[0].x(), cubic[1].x(), cubic[2].x(), cubic[3].x(), t),
+ evaluateCubic(cubic[0].y(), cubic[1].y(), cubic[2].y(), cubic[3].y(), t));
+}
+
+bool xRayCrossesMonotonicCubic(const XRay& xRay, const FloatPoint cubic[4], bool& ambiguous)
+{
+ ambiguous = false;
+
+ // Find the minimum and maximum y of the extrema, which are the
+ // first and last points since this cubic is monotonic
+ float minY = std::min(cubic[0].y(), cubic[3].y());
+ float maxY = std::max(cubic[0].y(), cubic[3].y());
+
+ if (xRay.y() == cubic[0].y()
+ || xRay.y() < minY
+ || xRay.y() > maxY) {
+ // The query line definitely does not cross the curve
+ ambiguous = (xRay.y() == cubic[0].y());
+ return false;
+ }
+
+ const bool pointAtExtremum = (xRay.y() == cubic[3].y());
+
+ float minX = std::min(std::min(std::min(cubic[0].x(), cubic[1].x()),
+ cubic[2].x()),
+ cubic[3].x());
+ if (xRay.x() < minX) {
+ // The query line definitely crosses the curve
+ ambiguous = pointAtExtremum;
+ return true;
+ }
+
+ float maxX = std::max(std::max(std::max(cubic[0].x(), cubic[1].x()),
+ cubic[2].x()),
+ cubic[3].x());
+ if (xRay.x() > maxX)
+ // The query line definitely does not cross the curve
+ return false;
+
+ // Do a binary search to find the parameter value which makes y as
+ // close as possible to the query point. See whether the query
+ // line's origin is to the left of the associated x coordinate.
+
+ // MaxIterations is chosen as the number of mantissa bits for a float,
+ // since there's no way we are going to get more precision by
+ // iterating more times than that.
+ const int MaxIterations = 23;
+ FloatPoint evaluatedPoint;
+ int iter = 0;
+ float upperT;
+ float lowerT;
+ // Need to invert direction of t parameter if cubic goes up
+ // instead of down
+ if (cubic[3].y() > cubic[0].y()) {
+ upperT = 1;
+ lowerT = 0;
+ } else {
+ upperT = 0;
+ lowerT = 1;
+ }
+ do {
+ float t = 0.5f * (upperT + lowerT);
+ evaluatedPoint = evaluateCubicAt(cubic, t);
+ if (xRay.y() > evaluatedPoint.y())
+ lowerT = t;
+ else
+ upperT = t;
+ } while (++iter < MaxIterations && !nearlyZero(evaluatedPoint.y() - xRay.y()));
+
+ // FIXME: once we have more regression tests for this code,
+ // determine whether this should be using a fuzzy test.
+ if (xRay.x() <= evaluatedPoint.x()) {
+ ambiguous = pointAtExtremum;
+ return true;
+ }
+ return false;
+}
+
+// Divides the numerator by the denominator safely for the case where
+// the result must lie in the range (0..1). Result indicates whether
+// the result is valid.
+bool safeUnitDivide(float numerator, float denominator, float& ratio)
+{
+ if (numerator < 0) {
+ // Make the "numerator >= denominator" check below work.
+ numerator = -numerator;
+ denominator = -denominator;
+ }
+ if (!numerator || !denominator || numerator >= denominator)
+ return false;
+ float r = numerator / denominator;
+ if (isnan(r))
+ return false;
+ ASSERT(r >= 0 && r < 1);
+ if (!r) // catch underflow if numerator <<<< denominator
+ return false;
+ ratio = r;
+ return true;
+}
+
+// From Numerical Recipes in C.
+//
+// q = -1/2 (b + sign(b) sqrt[b*b - 4*a*c])
+// x1 = q / a
+// x2 = c / q
+//
+// Returns the number of real roots of the equation [0..2]. Roots are
+// returned in sorted order, smaller root first.
+int findUnitQuadRoots(float a, float b, float c, float roots[2])
+{
+ if (!a)
+ return safeUnitDivide(-c, b, roots[0]) ? 1 : 0;
+
+ float discriminant = b*b - 4*a*c;
+ if (discriminant < 0 || isnan(discriminant)) // complex roots
+ return 0;
+ discriminant = sqrtf(discriminant);
+
+ float q = (b < 0) ? -(b - discriminant) / 2 : -(b + discriminant) / 2;
+ int numberOfRoots = 0;
+ if (safeUnitDivide(q, a, roots[numberOfRoots]))
+ ++numberOfRoots;
+ if (safeUnitDivide(c, q, roots[numberOfRoots]))
+ ++numberOfRoots;
+ if (numberOfRoots == 2) {
+ // Seemingly have two roots. Check for equality and sort.
+ if (roots[0] == roots[1])
+ return 1;
+ if (roots[0] > roots[1])
+ std::swap(roots[0], roots[1]);
+ }
+ return numberOfRoots;
+}
+
+// Cubic'(t) = pt^2 + qt + r, where
+// p = 3(-a + 3(b - c) + d)
+// q = 6(a - 2b + c)
+// r = 3(b - a)
+// Solve for t, keeping only those that fit between 0 < t < 1.
+int findCubicExtrema(float a, float b, float c, float d, float tValues[2])
+{
+ // Divide p, q, and r by 3 to simplify the equations.
+ float p = d - a + 3*(b - c);
+ float q = 2*(a - b - b + c);
+ float r = b - a;
+
+ return findUnitQuadRoots(p, q, r, tValues);
+}
+
+void interpolateCubicCoords(float controlPoint0, float controlPoint1, float controlPoint2, float controlPoint3, float* dst, float t)
+{
+ float ab = interpolate(controlPoint0, controlPoint1, t);
+ float bc = interpolate(controlPoint1, controlPoint2, t);
+ float cd = interpolate(controlPoint2, controlPoint3, t);
+ float abc = interpolate(ab, bc, t);
+ float bcd = interpolate(bc, cd, t);
+ float abcd = interpolate(abc, bcd, t);
+
+ dst[0] = controlPoint0;
+ dst[2] = ab;
+ dst[4] = abc;
+ dst[6] = abcd;
+ dst[8] = bcd;
+ dst[10] = cd;
+ dst[12] = controlPoint3;
+}
+
+#ifndef NDEBUG
+bool isUnitInterval(float x)
+{
+ return x > 0 && x < 1;
+}
+#endif
+
+void chopCubicAtTValues(const FloatPoint src[4], FloatPoint dst[], const float tValues[], int roots)
+{
+#ifndef NDEBUG
+ for (int i = 0; i < roots - 1; ++i) {
+ ASSERT(isUnitInterval(tValues[i]));
+ ASSERT(isUnitInterval(tValues[i+1]));
+ ASSERT(tValues[i] < tValues[i+1]);
+ }
+#endif
+
+ if (!roots) {
+ // nothing to chop
+ for (int j = 0; j < 4; ++j)
+ dst[j] = src[j];
+ return;
+ }
+
+ float t = tValues[0];
+ FloatPoint tmp[4];
+ for (int j = 0; j < 4; ++j)
+ tmp[j] = src[j];
+
+ for (int i = 0; i < roots; ++i) {
+ chopCubicAt(tmp, dst, t);
+ if (i == roots - 1)
+ break;
+
+ dst += 3;
+ // Make tmp contain the remaining cubic (after the first chop).
+ for (int j = 0; j < 4; ++j)
+ tmp[j] = dst[j];
+
+ // Watch out for the case that the renormalized t isn't in range.
+ if (!safeUnitDivide(tValues[i+1] - tValues[i], 1.0f - tValues[i], t)) {
+ // If it isn't, just create a degenerate cubic.
+ dst[4] = dst[5] = dst[6] = tmp[3];
+ break;
+ }
+ }
+}
+
+void flattenDoubleCubicYExtrema(FloatPoint coords[7])
+{
+ coords[2].setY(coords[3].y());
+ coords[4].setY(coords[3].y());
+}
+
+int chopCubicAtYExtrema(const FloatPoint src[4], FloatPoint dst[10])
+{
+ float tValues[2];
+ int roots = findCubicExtrema(src[0].y(), src[1].y(), src[2].y(), src[3].y(), tValues);
+
+ chopCubicAtTValues(src, dst, tValues, roots);
+ if (roots) {
+ // we do some cleanup to ensure our Y extrema are flat
+ flattenDoubleCubicYExtrema(&dst[0]);
+ if (roots == 2)
+ flattenDoubleCubicYExtrema(&dst[3]);
+ }
+ return roots;
+}
+
+} // anonymous namespace
+
+// Public cubic operations.
+
+void chopCubicAt(const FloatPoint src[4], FloatPoint dst[7], float t)
+{
+ ASSERT(t >= 0 && t <= 1);
+
+ float output[14];
+ interpolateCubicCoords(src[0].x(), src[1].x(), src[2].x(), src[3].x(), &output[0], t);
+ interpolateCubicCoords(src[0].y(), src[1].y(), src[2].y(), src[3].y(), &output[1], t);
+ for (int i = 0; i < 7; i++)
+ dst[i].set(output[2 * i], output[2 * i + 1]);
+}
+
+// Public XRay queries.
+
+bool xRayCrossesLine(const XRay& xRay, const FloatPoint pts[2], bool& ambiguous)
+{
+ ambiguous = false;
+
+ // Determine quick discards.
+ // Consider query line going exactly through point 0 to not
+ // intersect, for symmetry with xRayCrossesMonotonicCubic.
+ if (xRay.y() == pts[0].y()) {
+ ambiguous = true;
+ return false;
+ }
+ if (xRay.y() < pts[0].y() && xRay.y() < pts[1].y())
+ return false;
+ if (xRay.y() > pts[0].y() && xRay.y() > pts[1].y())
+ return false;
+ if (xRay.x() > pts[0].x() && xRay.x() > pts[1].x())
+ return false;
+ // Determine degenerate cases
+ if (nearlyZero(pts[0].y() - pts[1].y()))
+ return false;
+ if (nearlyZero(pts[0].x() - pts[1].x())) {
+ // We've already determined the query point lies within the
+ // vertical range of the line segment.
+ if (xRay.x() <= pts[0].x()) {
+ ambiguous = (xRay.y() == pts[1].y());
+ return true;
+ }
+ return false;
+ }
+ // Ambiguity check
+ if (xRay.y() == pts[1].y()) {
+ if (xRay.x() <= pts[1].x()) {
+ ambiguous = true;
+ return true;
+ }
+ return false;
+ }
+ // Full line segment evaluation
+ float deltaY = pts[1].y() - pts[0].y();
+ float deltaX = pts[1].x() - pts[0].x();
+ float slope = deltaY / deltaX;
+ float b = pts[0].y() - slope * pts[0].x();
+ // Solve for x coordinate at y = xRay.y()
+ float x = (xRay.y() - b) / slope;
+ return xRay.x() <= x;
+}
+
+int numXRayCrossingsForCubic(const XRay& xRay, const FloatPoint cubic[4], bool& ambiguous)
+{
+ int numCrossings = 0;
+ FloatPoint monotonicCubics[10];
+ int numMonotonicCubics = 1 + chopCubicAtYExtrema(cubic, monotonicCubics);
+ ambiguous = false;
+ FloatPoint* monotonicCubicsPointer = &monotonicCubics[0];
+ for (int i = 0; i < numMonotonicCubics; ++i) {
+ if (xRayCrossesMonotonicCubic(xRay, monotonicCubicsPointer, ambiguous))
+ ++numCrossings;
+ if (ambiguous)
+ return 0;
+ monotonicCubicsPointer += 3;
+ }
+ return numCrossings;
+}
+
+} // namespace LoopBlinnMathUtils
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.h b/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.h
new file mode 100644
index 0000000..b9d19c5
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LoopBlinnMathUtils_h
+#define LoopBlinnMathUtils_h
+
+#include "FloatPoint.h"
+#include "FloatPoint3D.h"
+#include <math.h>
+
+namespace WebCore {
+
+// Use a namespace for these so we can easily import them.
+namespace LoopBlinnMathUtils {
+
+float roundToZero(float val);
+bool approxEqual(const FloatPoint& v0, const FloatPoint& v1);
+bool approxEqual(const FloatPoint3D& v0, const FloatPoint3D& v1);
+bool approxEqual(float f0, float f1);
+
+// Determines whether the line segment between (p1, q1) intersects
+// that between (p2, q2).
+bool linesIntersect(const FloatPoint& p1,
+ const FloatPoint& q1,
+ const FloatPoint& p2,
+ const FloatPoint& q2);
+
+// Determines whether "point" is inside the 2D triangle defined by
+// vertices a, b, and c. This test defines that points exactly on an
+// edge are not considered to be inside the triangle.
+bool pointInTriangle(const FloatPoint& point,
+ const FloatPoint& a,
+ const FloatPoint& b,
+ const FloatPoint& c);
+
+// Determines whether the triangles defined by the points (a1, b1, c1)
+// and (a2, b2, c2) overlap. The definition of this function is that
+// if the two triangles only share an adjacent edge or vertex, they
+// are not considered to overlap.
+bool trianglesOverlap(const FloatPoint& a1,
+ const FloatPoint& b1,
+ const FloatPoint& c1,
+ const FloatPoint& a2,
+ const FloatPoint& b2,
+ const FloatPoint& c2);
+
+// Given a src cubic bezier, chops it at the specified t value,
+// where 0 < t < 1, and returns the two new cubics in dst[0..3]
+// and dst[3..6].
+void chopCubicAt(const FloatPoint src[4], FloatPoint dst[7], float t);
+
+// "X-Ray" queries. An XRay is a half-line originating at the given
+// point and extending to x=+infinity.
+typedef FloatPoint XRay;
+
+// Given an arbitrary cubic bezier, return the number of times an XRay
+// crosses the cubic. Valid return values are [0..3].
+//
+// By definition the cubic is open at the starting point; in other
+// words, if pt.fY is equivalent to cubic[0].fY, and pt.fX is to the
+// left of the curve, the line is not considered to cross the curve,
+// but if it is equal to cubic[3].fY then it is considered to
+// cross.
+//
+// Outgoing "ambiguous" argument indicates whether the answer is ambiguous
+// because the query occurred exactly at one of the endpoints' y
+// coordinates or at a tangent point, indicating that another query y
+// coordinate is preferred for robustness.
+int numXRayCrossingsForCubic(const XRay& xRay,
+ const FloatPoint cubic[4],
+ bool& ambiguous);
+
+// Given a line segment from lineEndpoints[0] to lineEndpoints[1], and an
+// XRay, returns true if they intersect. Outgoing "ambiguous" argument
+// indicates whether the answer is ambiguous because the query occurred
+// exactly at one of the endpoints' y coordinates, indicating that another
+// query y coordinate is preferred for robustness.
+bool xRayCrossesLine(const XRay& xRay,
+ const FloatPoint lineEndpoints[2],
+ bool& ambiguous);
+
+} // namespace LoopBlinnMathUtils
+
+} // namespace WebCore
+
+#endif // LoopBlinnMathUtils_h
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.cpp b/WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.cpp
new file mode 100644
index 0000000..ac82637
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "LoopBlinnTextureCoords.h"
+
+#include <math.h>
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+LoopBlinnTextureCoords::Result LoopBlinnTextureCoords::compute(const LoopBlinnClassifier::Result& classification, LoopBlinnConstants::FillSide sideToFill)
+{
+ // Loop and Blinn's formulation states that the right side of the
+ // curve is defined to be the inside (filled region), but for some
+ // reason it looks like with the default orientation parameters we
+ // are filling the left side of the curve. Regardless, because we
+ // can receive arbitrarily oriented curves as input, we might have
+ // to reverse the orientation of the cubic texture coordinates even
+ // in cases where the paper doesn't say it is necessary.
+ bool reverseOrientation = false;
+ static const float OneThird = 1.0f / 3.0f;
+ static const float TwoThirds = 2.0f / 3.0f;
+ LoopBlinnClassifier::CurveType curveType = classification.curveType;
+
+ LoopBlinnTextureCoords::Result result;
+
+ switch (curveType) {
+ case LoopBlinnClassifier::kSerpentine: {
+ float t1 = sqrtf(9.0f * classification.d2 * classification.d2 - 12 * classification.d1 * classification.d3);
+ float ls = 3.0f * classification.d2 - t1;
+ float lt = 6.0f * classification.d1;
+ float ms = 3.0f * classification.d2 + t1;
+ float mt = lt;
+ float ltMinusLs = lt - ls;
+ float mtMinusMs = mt - ms;
+ result.klmCoordinates[0] = FloatPoint3D(ls * ms,
+ ls * ls * ls,
+ ms * ms * ms);
+ result.klmCoordinates[1] = FloatPoint3D(OneThird * (3.0f * ls * ms - ls * mt - lt * ms),
+ ls * ls * (ls - lt),
+ ms * ms * (ms - mt));
+ result.klmCoordinates[2] = FloatPoint3D(OneThird * (lt * (mt - 2.0f * ms) + ls * (3.0f * ms - 2.0f * mt)),
+ ltMinusLs * ltMinusLs * ls,
+ mtMinusMs * mtMinusMs * ms);
+ result.klmCoordinates[3] = FloatPoint3D(ltMinusLs * mtMinusMs,
+ -(ltMinusLs * ltMinusLs * ltMinusLs),
+ -(mtMinusMs * mtMinusMs * mtMinusMs));
+ if (classification.d1 < 0.0f)
+ reverseOrientation = true;
+ break;
+ }
+
+ case LoopBlinnClassifier::kLoop: {
+ float t1 = sqrtf(4.0f * classification.d1 * classification.d3 - 3.0f * classification.d2 * classification.d2);
+ float ls = classification.d2 - t1;
+ float lt = 2.0f * classification.d1;
+ float ms = classification.d2 + t1;
+ float mt = lt;
+
+ // Figure out whether there is a rendering artifact requiring
+ // the curve to be subdivided by the caller.
+ float ql = ls / lt;
+ float qm = ms / mt;
+ if (0.0f < ql && ql < 1.0f) {
+ result.hasRenderingArtifact = true;
+ result.subdivisionParameterValue = ql;
+ return result;
+ }
+
+ if (0.0f < qm && qm < 1.0f) {
+ result.hasRenderingArtifact = true;
+ result.subdivisionParameterValue = qm;
+ return result;
+ }
+
+ float ltMinusLs = lt - ls;
+ float mtMinusMs = mt - ms;
+ result.klmCoordinates[0] = FloatPoint3D(ls * ms,
+ ls * ls * ms,
+ ls * ms * ms);
+ result.klmCoordinates[1] = FloatPoint3D(OneThird * (-ls * mt - lt * ms + 3.0f * ls * ms),
+ -OneThird * ls * (ls * (mt - 3.0f * ms) + 2.0f * lt * ms),
+ -OneThird * ms * (ls * (2.0f * mt - 3.0f * ms) + lt * ms));
+ result.klmCoordinates[2] = FloatPoint3D(OneThird * (lt * (mt - 2.0f * ms) + ls * (3.0f * ms - 2.0f * mt)),
+ OneThird * (lt - ls) * (ls * (2.0f * mt - 3.0f * ms) + lt * ms),
+ OneThird * (mt - ms) * (ls * (mt - 3.0f * ms) + 2.0f * lt * ms));
+ result.klmCoordinates[3] = FloatPoint3D(ltMinusLs * mtMinusMs,
+ -(ltMinusLs * ltMinusLs) * mtMinusMs,
+ -ltMinusLs * mtMinusMs * mtMinusMs);
+ reverseOrientation = ((classification.d1 > 0.0f && result.klmCoordinates[0].x() < 0.0f)
+ || (classification.d1 < 0.0f && result.klmCoordinates[0].x() > 0.0f));
+ break;
+ }
+
+ case LoopBlinnClassifier::kCusp: {
+ float ls = classification.d3;
+ float lt = 3.0f * classification.d2;
+ float lsMinusLt = ls - lt;
+ result.klmCoordinates[0] = FloatPoint3D(ls,
+ ls * ls * ls,
+ 1.0f);
+ result.klmCoordinates[1] = FloatPoint3D(ls - OneThird * lt,
+ ls * ls * lsMinusLt,
+ 1.0f);
+ result.klmCoordinates[2] = FloatPoint3D(ls - TwoThirds * lt,
+ lsMinusLt * lsMinusLt * ls,
+ 1.0f);
+ result.klmCoordinates[3] = FloatPoint3D(lsMinusLt,
+ lsMinusLt * lsMinusLt * lsMinusLt,
+ 1.0f);
+ break;
+ }
+
+ case LoopBlinnClassifier::kQuadratic: {
+ result.klmCoordinates[0] = FloatPoint3D(0, 0, 0);
+ result.klmCoordinates[1] = FloatPoint3D(OneThird, 0, OneThird);
+ result.klmCoordinates[2] = FloatPoint3D(TwoThirds, OneThird, TwoThirds);
+ result.klmCoordinates[3] = FloatPoint3D(1, 1, 1);
+ if (classification.d3 < 0)
+ reverseOrientation = true;
+ break;
+ }
+
+ case LoopBlinnClassifier::kLine:
+ case LoopBlinnClassifier::kPoint:
+ result.isLineOrPoint = true;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ if (sideToFill == LoopBlinnConstants::RightSide)
+ reverseOrientation = !reverseOrientation;
+
+ if (reverseOrientation) {
+ for (int i = 0; i < 4; ++i) {
+ result.klmCoordinates[i].setX(-result.klmCoordinates[i].x());
+ result.klmCoordinates[i].setY(-result.klmCoordinates[i].y());
+ }
+ }
+
+ return result;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.h b/WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.h
new file mode 100644
index 0000000..5fdeb3b
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LoopBlinnTextureCoords_h
+#define LoopBlinnTextureCoords_h
+
+#include "FloatPoint3D.h"
+#include "LoopBlinnClassifier.h"
+#include "LoopBlinnConstants.h"
+
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+// Computes three-dimensional texture coordinates for the control
+// points of a cubic curve for rendering via the shader in "Rendering
+// Vector Art on the GPU" by Loop and Blinn, GPU Gems 3, Chapter 25.
+class LoopBlinnTextureCoords {
+public:
+ // Container for the cubic texture coordinates and other associated
+ // information.
+ struct Result {
+ Result()
+ : isLineOrPoint(false)
+ , hasRenderingArtifact(false)
+ , subdivisionParameterValue(0.0f) { }
+
+ // The (k, l, m) texture coordinates that are to be associated
+ // with the four control points of the cubic curve.
+ FloatPoint3D klmCoordinates[4];
+
+ // Indicates whether the curve is a line or a point, in which case
+ // we do not need to add its triangles to the mesh.
+ bool isLineOrPoint;
+
+ // For the loop case, indicates whether a rendering artifact was
+ // detected, in which case the curve needs to be further
+ // subdivided.
+ bool hasRenderingArtifact;
+
+ // If a rendering artifact will occur for the given loop curve,
+ // this is the parameter value (0 <= value <= 1) at which the
+ // curve needs to be subdivided to fix the artifact.
+ float subdivisionParameterValue;
+ };
+
+ // Computes the texture coordinates for a cubic curve segment's
+ // control points, given the classification of the curve as well as
+ // an indication of which side is to be filled.
+ static Result compute(const LoopBlinnClassifier::Result& classification,
+ LoopBlinnConstants::FillSide sideToFill);
+
+private:
+ // This class does not need to be instantiated.
+ LoopBlinnTextureCoords() { }
+};
+
+} // namespace WebCore
+
+#endif // LoopBlinnTextureCoords_h
diff --git a/WebCore/platform/graphics/gpu/PODArena.h b/WebCore/platform/graphics/gpu/PODArena.h
new file mode 100644
index 0000000..f68baef
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/PODArena.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PODArena_h
+#define PODArena_h
+
+#include <stdint.h>
+#include <wtf/Assertions.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+// An arena which allocates only Plain Old Data (POD), or classes and
+// structs bottoming out in Plain Old Data. NOTE: the constructors of
+// the objects allocated in this arena are called, but _not_ their
+// destructors.
+
+class PODArena : public RefCounted<PODArena> {
+public:
+ // The arena is configured with an allocator, which is responsible
+ // for allocating and freeing chunks of memory at a time.
+ class Allocator : public RefCounted<Allocator> {
+ public:
+ virtual void* allocate(size_t size) = 0;
+ virtual void free(void* ptr) = 0;
+ protected:
+ virtual ~Allocator() { }
+ friend class WTF::RefCounted<Allocator>;
+ };
+
+ // The Arena's default allocator, which uses fastMalloc and
+ // fastFree to allocate chunks of storage.
+ class FastMallocAllocator : public Allocator {
+ public:
+ static PassRefPtr<FastMallocAllocator> create()
+ {
+ return adoptRef(new FastMallocAllocator);
+ }
+
+ virtual void* allocate(size_t size) { return fastMalloc(size); }
+ virtual void free(void* ptr) { fastFree(ptr); }
+
+ protected:
+ FastMallocAllocator() { }
+ };
+
+ // Creates a new PODArena configured with a FastMallocAllocator.
+ static PassRefPtr<PODArena> create()
+ {
+ return adoptRef(new PODArena);
+ }
+
+ // Creates a new PODArena configured with the given Allocator.
+ static PassRefPtr<PODArena> create(PassRefPtr<Allocator> allocator)
+ {
+ return adoptRef(new PODArena(allocator));
+ }
+
+ // Allocates an object from the arena.
+ template<class T> T* allocateObject()
+ {
+ void* ptr = allocateBase<T>();
+ if (ptr) {
+ // Use placement operator new to allocate a T at this location.
+ new(ptr) T();
+ }
+ return static_cast<T*>(ptr);
+ }
+
+ // Allocates an object from the arena, calling a single-argument constructor.
+ template<class T, class Argument1Type> T* allocateObject(const Argument1Type& argument1)
+ {
+ void* ptr = allocateBase<T>();
+ if (ptr) {
+ // Use placement operator new to allocate a T at this location.
+ new(ptr) T(argument1);
+ }
+ return static_cast<T*>(ptr);
+ }
+
+ // The initial size of allocated chunks; increases as necessary to
+ // satisfy large allocations. Mainly public for unit tests.
+ enum {
+ DefaultChunkSize = 16384
+ };
+
+protected:
+ ~PODArena() { }
+ friend class WTF::RefCounted<PODArena>;
+
+private:
+ PODArena()
+ : m_allocator(FastMallocAllocator::create())
+ , m_current(0)
+ , m_currentChunkSize(DefaultChunkSize) { }
+
+ explicit PODArena(PassRefPtr<Allocator> allocator)
+ : m_allocator(allocator)
+ , m_current(0)
+ , m_currentChunkSize(DefaultChunkSize) { }
+
+ // Returns the alignment requirement for classes and structs on the
+ // current platform.
+ template <class T> static size_t minAlignment()
+ {
+ return WTF_ALIGN_OF(T);
+ }
+
+ template<class T> void* allocateBase()
+ {
+ void* ptr = 0;
+ size_t roundedSize = roundUp(sizeof(T), minAlignment<T>());
+ if (m_current)
+ ptr = m_current->allocate(roundedSize);
+
+ if (!ptr) {
+ if (roundedSize > m_currentChunkSize)
+ m_currentChunkSize = roundedSize;
+ m_chunks.append(adoptPtr(new Chunk(m_allocator.get(), m_currentChunkSize)));
+ m_current = m_chunks.last().get();
+ ptr = m_current->allocate(roundedSize);
+ }
+ return ptr;
+ }
+
+ // Rounds up the given allocation size to the specified alignment.
+ size_t roundUp(size_t size, size_t alignment)
+ {
+ ASSERT(!(alignment % 2));
+ return (size + alignment - 1) & ~(alignment - 1);
+ }
+
+ // Manages a chunk of memory and individual allocations out of it.
+ class Chunk : public Noncopyable {
+ public:
+ // Allocates a block of memory of the given size from the passed
+ // Allocator.
+ Chunk(Allocator* allocator, size_t size)
+ : m_allocator(allocator)
+ , m_size(size)
+ , m_currentOffset(0)
+ {
+ m_base = static_cast<uint8_t*>(m_allocator->allocate(size));
+ }
+
+ // Frees the memory allocated from the Allocator in the
+ // constructor.
+ ~Chunk()
+ {
+ m_allocator->free(m_base);
+ }
+
+ // Returns a pointer to "size" bytes of storage, or 0 if this
+ // Chunk could not satisfy the allocation.
+ void* allocate(size_t size)
+ {
+ // Check for overflow
+ if (m_currentOffset + size < m_currentOffset)
+ return 0;
+
+ if (m_currentOffset + size > m_size)
+ return 0;
+
+ void* result = m_base + m_currentOffset;
+ m_currentOffset += size;
+ return result;
+ }
+
+ private:
+ Allocator* m_allocator;
+ uint8_t* m_base;
+ size_t m_size;
+ size_t m_currentOffset;
+ };
+
+ RefPtr<Allocator> m_allocator;
+ Chunk* m_current;
+ size_t m_currentChunkSize;
+ Vector<OwnPtr<Chunk> > m_chunks;
+};
+
+} // namespace WebCore
+
+#endif // PODArena_h
diff --git a/WebCore/platform/graphics/gpu/PODInterval.h b/WebCore/platform/graphics/gpu/PODInterval.h
new file mode 100644
index 0000000..9df69ba
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/PODInterval.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PODInterval_h
+#define PODInterval_h
+
+#ifndef NDEBUG
+#include "StringBuilder.h"
+#endif
+
+namespace WebCore {
+
+// Class representing a closed interval which can hold an arbitrary
+// Plain Old Datatype (POD) as its endpoints and a piece of user
+// data. An important characteristic for the algorithms we use is that
+// if two intervals have identical endpoints but different user data,
+// they are not considered to be equal. This situation can arise when
+// representing the vertical extents of bounding boxes of overlapping
+// triangles, where the pointer to the triangle is the user data of
+// the interval.
+//
+// *Note* that the destructors of type T and UserData will *not* be
+// called by this class. They must not allocate any memory that is
+// required to be cleaned up in their destructors.
+//
+// The following constructors and operators must be implemented on
+// type T:
+//
+// - Copy constructor (if user data is desired)
+// - operator<
+// - operator==
+// - operator=
+//
+// If the UserData type is specified, it must support a copy
+// constructor and assignment operator.
+//
+// In debug mode, printing of intervals and the data they contain is
+// enabled. This requires the following functions to be available:
+//
+// String valueToString(const T&);
+// String valueToString(const UserData&);
+//
+// Note that this class requires a copy constructor and assignment
+// operator in order to be stored in the red-black tree.
+
+template<class T, class UserData = void*>
+class PODInterval {
+public:
+ // Constructor from endpoints. This constructor only works when the
+ // UserData type is a pointer or other type which can be initialized
+ // with 0.
+ PODInterval(const T& low, const T& high)
+ : m_low(low)
+ , m_high(high)
+ , m_data(0)
+ , m_maxHigh(high)
+ {
+ }
+
+ // Constructor from two endpoints plus explicit user data.
+ PODInterval(const T& low, const T& high, const UserData data)
+ : m_low(low)
+ , m_high(high)
+ , m_data(data)
+ , m_maxHigh(high)
+ {
+ }
+
+ const T& low() const { return m_low; }
+ const T& high() const { return m_high; }
+ const UserData& data() const { return m_data; }
+
+ bool overlaps(const T& low, const T& high) const
+ {
+ if (this->high() < low)
+ return false;
+ if (high < this->low())
+ return false;
+ return true;
+ }
+
+ bool overlaps(const PODInterval& other) const
+ {
+ return overlaps(other.low(), other.high());
+ }
+
+ // Returns true if this interval is "less" than the other. The
+ // comparison is performed on the low endpoints of the intervals.
+ bool operator<(const PODInterval& other) const
+ {
+ return low() < other.low();
+ }
+
+ // Returns true if this interval is strictly equal to the other,
+ // including comparison of the user data.
+ bool operator==(const PODInterval& other) const
+ {
+ return (low() == other.low()
+ && high() == other.high()
+ && data() == other.data());
+ }
+
+ const T& maxHigh() const { return m_maxHigh; }
+ void setMaxHigh(const T& maxHigh) { m_maxHigh = maxHigh; }
+
+#ifndef NDEBUG
+ // Support for printing PODIntervals.
+ String toString() const
+ {
+ StringBuilder builder;
+ builder.append("[PODInterval (");
+ builder.append(valueToString(low()));
+ builder.append(", ");
+ builder.append(valueToString(high()));
+ builder.append("), data=");
+ builder.append(valueToString(data()));
+ builder.append(", maxHigh=");
+ builder.append(valueToString(maxHigh()));
+ builder.append("]");
+ return builder.toString();
+ }
+#endif
+
+private:
+ T m_low;
+ T m_high;
+ UserData m_data;
+ T m_maxHigh;
+};
+
+} // namespace WebCore
+
+#endif // PODInterval_h
diff --git a/WebCore/platform/graphics/gpu/PODIntervalTree.h b/WebCore/platform/graphics/gpu/PODIntervalTree.h
new file mode 100644
index 0000000..c0a86aa
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/PODIntervalTree.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PODIntervalTree_h
+#define PODIntervalTree_h
+
+#include "PODArena.h"
+#include "PODInterval.h"
+#include "PODRedBlackTree.h"
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+// An interval tree, which is a form of augmented red-black tree. It
+// supports efficient (O(lg n)) insertion, removal and querying of
+// intervals in the tree.
+template<class T, class UserData = void*>
+class PODIntervalTree : public Noncopyable,
+ public PODRedBlackTree<PODInterval<T, UserData> > {
+public:
+ // Typedef to reduce typing when declaring intervals to be stored in
+ // this tree.
+ typedef PODInterval<T, UserData> IntervalType;
+
+ PODIntervalTree()
+ : PODRedBlackTree<IntervalType>()
+ {
+ init();
+ }
+
+ explicit PODIntervalTree(PassRefPtr<PODArena> arena)
+ : PODRedBlackTree<IntervalType>(arena)
+ {
+ init();
+ }
+
+ // Returns all intervals in the tree which overlap the given query
+ // interval. The returned intervals are sorted by increasing low
+ // endpoint.
+ Vector<IntervalType> allOverlaps(const IntervalType& interval) const
+ {
+ Vector<IntervalType> result;
+ allOverlaps(interval, result);
+ return result;
+ }
+
+ // Returns all intervals in the tree which overlap the given query
+ // interval. The returned intervals are sorted by increasing low
+ // endpoint.
+ void allOverlaps(const IntervalType& interval, Vector<IntervalType>& result) const
+ {
+ // Explicit dereference of "this" required because of
+ // inheritance rules in template classes.
+ searchForOverlapsFrom(this->root(), interval, result);
+ }
+
+ // Helper to create interval objects.
+ static IntervalType createInterval(const T& low, const T& high, const UserData data = 0)
+ {
+ return IntervalType(low, high, data);
+ }
+
+ virtual bool checkInvariants() const
+ {
+ if (!PODRedBlackTree<IntervalType>::checkInvariants())
+ return false;
+ if (!this->root())
+ return true;
+ return checkInvariantsFromNode(this->root(), 0);
+ }
+
+private:
+ typedef typename PODRedBlackTree<IntervalType>::Node IntervalNode;
+
+ // Initializes the tree.
+ void init()
+ {
+ // Explicit dereference of "this" required because of
+ // inheritance rules in template classes.
+ this->setNeedsFullOrderingComparisons(true);
+ }
+
+ // Starting from the given node, adds all overlaps with the given
+ // interval to the result vector. The intervals are sorted by
+ // increasing low endpoint.
+ void searchForOverlapsFrom(IntervalNode* node, const IntervalType& interval, Vector<IntervalType>& res) const
+ {
+ if (!node)
+ return;
+
+ // Because the intervals are sorted by left endpoint, inorder
+ // traversal produces results sorted as desired.
+
+ // See whether we need to traverse the left subtree.
+ IntervalNode* left = node->left();
+ if (left
+ // This is phrased this way to avoid the need for operator
+ // <= on type T.
+ && !(left->data().maxHigh() < interval.low()))
+ searchForOverlapsFrom(left, interval, res);
+
+ // Check for overlap with current node.
+ if (node->data().overlaps(interval))
+ res.append(node->data());
+
+ // See whether we need to traverse the right subtree.
+ // This is phrased this way to avoid the need for operator <=
+ // on type T.
+ if (!(interval.high() < node->data().low()))
+ searchForOverlapsFrom(node->right(), interval, res);
+ }
+
+ virtual bool updateNode(IntervalNode* node)
+ {
+ // Would use const T&, but need to reassign this reference in this
+ // function.
+ const T* curMax = &node->data().high();
+ IntervalNode* left = node->left();
+ if (left) {
+ if (*curMax < left->data().maxHigh())
+ curMax = &left->data().maxHigh();
+ }
+ IntervalNode* right = node->right();
+ if (right) {
+ if (*curMax < right->data().maxHigh())
+ curMax = &right->data().maxHigh();
+ }
+ // This is phrased like this to avoid needing operator!= on type T.
+ if (!(*curMax == node->data().maxHigh())) {
+ node->data().setMaxHigh(*curMax);
+ return true;
+ }
+ return false;
+ }
+
+ bool checkInvariantsFromNode(IntervalNode* node, T* currentMaxValue) const
+ {
+ // These assignments are only done in order to avoid requiring
+ // a default constructor on type T.
+ T leftMaxValue(node->data().maxHigh());
+ T rightMaxValue(node->data().maxHigh());
+ IntervalNode* left = node->left();
+ IntervalNode* right = node->right();
+ if (left) {
+ if (!checkInvariantsFromNode(left, &leftMaxValue))
+ return false;
+ }
+ if (right) {
+ if (!checkInvariantsFromNode(right, &rightMaxValue))
+ return false;
+ }
+ if (!left && !right) {
+ // Base case.
+ if (currentMaxValue)
+ *currentMaxValue = node->data().high();
+ return (node->data().high() == node->data().maxHigh());
+ }
+ T localMaxValue(node->data().maxHigh());
+ if (!left || !right) {
+ if (left)
+ localMaxValue = leftMaxValue;
+ else
+ localMaxValue = rightMaxValue;
+ } else
+ localMaxValue = (leftMaxValue < rightMaxValue) ? rightMaxValue : leftMaxValue;
+ if (localMaxValue < node->data().high())
+ localMaxValue = node->data().high();
+ if (!(localMaxValue == node->data().maxHigh())) {
+#ifndef NDEBUG
+ String localMaxValueString = valueToString(localMaxValue);
+ LOG_ERROR("PODIntervalTree verification failed at node 0x%p: localMaxValue=%s and data=%s",
+ node, localMaxValueString.utf8().data(), node->data().toString().utf8().data());
+#endif
+ return false;
+ }
+ if (currentMaxValue)
+ *currentMaxValue = localMaxValue;
+ return true;
+ }
+};
+
+#ifndef NDEBUG
+// Support for printing PODIntervals at the PODRedBlackTree level.
+template<class T, class UserData>
+String valueToString(const PODInterval<T, UserData>& interval)
+{
+ return interval.toString();
+}
+#endif
+
+} // namespace WebCore
+
+#endif // PODIntervalTree_h
diff --git a/WebCore/platform/graphics/gpu/PODRedBlackTree.h b/WebCore/platform/graphics/gpu/PODRedBlackTree.h
new file mode 100644
index 0000000..9b02037
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/PODRedBlackTree.h
@@ -0,0 +1,750 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// A red-black tree, which is a form of a balanced binary tree. It
+// supports efficient insertion, deletion and queries of comparable
+// elements. The same element may be inserted multiple times. The
+// algorithmic complexity of common operations is:
+//
+// Insertion: O(lg(n))
+// Deletion: O(lg(n))
+// Querying: O(lg(n))
+//
+// The data type T that is stored in this red-black tree must be only
+// Plain Old Data (POD), or bottom out into POD. It must _not_ rely on
+// having its destructor called. This implementation internally
+// allocates storage in large chunks and does not call the destructor
+// on each object.
+//
+// Type T must supply a default constructor, a copy constructor, and
+// the "<" and "==" operators.
+//
+// In debug mode, printing of the data contained in the tree is
+// enabled. This requires the following function to be available:
+//
+// String valueToString(const T&);
+//
+// Note that when complex types are stored in this red/black tree, it
+// is possible that single invocations of the "<" and "==" operators
+// will be insufficient to describe the ordering of elements in the
+// tree during queries. As a concrete example, consider the case where
+// intervals are stored in the tree sorted by low endpoint. The "<"
+// operator on the Interval class only compares the low endpoint, but
+// the "==" operator takes into account the high endpoint as well.
+// This makes the necessary logic for querying and deletion somewhat
+// more complex. In order to properly handle such situations, the
+// property "needsFullOrderingComparisons" must be set to true on
+// the tree.
+//
+// This red-black tree is designed to be _augmented_; subclasses can
+// add additional and summary information to each node to efficiently
+// store and index more complex data structures. A concrete example is
+// the IntervalTree, which extends each node with a summary statistic
+// to efficiently store one-dimensional intervals.
+//
+// The design of this red-black tree comes from Cormen, Leiserson,
+// and Rivest, _Introduction to Algorithms_, MIT Press, 1990.
+
+#ifndef PODRedBlackTree_h
+#define PODRedBlackTree_h
+
+#include "PODArena.h"
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/RefPtr.h>
+#ifndef NDEBUG
+#include "Logging.h"
+#include "PlatformString.h"
+#include "StringBuilder.h"
+#include <wtf/text/CString.h>
+#endif
+
+namespace WebCore {
+
+template<class T>
+class PODRedBlackTree {
+public:
+ // Visitor interface for walking all of the tree's elements.
+ class Visitor {
+ public:
+ virtual void visit(const T& data) = 0;
+ protected:
+ virtual ~Visitor() { }
+ };
+
+ // Constructs a new red-black tree, allocating temporary objects
+ // from a newly constructed PODArena.
+ PODRedBlackTree()
+ : m_arena(PODArena::create())
+ , m_root(0)
+ , m_needsFullOrderingComparisons(false)
+#ifndef NDEBUG
+ , m_verboseDebugging(false)
+#endif
+ {
+ }
+
+ // Constructs a new red-black tree, allocating temporary objects
+ // from the given PODArena.
+ explicit PODRedBlackTree(PassRefPtr<PODArena> arena)
+ : m_arena(arena)
+ , m_root(0)
+ , m_needsFullOrderingComparisons(false)
+#ifndef NDEBUG
+ , m_verboseDebugging(false)
+#endif
+ {
+ }
+
+ virtual ~PODRedBlackTree() { }
+
+ void add(const T& data)
+ {
+ Node* node = m_arena->allocateObject<Node, T>(data);
+ insertNode(node);
+ }
+
+ // Returns true if the datum was found in the tree.
+ bool remove(const T& data)
+ {
+ Node* node = treeSearch(data);
+ if (node) {
+ deleteNode(node);
+ return true;
+ }
+ return false;
+ }
+
+ bool contains(const T& data) const { return treeSearch(data); }
+
+ void visitInorder(Visitor* visitor) const
+ {
+ if (!m_root)
+ return;
+ visitInorderImpl(m_root, visitor);
+ }
+
+ int size() const
+ {
+ Counter counter;
+ visitInorder(&counter);
+ return counter.count();
+ }
+
+ // See the class documentation for an explanation of this property.
+ void setNeedsFullOrderingComparisons(bool needsFullOrderingComparisons)
+ {
+ m_needsFullOrderingComparisons = needsFullOrderingComparisons;
+ }
+
+ virtual bool checkInvariants() const
+ {
+ int blackCount;
+ return checkInvariantsFromNode(m_root, &blackCount);
+ }
+
+#ifndef NDEBUG
+ // Dumps the tree's contents to the logging info stream for
+ // debugging purposes.
+ void dump() const
+ {
+ dumpFromNode(m_root, 0);
+ }
+
+ // Turns on or off verbose debugging of the tree, causing many
+ // messages to be logged during insertion and other operations in
+ // debug mode.
+ void setVerboseDebugging(bool verboseDebugging)
+ {
+ m_verboseDebugging = verboseDebugging;
+ }
+#endif
+
+protected:
+ enum Color {
+ Red = 1,
+ Black
+ };
+
+ // The base Node class which is stored in the tree. Nodes are only
+ // an internal concept; users of the tree deal only with the data
+ // they store in it.
+ class Node : public Noncopyable {
+ public:
+ // Constructor. Newly-created nodes are colored red.
+ explicit Node(const T& data)
+ : m_left(0)
+ , m_right(0)
+ , m_parent(0)
+ , m_color(Red)
+ , m_data(data)
+ {
+ }
+
+ virtual ~Node() { }
+
+ Color color() const { return m_color; }
+ void setColor(Color color) { m_color = color; }
+
+ // Fetches the user data.
+ T& data() { return m_data; }
+
+ // Copies all user-level fields from the source node, but not
+ // internal fields. For example, the base implementation of this
+ // method copies the "m_data" field, but not the child or parent
+ // fields. Any augmentation information also does not need to be
+ // copied, as it will be recomputed. Subclasses must call the
+ // superclass implementation.
+ virtual void copyFrom(Node* src) { m_data = src->data(); }
+
+ Node* left() const { return m_left; }
+ void setLeft(Node* node) { m_left = node; }
+
+ Node* right() const { return m_right; }
+ void setRight(Node* node) { m_right = node; }
+
+ Node* parent() const { return m_parent; }
+ void setParent(Node* node) { m_parent = node; }
+
+ private:
+ Node* m_left;
+ Node* m_right;
+ Node* m_parent;
+ Color m_color;
+ T m_data;
+ };
+
+ // Returns the root of the tree, which is needed by some subclasses.
+ Node* root() const { return m_root; }
+
+private:
+ // This virtual method is the hook that subclasses should use when
+ // augmenting the red-black tree with additional per-node summary
+ // information. For example, in the case of an interval tree, this
+ // is used to compute the maximum endpoint of the subtree below the
+ // given node based on the values in the left and right children. It
+ // is guaranteed that this will be called in the correct order to
+ // properly update such summary information based only on the values
+ // in the left and right children. This method should return true if
+ // the node's summary information changed.
+ virtual bool updateNode(Node* node) { return false; }
+
+ //----------------------------------------------------------------------
+ // Generic binary search tree operations
+ //
+
+ // Searches the tree for the given datum.
+ Node* treeSearch(const T& data) const
+ {
+ if (m_needsFullOrderingComparisons)
+ return treeSearchFullComparisons(m_root, data);
+
+ return treeSearchNormal(m_root, data);
+ }
+
+ // Searches the tree using the normal comparison operations,
+ // suitable for simple data types such as numbers.
+ Node* treeSearchNormal(Node* current, const T& data) const
+ {
+ while (current) {
+ if (current->data() == data)
+ return current;
+ if (data < current->data())
+ current = current->left();
+ else
+ current = current->right();
+ }
+ return 0;
+ }
+
+ // Searches the tree using multiple comparison operations, required
+ // for data types with more complex behavior such as intervals.
+ Node* treeSearchFullComparisons(Node* current, const T& data) const
+ {
+ if (!current)
+ return 0;
+ if (data < current->data())
+ return treeSearchFullComparisons(current->left(), data);
+ if (current->data() < data)
+ return treeSearchFullComparisons(current->right(), data);
+ if (data == current->data())
+ return current;
+
+ // We may need to traverse both the left and right subtrees.
+ Node* result = treeSearchFullComparisons(current->left(), data);
+ if (!result)
+ result = treeSearchFullComparisons(current->right(), data);
+ return result;
+ }
+
+ void treeInsert(Node* z)
+ {
+ Node* y = 0;
+ Node* x = m_root;
+ while (x) {
+ y = x;
+ if (z->data() < x->data())
+ x = x->left();
+ else
+ x = x->right();
+ }
+ z->setParent(y);
+ if (!y)
+ m_root = z;
+ else {
+ if (z->data() < y->data())
+ y->setLeft(z);
+ else
+ y->setRight(z);
+ }
+ }
+
+ // Finds the node following the given one in sequential ordering of
+ // their data, or null if none exists.
+ Node* treeSuccessor(Node* x)
+ {
+ if (x->right())
+ return treeMinimum(x->right());
+ Node* y = x->parent();
+ while (y && x == y->right()) {
+ x = y;
+ y = y->parent();
+ }
+ return y;
+ }
+
+ // Finds the minimum element in the sub-tree rooted at the given
+ // node.
+ Node* treeMinimum(Node* x)
+ {
+ while (x->left())
+ x = x->left();
+ return x;
+ }
+
+ // Helper for maintaining the augmented red-black tree.
+ void propagateUpdates(Node* start)
+ {
+ bool shouldContinue = true;
+ while (start && shouldContinue) {
+ shouldContinue = updateNode(start);
+ start = start->parent();
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Red-Black tree operations
+ //
+
+ // Left-rotates the subtree rooted at x.
+ // Returns the new root of the subtree (x's right child).
+ Node* leftRotate(Node* x)
+ {
+ // Set y.
+ Node* y = x->right();
+
+ // Turn y's left subtree into x's right subtree.
+ x->setRight(y->left());
+ if (y->left())
+ y->left()->setParent(x);
+
+ // Link x's parent to y.
+ y->setParent(x->parent());
+ if (!x->parent())
+ m_root = y;
+ else {
+ if (x == x->parent()->left())
+ x->parent()->setLeft(y);
+ else
+ x->parent()->setRight(y);
+ }
+
+ // Put x on y's left.
+ y->setLeft(x);
+ x->setParent(y);
+
+ // Update nodes lowest to highest.
+ updateNode(x);
+ updateNode(y);
+ return y;
+ }
+
+ // Right-rotates the subtree rooted at y.
+ // Returns the new root of the subtree (y's left child).
+ Node* rightRotate(Node* y)
+ {
+ // Set x.
+ Node* x = y->left();
+
+ // Turn x's right subtree into y's left subtree.
+ y->setLeft(x->right());
+ if (x->right())
+ x->right()->setParent(y);
+
+ // Link y's parent to x.
+ x->setParent(y->parent());
+ if (!y->parent())
+ m_root = x;
+ else {
+ if (y == y->parent()->left())
+ y->parent()->setLeft(x);
+ else
+ y->parent()->setRight(x);
+ }
+
+ // Put y on x's right.
+ x->setRight(y);
+ y->setParent(x);
+
+ // Update nodes lowest to highest.
+ updateNode(y);
+ updateNode(x);
+ return x;
+ }
+
+ // Inserts the given node into the tree.
+ void insertNode(Node* x)
+ {
+ treeInsert(x);
+ x->setColor(Red);
+ updateNode(x);
+
+ logIfVerbose(" PODRedBlackTree::InsertNode");
+
+ // The node from which to start propagating updates upwards.
+ Node* updateStart = x->parent();
+
+ while (x != m_root && x->parent()->color() == Red) {
+ if (x->parent() == x->parent()->parent()->left()) {
+ Node* y = x->parent()->parent()->right();
+ if (y && y->color() == Red) {
+ // Case 1
+ logIfVerbose(" Case 1/1");
+ x->parent()->setColor(Black);
+ y->setColor(Black);
+ x->parent()->parent()->setColor(Red);
+ updateNode(x->parent());
+ x = x->parent()->parent();
+ updateNode(x);
+ updateStart = x->parent();
+ } else {
+ if (x == x->parent()->right()) {
+ logIfVerbose(" Case 1/2");
+ // Case 2
+ x = x->parent();
+ leftRotate(x);
+ }
+ // Case 3
+ logIfVerbose(" Case 1/3");
+ x->parent()->setColor(Black);
+ x->parent()->parent()->setColor(Red);
+ Node* newSubTreeRoot = rightRotate(x->parent()->parent());
+ updateStart = newSubTreeRoot->parent();
+ }
+ } else {
+ // Same as "then" clause with "right" and "left" exchanged.
+ Node* y = x->parent()->parent()->left();
+ if (y && y->color() == Red) {
+ // Case 1
+ logIfVerbose(" Case 2/1");
+ x->parent()->setColor(Black);
+ y->setColor(Black);
+ x->parent()->parent()->setColor(Red);
+ updateNode(x->parent());
+ x = x->parent()->parent();
+ updateNode(x);
+ updateStart = x->parent();
+ } else {
+ if (x == x->parent()->left()) {
+ // Case 2
+ logIfVerbose(" Case 2/2");
+ x = x->parent();
+ rightRotate(x);
+ }
+ // Case 3
+ logIfVerbose(" Case 2/3");
+ x->parent()->setColor(Black);
+ x->parent()->parent()->setColor(Red);
+ Node* newSubTreeRoot = leftRotate(x->parent()->parent());
+ updateStart = newSubTreeRoot->parent();
+ }
+ }
+ }
+
+ propagateUpdates(updateStart);
+
+ m_root->setColor(Black);
+ }
+
+ // Restores the red-black property to the tree after splicing out
+ // a node. Note that x may be null, which is why xParent must be
+ // supplied.
+ void deleteFixup(Node* x, Node* xParent)
+ {
+ while (x != m_root && (!x || x->color() == Black)) {
+ if (x == xParent->left()) {
+ // Note: the text points out that w can not be null.
+ // The reason is not obvious from simply looking at
+ // the code; it comes about from the properties of the
+ // red-black tree.
+ Node* w = xParent->right();
+ ASSERT(w); // x's sibling should not be null.
+ if (w->color() == Red) {
+ // Case 1
+ w->setColor(Black);
+ xParent->setColor(Red);
+ leftRotate(xParent);
+ w = xParent->right();
+ }
+ if ((!w->left() || w->left()->color() == Black)
+ && (!w->right() || w->right()->color() == Black)) {
+ // Case 2
+ w->setColor(Red);
+ x = xParent;
+ xParent = x->parent();
+ } else {
+ if (!w->right() || w->right()->color() == Black) {
+ // Case 3
+ w->left()->setColor(Black);
+ w->setColor(Red);
+ rightRotate(w);
+ w = xParent->right();
+ }
+ // Case 4
+ w->setColor(xParent->color());
+ xParent->setColor(Black);
+ if (w->right())
+ w->right()->setColor(Black);
+ leftRotate(xParent);
+ x = m_root;
+ xParent = x->parent();
+ }
+ } else {
+ // Same as "then" clause with "right" and "left"
+ // exchanged.
+
+ // Note: the text points out that w can not be null.
+ // The reason is not obvious from simply looking at
+ // the code; it comes about from the properties of the
+ // red-black tree.
+ Node* w = xParent->left();
+ ASSERT(w); // x's sibling should not be null.
+ if (w->color() == Red) {
+ // Case 1
+ w->setColor(Black);
+ xParent->setColor(Red);
+ rightRotate(xParent);
+ w = xParent->left();
+ }
+ if ((!w->right() || w->right()->color() == Black)
+ && (!w->left() || w->left()->color() == Black)) {
+ // Case 2
+ w->setColor(Red);
+ x = xParent;
+ xParent = x->parent();
+ } else {
+ if (!w->left() || w->left()->color() == Black) {
+ // Case 3
+ w->right()->setColor(Black);
+ w->setColor(Red);
+ leftRotate(w);
+ w = xParent->left();
+ }
+ // Case 4
+ w->setColor(xParent->color());
+ xParent->setColor(Black);
+ if (w->left())
+ w->left()->setColor(Black);
+ rightRotate(xParent);
+ x = m_root;
+ xParent = x->parent();
+ }
+ }
+ }
+ if (x)
+ x->setColor(Black);
+ }
+
+ // Deletes the given node from the tree. Note that this
+ // particular node may not actually be removed from the tree;
+ // instead, another node might be removed and its contents
+ // copied into z.
+ void deleteNode(Node* z)
+ {
+ // Y is the node to be unlinked from the tree.
+ Node* y;
+ if (!z->left() || !z->right())
+ y = z;
+ else
+ y = treeSuccessor(z);
+
+ // Y is guaranteed to be non-null at this point.
+ Node* x;
+ if (y->left())
+ x = y->left();
+ else
+ x = y->right();
+
+ // X is the child of y which might potentially replace y in
+ // the tree. X might be null at this point.
+ Node* xParent;
+ if (x) {
+ x->setParent(y->parent());
+ xParent = x->parent();
+ } else
+ xParent = y->parent();
+ if (!y->parent())
+ m_root = x;
+ else {
+ if (y == y->parent()->left())
+ y->parent()->setLeft(x);
+ else
+ y->parent()->setRight(x);
+ }
+ if (y != z) {
+ z->copyFrom(y);
+ // This node has changed location in the tree and must be updated.
+ updateNode(z);
+ // The parent and its parents may now be out of date.
+ propagateUpdates(z->parent());
+ }
+
+ // If we haven't already updated starting from xParent, do so now.
+ if (xParent && xParent != y && xParent != z)
+ propagateUpdates(xParent);
+ if (y->color() == Black)
+ deleteFixup(x, xParent);
+ }
+
+ // Visits the subtree rooted at the given node in order.
+ void visitInorderImpl(Node* node, Visitor* visitor) const
+ {
+ if (node->left())
+ visitInorderImpl(node->left(), visitor);
+ visitor->visit(node->data());
+ if (node->right())
+ visitInorderImpl(node->right(), visitor);
+ }
+
+ //----------------------------------------------------------------------
+ // Helper class for size()
+
+ // A Visitor which simply counts the number of visited elements.
+ class Counter : public Visitor, public Noncopyable {
+ public:
+ Counter()
+ : m_count(0) { }
+
+ virtual void visit(const T& data) { ++m_count; }
+ int count() const { return m_count; }
+
+ private:
+ int m_count;
+ };
+
+ //----------------------------------------------------------------------
+ // Verification and debugging routines
+ //
+
+ // Returns in the "blackCount" parameter the number of black
+ // children along all paths to all leaves of the given node.
+ bool checkInvariantsFromNode(Node* node, int* blackCount) const
+ {
+ // Base case is a leaf node.
+ if (!node) {
+ *blackCount = 1;
+ return true;
+ }
+
+ // Each node is either red or black.
+ if (!(node->color() == Red || node->color() == Black))
+ return false;
+
+ // Every leaf (or null) is black.
+
+ if (node->color() == Red) {
+ // Both of its children are black.
+ if (!((!node->left() || node->left()->color() == Black)))
+ return false;
+ if (!((!node->right() || node->right()->color() == Black)))
+ return false;
+ }
+
+ // Every simple path to a leaf node contains the same number of
+ // black nodes.
+ int leftCount = 0, rightCount = 0;
+ bool leftValid = checkInvariantsFromNode(node->left(), &leftCount);
+ bool rightValid = checkInvariantsFromNode(node->right(), &rightCount);
+ if (!leftValid || !rightValid)
+ return false;
+ *blackCount = leftCount + (node->color() == Black ? 1 : 0);
+ return leftCount == rightCount;
+ }
+
+#ifdef NDEBUG
+ void logIfVerbose(const char* output) const { }
+#else
+ void logIfVerbose(const char* output) const
+ {
+ if (m_verboseDebugging)
+ LOG_ERROR("%s", output);
+ }
+#endif
+
+#ifndef NDEBUG
+ // Dumps the subtree rooted at the given node.
+ void dumpFromNode(Node* node, int indentation) const
+ {
+ StringBuilder builder;
+ for (int i = 0; i < indentation; i++)
+ builder.append(" ");
+ builder.append("-");
+ if (node) {
+ builder.append(" ");
+ builder.append(valueToString(node->data()));
+ builder.append((node->color() == Black) ? " (black)" : " (red)");
+ }
+ LOG_ERROR("%s", builder.toString().ascii().data());
+ if (node) {
+ dumpFromNode(node->left(), indentation + 2);
+ dumpFromNode(node->right(), indentation + 2);
+ }
+ }
+#endif
+
+ //----------------------------------------------------------------------
+ // Data members
+
+ RefPtr<PODArena> m_arena;
+ Node* m_root;
+ bool m_needsFullOrderingComparisons;
+#ifndef NDEBUG
+ bool m_verboseDebugging;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // PODRedBlackTree_h
diff --git a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
new file mode 100644
index 0000000..6424293
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "SharedGraphicsContext3D.h"
+
+#include "AffineTransform.h"
+#include "Color.h"
+#include "FloatRect.h"
+#include "GraphicsContext3D.h"
+#include "GraphicsTypes.h"
+#include "IntSize.h"
+#include "SolidFillShader.h"
+#include "TexShader.h"
+
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// static
+PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(PassOwnPtr<GraphicsContext3D> context)
+{
+ return adoptRef(new SharedGraphicsContext3D(context));
+}
+
+SharedGraphicsContext3D::SharedGraphicsContext3D(PassOwnPtr<GraphicsContext3D> context)
+ : m_context(context)
+ , m_quadVertices(0)
+ , m_solidFillShader(SolidFillShader::create(m_context.get()))
+ , m_texShader(TexShader::create(m_context.get()))
+{
+}
+
+SharedGraphicsContext3D::~SharedGraphicsContext3D()
+{
+ m_context->deleteBuffer(m_quadVertices);
+}
+
+void SharedGraphicsContext3D::makeContextCurrent()
+{
+ m_context->makeContextCurrent();
+}
+
+void SharedGraphicsContext3D::scissor(const FloatRect& rect)
+{
+ m_context->scissor(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+void SharedGraphicsContext3D::enable(unsigned capacity)
+{
+ m_context->enable(capacity);
+}
+
+void SharedGraphicsContext3D::disable(unsigned capacity)
+{
+ m_context->disable(capacity);
+}
+
+void SharedGraphicsContext3D::clearColor(const Color& color)
+{
+ float rgba[4];
+ color.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
+ m_context->clearColor(rgba[0], rgba[1], rgba[2], rgba[3]);
+}
+
+void SharedGraphicsContext3D::clear(unsigned mask)
+{
+ m_context->clear(mask);
+}
+
+void SharedGraphicsContext3D::drawArrays(unsigned long mode, long first, long count)
+{
+ m_context->drawArrays(mode, first, count);
+}
+
+unsigned long SharedGraphicsContext3D::getError()
+{
+ return m_context->getError();
+}
+
+void SharedGraphicsContext3D::getIntegerv(unsigned long pname, int* value)
+{
+ m_context->getIntegerv(pname, value);
+}
+
+unsigned SharedGraphicsContext3D::createFramebuffer()
+{
+ return m_context->createFramebuffer();
+}
+
+unsigned SharedGraphicsContext3D::createTexture()
+{
+ return m_context->createTexture();
+}
+
+void SharedGraphicsContext3D::deleteFramebuffer(unsigned framebuffer)
+{
+ m_context->deleteFramebuffer(framebuffer);
+}
+
+void SharedGraphicsContext3D::deleteTexture(unsigned texture)
+{
+ m_context->deleteTexture(texture);
+}
+
+void SharedGraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, unsigned texture, long level)
+{
+ m_context->framebufferTexture2D(target, attachment, textarget, texture, level);
+}
+
+void SharedGraphicsContext3D::texParameteri(unsigned target, unsigned pname, int param)
+{
+ m_context->texParameteri(target, pname, param);
+}
+
+int SharedGraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels)
+{
+ return m_context->texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+}
+
+int SharedGraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels)
+{
+ return m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+
+void SharedGraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* data)
+{
+ m_context->readPixels(x, y, width, height, format, type, data);
+}
+
+bool SharedGraphicsContext3D::supportsBGRA()
+{
+ return m_context->supportsBGRA();
+}
+
+Texture* SharedGraphicsContext3D::createTexture(NativeImagePtr ptr, Texture::Format format, int width, int height)
+{
+ RefPtr<Texture> texture = m_textures.get(ptr);
+ if (texture)
+ return texture.get();
+
+ texture = Texture::create(m_context.get(), format, width, height);
+ Texture* t = texture.get();
+ m_textures.set(ptr, texture);
+ return t;
+}
+
+Texture* SharedGraphicsContext3D::getTexture(NativeImagePtr ptr)
+{
+ RefPtr<Texture> texture = m_textures.get(ptr);
+ return texture ? texture.get() : 0;
+}
+
+PassRefPtr<Texture> SharedGraphicsContext3D::createTexture(Texture::Format format, int width, int height)
+{
+ return Texture::create(m_context.get(), format, width, height);
+}
+
+void SharedGraphicsContext3D::applyCompositeOperator(CompositeOperator op)
+{
+ switch (op) {
+ case CompositeClear:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::ZERO);
+ break;
+ case CompositeCopy:
+ m_context->disable(GraphicsContext3D::BLEND);
+ break;
+ case CompositeSourceOver:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
+ break;
+ case CompositeSourceIn:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::DST_ALPHA, GraphicsContext3D::ZERO);
+ break;
+ case CompositeSourceOut:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ZERO);
+ break;
+ case CompositeSourceAtop:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::DST_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
+ break;
+ case CompositeDestinationOver:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ONE);
+ break;
+ case CompositeDestinationIn:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::SRC_ALPHA);
+ break;
+ case CompositeDestinationOut:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
+ break;
+ case CompositeDestinationAtop:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::SRC_ALPHA);
+ break;
+ case CompositeXOR:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
+ break;
+ case CompositePlusDarker:
+ case CompositeHighlight:
+ // unsupported
+ m_context->disable(GraphicsContext3D::BLEND);
+ break;
+ case CompositePlusLighter:
+ m_context->enable(GraphicsContext3D::BLEND);
+ m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE);
+ break;
+ }
+}
+
+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 };
+ 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);
+ } else {
+ m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVertices);
+ }
+}
+
+void SharedGraphicsContext3D::setActiveTexture(unsigned textureUnit)
+{
+ m_context->activeTexture(textureUnit);
+}
+
+void SharedGraphicsContext3D::bindTexture(unsigned target, unsigned texture)
+{
+ m_context->bindTexture(target, texture);
+}
+
+void SharedGraphicsContext3D::useFillSolidProgram(const AffineTransform& transform, const Color& color)
+{
+ m_solidFillShader->use(transform, color);
+}
+
+void SharedGraphicsContext3D::useTextureProgram(const AffineTransform& transform, const AffineTransform& texTransform, float alpha)
+{
+ m_texShader->use(transform, texTransform, 0, alpha);
+}
+
+void SharedGraphicsContext3D::bindFramebuffer(unsigned framebuffer)
+{
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer);
+}
+
+void SharedGraphicsContext3D::setViewport(const IntSize& size)
+{
+ m_context->viewport(0, 0, size.width(), size.height());
+}
+
+bool SharedGraphicsContext3D::paintsIntoCanvasBuffer() const
+{
+ return m_context->paintsIntoCanvasBuffer();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
new file mode 100644
index 0000000..1baa0f6
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SharedGraphicsContext3D_h
+#define SharedGraphicsContext3D_h
+
+#include "GraphicsTypes.h"
+#include "ImageSource.h"
+#include "Texture.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class AffineTransform;
+class Color;
+class GraphicsContext3D;
+class FloatRect;
+class IntSize;
+class SolidFillShader;
+class TexShader;
+
+typedef HashMap<NativeImagePtr, RefPtr<Texture> > TextureHashMap;
+
+class SharedGraphicsContext3D : public RefCounted<SharedGraphicsContext3D> {
+public:
+ static PassRefPtr<SharedGraphicsContext3D> create(PassOwnPtr<GraphicsContext3D>);
+ ~SharedGraphicsContext3D();
+
+ // Functions that delegate directly to GraphicsContext3D, with caching
+ void makeContextCurrent();
+ void bindFramebuffer(unsigned framebuffer);
+ void setViewport(const IntSize&);
+ void scissor(const FloatRect&);
+ void enable(unsigned capacity);
+ void disable(unsigned capacity);
+ void clearColor(const Color&);
+ void clear(unsigned mask);
+ void drawArrays(unsigned long mode, long first, long count);
+ unsigned long getError();
+ void getIntegerv(unsigned long pname, int* value);
+
+ unsigned createFramebuffer();
+ unsigned createTexture();
+
+ void deleteFramebuffer(unsigned framebuffer);
+ void deleteTexture(unsigned texture);
+
+ void framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, unsigned, long level);
+ void texParameteri(unsigned target, unsigned pname, int param);
+ int texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels);
+ int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels);
+
+ void readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* data);
+
+ bool paintsIntoCanvasBuffer() const;
+
+ // Shared logic for canvas 2d
+ void applyCompositeOperator(CompositeOperator);
+ void useQuadVertices();
+
+ void useFillSolidProgram(const AffineTransform&, const Color&);
+ void useTextureProgram(const AffineTransform&, const AffineTransform&, float alpha);
+
+ void setActiveTexture(unsigned textureUnit);
+ void bindTexture(unsigned target, unsigned texture);
+
+ bool supportsBGRA();
+
+ // Creates a texture associated with the given image. Is owned by this context's
+ // TextureHashMap.
+ Texture* createTexture(NativeImagePtr, Texture::Format, int width, int height);
+ Texture* getTexture(NativeImagePtr);
+
+ // Creates a texture that is not associated with any image. The caller takes ownership of
+ // the texture.
+ PassRefPtr<Texture> createTexture(Texture::Format, int width, int height);
+
+private:
+ SharedGraphicsContext3D(PassOwnPtr<GraphicsContext3D> context);
+
+ OwnPtr<GraphicsContext3D> m_context;
+
+ unsigned m_quadVertices;
+
+ OwnPtr<SolidFillShader> m_solidFillShader;
+ OwnPtr<TexShader> m_texShader;
+
+ TextureHashMap m_textures;
+};
+
+} // namespace WebCore
+
+#endif // SharedGraphicsContext3D_h
diff --git a/WebCore/platform/graphics/gpu/Texture.cpp b/WebCore/platform/graphics/gpu/Texture.cpp
index 557603c..95436ba 100644
--- a/WebCore/platform/graphics/gpu/Texture.cpp
+++ b/WebCore/platform/graphics/gpu/Texture.cpp
@@ -32,10 +32,15 @@
#include "Texture.h"
+#include "FloatRect.h"
#include "GraphicsContext3D.h"
#include "IntRect.h"
+
+#include <algorithm>
#include <wtf/OwnArrayPtr.h>
+using namespace std;
+
namespace WebCore {
@@ -81,7 +86,6 @@ PassRefPtr<Texture> Texture::create(GraphicsContext3D* context, Format format, i
{
int maxTextureSize = 0;
context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize);
-
TilingData tiling(maxTextureSize, width, height, true);
int numTiles = tiling.numTiles();
@@ -120,15 +124,18 @@ static uint32_t* copySubRect(uint32_t* src, int srcX, int srcY, uint32_t* dst, i
if (!swizzle && width == srcStride)
return srcOffset;
- uint32_t* dstPixel = dst;
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width ; x++) {
- uint32_t pixel = srcOffset[x + y * srcStride];
- if (swizzle)
+ if (swizzle) {
+ uint32_t* dstPixel = dst;
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width ; ++x) {
+ uint32_t pixel = srcOffset[x + y * srcStride];
*dstPixel = pixel & 0xFF00FF00 | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16);
- else
- *dstPixel = pixel;
- dstPixel++;
+ dstPixel++;
+ }
+ }
+ } else {
+ for (int y = 0; y < height; ++y) {
+ memcpy(dst + y * width, srcOffset + y * srcStride, 4 * width);
}
}
return dst;
@@ -136,6 +143,11 @@ static uint32_t* copySubRect(uint32_t* src, int srcX, int srcY, uint32_t* dst, i
void Texture::load(void* pixels)
{
+ updateSubRect(pixels, IntRect(0, 0, m_tiles.totalSizeX(), m_tiles.totalSizeY()));
+}
+
+void Texture::updateSubRect(void* pixels, const IntRect updateRect)
+{
uint32_t* pixels32 = static_cast<uint32_t*>(pixels);
unsigned int glFormat = 0;
unsigned int glType = 0;
@@ -145,26 +157,42 @@ void Texture::load(void* pixels)
ASSERT(glFormat == GraphicsContext3D::RGBA && glType == GraphicsContext3D::UNSIGNED_BYTE);
// FIXME: This could use PBO's to save doing an extra copy here.
}
- OwnArrayPtr<uint32_t> tempBuff(new uint32_t[m_tiles.maxTextureSize() * m_tiles.maxTextureSize()]);
+ int tempBuffSize = // Temporary buffer size is the smaller of the max texture size or the updateRect
+ min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRect.width()) *
+ min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRect.height());
+ OwnArrayPtr<uint32_t> tempBuff(new uint32_t[tempBuffSize]);
+
+ for (int tile = 0; tile < m_tiles.numTiles(); tile++) {
+ // Intersect with tile
+ IntRect tileBoundsWithBorder = m_tiles.tileBoundsWithBorder(tile);
- for (int i = 0; i < m_tiles.numTiles(); i++) {
- IntRect tileBoundsWithBorder = m_tiles.tileBoundsWithBorder(i);
+ IntRect updateRectIntersected = updateRect;
+ updateRectIntersected.intersect(tileBoundsWithBorder);
+ IntRect dstRect = updateRectIntersected;
+ dstRect.move(-tileBoundsWithBorder.x(), -tileBoundsWithBorder.y());
+
+ if (updateRectIntersected.isEmpty())
+ continue;
+
+ // Copy sub rectangle out of larger pixel data
uint32_t* uploadBuff = 0;
if (swizzle) {
uploadBuff = copySubRect<true>(
- pixels32, tileBoundsWithBorder.x(), tileBoundsWithBorder.y(),
- tempBuff.get(), tileBoundsWithBorder.width(), tileBoundsWithBorder.height(), m_tiles.totalSizeX());
+ pixels32, updateRectIntersected.x(), updateRectIntersected.y(),
+ tempBuff.get(), updateRectIntersected.width(), updateRectIntersected.height(), m_tiles.totalSizeX());
} else {
uploadBuff = copySubRect<false>(
- pixels32, tileBoundsWithBorder.x(), tileBoundsWithBorder.y(),
- tempBuff.get(), tileBoundsWithBorder.width(), tileBoundsWithBorder.height(), m_tiles.totalSizeX());
+ pixels32, updateRectIntersected.x(), updateRectIntersected.y(),
+ tempBuff.get(), updateRectIntersected.width(), updateRectIntersected.height(), m_tiles.totalSizeX());
}
- m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_tileTextureIds->at(i));
- m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0,
- tileBoundsWithBorder.width(),
- tileBoundsWithBorder.height(), glFormat, glType, uploadBuff);
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_tileTextureIds->at(tile));
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0 /* level */,
+ dstRect.x(),
+ dstRect.y(),
+ updateRectIntersected.width(),
+ updateRectIntersected.height(), glFormat, glType, uploadBuff);
}
}
diff --git a/WebCore/platform/graphics/gpu/Texture.h b/WebCore/platform/graphics/gpu/Texture.h
index 7e4a72b..eda475e 100644
--- a/WebCore/platform/graphics/gpu/Texture.h
+++ b/WebCore/platform/graphics/gpu/Texture.h
@@ -41,6 +41,8 @@
namespace WebCore {
class GraphicsContext3D;
+class IntRect;
+
class Texture : public RefCounted<Texture> {
public:
~Texture();
@@ -48,6 +50,7 @@ public:
static PassRefPtr<Texture> create(GraphicsContext3D*, Format, int width, int height);
void bindTile(int tile);
void load(void* pixels);
+ void updateSubRect(void* pixels, const IntRect);
Format format() const { return m_format; }
const TilingData& tiles() const { return m_tiles; }
private:
diff --git a/WebCore/platform/graphics/gpu/TilingData.h b/WebCore/platform/graphics/gpu/TilingData.h
index f12e66e..1bdc51a 100644
--- a/WebCore/platform/graphics/gpu/TilingData.h
+++ b/WebCore/platform/graphics/gpu/TilingData.h
@@ -44,6 +44,7 @@ public:
int maxTextureSize() const { return m_maxTextureSize; }
int totalSizeX() const { return m_totalSizeX; }
int totalSizeY() const { return m_totalSizeY; }
+ int borderTexels() const { return m_borderTexels; }
int numTiles() const { return numTilesX() * numTilesY(); }
int numTilesX() const { return m_numTilesX; }
diff --git a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp
index 567da74..63555bf 100644
--- a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp
@@ -18,6 +18,7 @@
#include "config.h"
#include "DataSourceGStreamer.h"
+#if ENABLE(VIDEO)
#include <gio/gio.h>
#include <glib.h>
@@ -241,3 +242,5 @@ static void webkit_data_src_uri_handler_init(gpointer g_iface, gpointer iface_da
iface->get_uri = webkit_data_src_uri_get_uri;
iface->set_uri = webkit_data_src_uri_set_uri;
}
+
+#endif // ENABLE(VIDEO)
diff --git a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h
index 38f69b1..453685a 100644
--- a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h
@@ -19,6 +19,8 @@
#ifndef DataSourceGStreamer_h
#define DataSourceGStreamer_h
+#if ENABLE(VIDEO)
+
#include <glib-object.h>
#include <gst/base/gstbasesrc.h>
@@ -51,4 +53,5 @@ GType webkit_data_src_get_type(void);
G_END_DECLS
+#endif // ENABLE(VIDEO)
#endif
diff --git a/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp
index 75bf5e7..6333437 100644
--- a/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp
@@ -32,4 +32,4 @@ template <> void freeOwnedGPtr<GstElement>(GstElement* ptr)
}
}
-#endif
+#endif // ENABLE(VIDEO)
diff --git a/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h
index 6655f38..84a3e30 100644
--- a/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h
@@ -19,6 +19,7 @@
#ifndef GOwnPtrGStreamer_h
#define GOwnPtrGStreamer_h
+#if ENABLE(VIDEO)
#include "GOwnPtr.h"
@@ -30,4 +31,5 @@ template<> void freeOwnedGPtr<GstElement>(GstElement* ptr);
}
+#endif // ENABLE(VIDEO)
#endif
diff --git a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
index e1efdd4..2ff4f38 100644
--- a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
+++ b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
@@ -18,11 +18,10 @@
*/
#include "config.h"
-
#include "GStreamerGWorld.h"
+#if ENABLE(VIDEO)
#include "GOwnPtrGStreamer.h"
-
#include <gst/gst.h>
#include <gst/interfaces/xoverlay.h>
@@ -200,3 +199,4 @@ void GStreamerGWorld::setWindowOverlay(GstMessage* message)
}
}
+#endif // ENABLE(VIDEO)
diff --git a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h
index 659052a..282f13c 100644
--- a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h
+++ b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h
@@ -20,7 +20,6 @@
#ifndef GStreamerGWorld_h
#define GStreamerGWorld_h
-
#if ENABLE(VIDEO)
#include "PlatformVideoWindow.h"
@@ -63,5 +62,5 @@ private:
};
}
-#endif
+#endif // ENABLE(VIDEO)
#endif
diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamer.h b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h
index 9288df9..4a4ff2b 100644
--- a/WebCore/platform/graphics/gstreamer/ImageGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h
@@ -23,7 +23,6 @@
#if ENABLE(VIDEO)
#include "BitmapImage.h"
-
#include <gst/gst.h>
#include <gst/video/video.h>
#include <wtf/PassRefPtr.h>
@@ -60,6 +59,5 @@ class ImageGStreamer : public RefCounted<ImageGStreamer> {
};
}
-#endif
-
+#endif // ENABLE(VIDEO)
#endif
diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamerCG.mm b/WebCore/platform/graphics/gstreamer/ImageGStreamerCG.mm
index 421b90f..076df4a 100644
--- a/WebCore/platform/graphics/gstreamer/ImageGStreamerCG.mm
+++ b/WebCore/platform/graphics/gstreamer/ImageGStreamerCG.mm
@@ -19,6 +19,7 @@
#include "config.h"
#include "ImageGStreamer.h"
+#if ENABLE(VIDEO)
using namespace WebCore;
@@ -55,3 +56,5 @@ ImageGStreamer::~ImageGStreamer()
m_image = 0;
}
+
+#endif // ENABLE(VIDEO)
diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp b/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp
index aeaee19..2fed892 100644
--- a/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp
+++ b/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp
@@ -18,12 +18,13 @@
*/
#include "config.h"
+#include "ImageGStreamer.h"
+
+#if ENABLE(VIDEO)
#include "GOwnPtr.h"
-#include "ImageGStreamer.h"
using namespace std;
-
using namespace WebCore;
PassRefPtr<ImageGStreamer> ImageGStreamer::createImage(GstBuffer* buffer)
@@ -64,3 +65,4 @@ ImageGStreamer::~ImageGStreamer()
m_image = 0;
}
+#endif // ENABLE(VIDEO)
diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index 5628eb3..4791b4c 100644
--- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -22,11 +22,8 @@
*/
#include "config.h"
-
-#if ENABLE(VIDEO)
-
#include "MediaPlayerPrivateGStreamer.h"
-
+#if ENABLE(VIDEO)
#include "ColorSpace.h"
#include "DataSourceGStreamer.h"
@@ -49,14 +46,13 @@
#include "VideoSinkGStreamer.h"
#include "WebKitWebSourceGStreamer.h"
#include "Widget.h"
-#include <wtf/text/CString.h>
-
#include <GOwnPtr.h>
#include <gst/gst.h>
#include <gst/interfaces/mixer.h>
#include <gst/video/video.h>
#include <limits>
#include <math.h>
+#include <wtf/text/CString.h>
// GstPlayFlags flags from playbin2. It is the policy of GStreamer to
// not publicly expose element-specific enums. That's why this
@@ -843,8 +839,12 @@ void MediaPlayerPrivateGStreamer::updateStates()
// Try to figure out ready and network states.
if (state == GST_STATE_READY) {
- m_readyState = MediaPlayer::HaveNothing;
+ m_readyState = MediaPlayer::HaveMetadata;
m_networkState = MediaPlayer::Empty;
+ // Cache the duration without emiting the durationchange
+ // event because it's taken care of by the media element
+ // in this precise case.
+ cacheDuration();
} else if (maxTimeLoaded() == duration()) {
m_networkState = MediaPlayer::Loaded;
m_readyState = MediaPlayer::HaveEnoughData;
@@ -880,13 +880,6 @@ void MediaPlayerPrivateGStreamer::updateStates()
m_readyState = MediaPlayer::HaveEnoughData;
m_paused = false;
- if (!m_mediaDuration) {
- float newDuration = duration();
- m_mediaDurationKnown = !isinf(newDuration);
- if (m_mediaDurationKnown)
- m_mediaDuration = newDuration;
- }
-
if (m_buffering) {
m_readyState = MediaPlayer::HaveCurrentData;
m_networkState = MediaPlayer::Loading;
@@ -1119,7 +1112,7 @@ void MediaPlayerPrivateGStreamer::didEnd()
timeChanged();
}
-void MediaPlayerPrivateGStreamer::durationChanged()
+void MediaPlayerPrivateGStreamer::cacheDuration()
{
// Reset cached media duration
m_mediaDuration = 0;
@@ -1143,8 +1136,16 @@ void MediaPlayerPrivateGStreamer::durationChanged()
if (!isinf(newDuration))
m_mediaDuration = newDuration;
+}
- m_player->durationChanged();
+void MediaPlayerPrivateGStreamer::durationChanged()
+{
+ float previousDuration = m_mediaDuration;
+
+ cacheDuration();
+
+ if (m_mediaDuration != previousDuration)
+ m_player->durationChanged();
}
bool MediaPlayerPrivateGStreamer::supportsMuting() const
@@ -1266,6 +1267,7 @@ static HashSet<String> mimeTypeCache()
if (g_str_equal(name, "audio/x-vorbis")) {
cache.add(String("audio/ogg"));
+ cache.add(String("audio/x-vorbis+ogg"));
cached = true;
}
@@ -1460,4 +1462,4 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin()
}
-#endif
+#endif // ENABLE(VIDEO)
diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
index f2f684b..6d1392d 100644
--- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
@@ -22,7 +22,6 @@
#ifndef MediaPlayerPrivateGStreamer_h
#define MediaPlayerPrivateGStreamer_h
-
#if ENABLE(VIDEO)
#include <wtf/Forward.h>
@@ -132,6 +131,7 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
static bool isAvailable();
+ void cacheDuration();
void updateStates();
void cancelSeek();
void endPointTimerFired(Timer<MediaPlayerPrivateGStreamer>*);
@@ -179,5 +179,5 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
};
}
-#endif
+#endif // ENABLE(VIDEO)
#endif
diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h b/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h
index 8d99f05..3c4904b 100644
--- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h
+++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h
@@ -19,7 +19,6 @@
#ifndef PlatformVideoWindow_h
#define PlatformVideoWindow_h
-
#if ENABLE(VIDEO)
#include "Widget.h"
@@ -45,6 +44,5 @@ class PlatformVideoWindow : public RefCounted<PlatformVideoWindow> {
};
}
-#endif
-
+#endif // ENABLE(VIDEO)
#endif
diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp
index 5c0e6ea..68ab7ac 100644
--- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp
+++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp
@@ -19,6 +19,7 @@
#include "config.h"
#include "PlatformVideoWindow.h"
+#if ENABLE(VIDEO)
#include "NotImplemented.h"
@@ -33,3 +34,5 @@ PlatformVideoWindow::~PlatformVideoWindow()
{
notImplemented();
}
+
+#endif // ENABLE(VIDEO)
diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp
index c5f835c..88b6552 100644
--- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp
+++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp
@@ -19,8 +19,10 @@
#include "config.h"
#include "PlatformVideoWindow.h"
+#if ENABLE(VIDEO)
#include <gtk/gtk.h>
+
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h> // for GDK_WINDOW_XID
#endif
@@ -59,3 +61,4 @@ PlatformVideoWindow::~PlatformVideoWindow()
m_videoWindowId = 0;
}
+#endif // ENABLE(VIDEO)
diff --git a/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp
index dd8c3ee..00fef4b 100644
--- a/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp
@@ -28,6 +28,7 @@
#include "config.h"
#include "VideoSinkGStreamer.h"
+#if ENABLE(VIDEO)
#include <glib.h>
#include <gst/gst.h>
@@ -370,3 +371,4 @@ webkit_video_sink_new(void)
return (GstElement*)g_object_new(WEBKIT_TYPE_VIDEO_SINK, 0);
}
+#endif // ENABLE(VIDEO)
diff --git a/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h
index 4fb0b73..767e83f 100644
--- a/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h
@@ -20,6 +20,8 @@
#ifndef VideoSinkGStreamer_h
#define VideoSinkGStreamer_h
+#if ENABLE(VIDEO)
+
#include <glib-object.h>
#include <gst/video/gstvideosink.h>
@@ -75,4 +77,5 @@ GstElement *webkit_video_sink_new(void);
G_END_DECLS
+#endif // ENABLE(VIDEO)
#endif
diff --git a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
index 1059b59..bcd59c6 100644
--- a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
@@ -18,6 +18,7 @@
#include "config.h"
#include "WebKitWebSourceGStreamer.h"
+#if ENABLE(VIDEO)
#include "Document.h"
#include "GOwnPtr.h"
@@ -790,3 +791,5 @@ void StreamingClient::cannotShowURL(ResourceHandle*)
GST_ELEMENT_ERROR(m_src, RESOURCE, OPEN_READ, ("Can't show \"%s\"", m_src->priv->uri), (0));
}
+#endif // ENABLE(VIDEO)
+
diff --git a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h
index ae19640..1594062 100644
--- a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h
@@ -18,6 +18,7 @@
#ifndef WebKitWebSourceGStreamer_h
#define WebKitWebSourceGStreamer_h
+#if ENABLE(VIDEO)
#include "Frame.h"
#include <gst/gst.h>
@@ -49,4 +50,5 @@ void webKitWebSrcSetFrame(WebKitWebSrc* src, WebCore::Frame* frame);
G_END_DECLS
+#endif // ENABLE(VIDEO)
#endif
diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
index ab4ef4b..54b261c 100644
--- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
@@ -31,7 +31,6 @@
#import "BlockExceptions.h"
-#include "ANGLE/ResourceLimits.h"
#include "ArrayBuffer.h"
#include "ArrayBufferView.h"
#include "WebGLObject.h"
@@ -186,23 +185,23 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi
TBuiltInResource ANGLEResources;
- ANGLEResources.maxVertexAttribs = 0;
- getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.maxVertexAttribs);
- ANGLEResources.maxVertexUniformVectors = 0;
- getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.maxVertexUniformVectors);
- ANGLEResources.maxVaryingVectors = 0;
- getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.maxVaryingVectors);
- ANGLEResources.maxVertexTextureImageUnits = 0;
- getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.maxVertexTextureImageUnits);
- ANGLEResources.maxCombinedTextureImageUnits = 0;
- getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.maxCombinedTextureImageUnits);
- ANGLEResources.maxTextureImageUnits = 0;
- getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.maxTextureImageUnits);
- ANGLEResources.maxFragmentUniformVectors = 0;
- getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.maxFragmentUniformVectors);
+ ANGLEResources.MaxVertexAttribs = 0;
+ getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs);
+ ANGLEResources.MaxVertexUniformVectors = 0;
+ getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors);
+ ANGLEResources.MaxVaryingVectors = 0;
+ getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors);
+ ANGLEResources.MaxVertexTextureImageUnits = 0;
+ getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits);
+ ANGLEResources.MaxCombinedTextureImageUnits = 0;
+ getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits);
+ ANGLEResources.MaxTextureImageUnits = 0;
+ getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits);
+ ANGLEResources.MaxFragmentUniformVectors = 0;
+ getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors);
// Always set to 1 for OpenGL ES.
- ANGLEResources.maxDrawBuffers = 1;
+ ANGLEResources.MaxDrawBuffers = 1;
m_compiler.setResources(ANGLEResources);
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index 315cc00..5fedaff 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -272,16 +272,16 @@ static TransformationMatrix flipTransform()
}
#endif
-static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction& timingFunction)
-{
- switch (timingFunction.type()) {
- case LinearTimingFunction:
- return [CAMediaTimingFunction functionWithName:@"linear"];
- case CubicBezierTimingFunction:
- return [CAMediaTimingFunction functionWithControlPoints:static_cast<float>(timingFunction.x1()) :static_cast<float>(timingFunction.y1())
- :static_cast<float>(timingFunction.x2()) :static_cast<float>(timingFunction.y2())];
- }
- return 0;
+static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction* timingFunction)
+{
+ // By this point, timing functions can only be linear or cubic, not steps.
+ ASSERT(!timingFunction->isStepsTimingFunction());
+ if (timingFunction->isCubicBezierTimingFunction()) {
+ const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
+ return [CAMediaTimingFunction functionWithControlPoints:static_cast<float>(ctf->x1()) :static_cast<float>(ctf->y1())
+ :static_cast<float>(ctf->x2()) :static_cast<float>(ctf->y2())];
+ } else
+ return [CAMediaTimingFunction functionWithName:@"linear"];
}
static void setLayerBorderColor(PlatformLayer* layer, const Color& color)
@@ -356,6 +356,20 @@ static NSDictionary* nullActionsDictionary()
return actions;
}
+static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim)
+{
+ if (anim->timingFunction()->isStepsTimingFunction())
+ return true;
+
+ for (unsigned i = 0; i < valueList.size(); ++i) {
+ const TimingFunction* timingFunction = valueList.at(i)->timingFunction();
+ if (timingFunction && timingFunction->isStepsTimingFunction())
+ return true;
+ }
+
+ return false;
+}
+
PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
{
return new GraphicsLayerCA(client);
@@ -716,6 +730,11 @@ bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const Int
return false;
#endif
+ // CoreAnimation does not handle the steps() timing function. Fall back
+ // to software animation in that case.
+ if (animationHasStepsTimingFunction(valueList, anim))
+ return false;
+
bool createdAnimations = false;
if (valueList.property() == AnimatedPropertyWebkitTransform)
createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, keyframesName, timeOffset, boxSize);
@@ -1913,9 +1932,9 @@ CAMediaTimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const An
if (animValue->timingFunction())
tf = animValue->timingFunction();
else if (anim->isTimingFunctionSet())
- tf = &anim->timingFunction();
+ tf = anim->timingFunction().get();
- return getCAMediaTimingFunction(tf ? *tf : TimingFunction());
+ return getCAMediaTimingFunction(tf ? tf : CubicBezierTimingFunction::create().get());
}
bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, CABasicAnimation* basicAnim)
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
index 89badcc..e164f8c 100644
--- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
@@ -1213,7 +1213,7 @@ PlatformLayer* GraphicsLayerQt::platformLayer() const
template <typename T>
struct KeyframeValueQt {
- TimingFunction timingFunction;
+ const TimingFunction* timingFunction;
T value;
};
@@ -1230,23 +1230,32 @@ static inline double solveCubicBezierFunction(qreal p1x, qreal p1y, qreal p2x, q
return bezier.solve(t, solveEpsilon(duration));
}
-static inline qreal applyTimingFunction(const TimingFunction& timingFunction, qreal progress, double duration)
+static inline double solveStepsFunction(int numSteps, bool stepAtStart, double t)
+{
+ if (stepAtStart)
+ return qMin(1.0, (floor(numSteps * t) + 1) / numSteps);
+ return floor(numSteps * t) / numSteps;
+}
+
+static inline qreal applyTimingFunction(const TimingFunction* timingFunction, qreal progress, double duration)
{
// We want the timing function to be as close as possible to what the web-developer intended, so
// we're using the same function used by WebCore when compositing is disabled. Using easing-curves
// would probably work for some of the cases, but wouldn't really buy us anything as we'd have to
// convert the bezier function back to an easing curve.
- if (timingFunction.type() == LinearTimingFunction)
- return progress;
- if (timingFunction.type() == CubicBezierTimingFunction) {
- return solveCubicBezierFunction(timingFunction.x1(),
- timingFunction.y1(),
- timingFunction.x2(),
- timingFunction.y2(),
+ if (timingFunction->isCubicBezierTimingFunction()) {
+ const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
+ return solveCubicBezierFunction(ctf->x1(),
+ ctf->y1(),
+ ctf->x2(),
+ ctf->y2(),
double(progress), double(duration) / 1000);
- }
- return progress;
+ } else if (timingFunction->isStepsTimingFunction()) {
+ const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(timingFunction);
+ return solveStepsFunction(stf->numberOfSteps(), stf->stepAtStart(), double(progress));
+ } else
+ return progress;
}
// Helper functions to safely get a value out of WebCore's AnimationValue*.
@@ -1322,9 +1331,9 @@ public:
const AnimationValue* animationValue = values.at(i);
KeyframeValueQt<T> keyframeValue;
if (animationValue->timingFunction())
- keyframeValue.timingFunction = *animationValue->timingFunction();
+ keyframeValue.timingFunction = animationValue->timingFunction();
else
- keyframeValue.timingFunction = anim->timingFunction();
+ keyframeValue.timingFunction = anim->timingFunction().get();
webkitAnimationToQtAnimationValue(animationValue, keyframeValue.value);
m_keyframeValues[animationValue->keyTime()] = keyframeValue;
}
@@ -1381,7 +1390,7 @@ protected:
const KeyframeValueQt<T>& fromKeyframe = it.value();
const KeyframeValueQt<T>& toKeyframe = it2.value();
- const TimingFunction& timingFunc = fromKeyframe.timingFunction;
+ const TimingFunction* timingFunc = fromKeyframe.timingFunction;
const T& fromValue = fromKeyframe.value;
const T& toValue = toKeyframe.value;
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
index 4ad5571..605dcb7 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
@@ -604,6 +604,14 @@ PlatformLayer* MediaPlayerPrivate::platformLayer() const
}
#endif
+PlatformMedia MediaPlayerPrivate::platformMedia() const
+{
+ PlatformMedia pm;
+ pm.type = PlatformMedia::QtMediaPlayerType;
+ pm.media.qtMediaPlayer = const_cast<MediaPlayerPrivate*>(this);
+ return pm;
+}
+
} // namespace WebCore
#include "moc_MediaPlayerPrivateQt.cpp"
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
index 165efde..117187d 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
@@ -99,6 +99,7 @@ public:
virtual PlatformLayer* platformLayer() const;
#endif
+ virtual PlatformMedia platformMedia() const;
private slots:
void mediaStatusChanged(QMediaPlayer::MediaStatus);
void handleError(QMediaPlayer::Error);
diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp
index ce5da2e..df54684 100644
--- a/WebCore/platform/graphics/qt/PathQt.cpp
+++ b/WebCore/platform/graphics/qt/PathQt.cpp
@@ -264,6 +264,11 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
void Path::closeSubpath()
{
+ m_path.closeSubpath();
+}
+
+void Path::closeCanvasSubpath()
+{
const int elementCount = m_path.elementCount();
if (!elementCount)
@@ -469,6 +474,31 @@ void Path::transform(const AffineTransform& transform)
m_path = qTransform.map(m_path);
}
+float Path::length()
+{
+ return m_path.length();
+}
+
+FloatPoint Path::pointAtLength(float length, bool& ok)
+{
+ ok = (length >= 0 && length <= m_path.length());
+
+ qreal percent = m_path.percentAtLength(length);
+ QPointF point = m_path.pointAtPercent(percent);
+
+ return point;
+}
+
+float Path::normalAngleAtLength(float length, bool& ok)
+{
+ ok = (length >= 0 && length <= m_path.length());
+
+ qreal percent = m_path.percentAtLength(length);
+ qreal angle = m_path.angleAtPercent(percent);
+
+ return angle;
+}
+
}
// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp b/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
index b6d6e65..b6d6e65 100644
--- a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.h b/WebCore/platform/graphics/skia/FontCustomPlatformData.h
index d451c9c..d451c9c 100644
--- a/WebCore/platform/graphics/chromium/FontCustomPlatformData.h
+++ b/WebCore/platform/graphics/skia/FontCustomPlatformData.h
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index 1c80d49..d618c19 100644
--- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -1,10 +1,10 @@
/*
* Copyright (c) 2006, Google Inc. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -65,7 +65,7 @@ namespace {
inline int fastMod(int value, int max)
{
int sign = SkExtractSign(value);
-
+
value = SkApplySign(value, sign);
if (value >= max)
value %= max;
@@ -391,7 +391,7 @@ void GraphicsContext::canvasClip(const Path& path)
if (!isPathSkiaSafe(getCTM(), p))
return;
- platformContext()->canvas()->clipPath(p);
+ platformContext()->canvasClipPath(p);
}
void GraphicsContext::clipOut(const IntRect& rect)
@@ -499,7 +499,7 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin
if (numPoints <= 1)
return;
-
+
// FIXME: IMPLEMENT!!
}
@@ -767,7 +767,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
ClipRectToCanvas(*platformContext()->canvas(), r, &r);
}
- if (platformContext()->useGPU() && !m_common->state.fillPattern && !m_common->state.fillGradient && !platformContext()->getDrawLooper()) {
+ if (platformContext()->useGPU() && platformContext()->canAccelerate()) {
platformContext()->prepareForHardwareDraw();
platformContext()->gpuCanvas()->fillRect(rect);
return;
@@ -789,7 +789,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
if (paintingDisabled())
return;
- if (platformContext()->useGPU() && !m_common->state.fillPattern && !m_common->state.fillGradient) {
+ if (platformContext()->useGPU() && platformContext()->canAccelerate()) {
platformContext()->prepareForHardwareDraw();
platformContext()->gpuCanvas()->fillRect(rect, color, colorSpace);
return;
@@ -1240,14 +1240,19 @@ void GraphicsContext::translate(float w, float h)
WebCoreFloatToSkScalar(h));
}
-void GraphicsContext::setGraphicsContext3D(GraphicsContext3D* context3D, const IntSize& size)
+void GraphicsContext::syncSoftwareCanvas()
{
- platformContext()->setGraphicsContext3D(context3D, size);
+ platformContext()->syncSoftwareCanvas();
}
-void GraphicsContext::syncSoftwareCanvas()
+void GraphicsContext::setSharedGraphicsContext3D(SharedGraphicsContext3D* context, DrawingBuffer* framebuffer, const IntSize& size)
{
- platformContext()->syncSoftwareCanvas();
+ platformContext()->setSharedGraphicsContext3D(context, framebuffer, size);
+}
+
+void GraphicsContext::markDirtyRect(const IntRect& rect)
+{
+ platformContext()->markDirtyRect(rect);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index 9403406..2be7dc5 100644
--- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -36,10 +36,12 @@
#include "Base64.h"
#include "BitmapImage.h"
#include "BitmapImageSingleFrameSkia.h"
+#include "DrawingBuffer.h"
+#include "GLES2Canvas.h"
#include "GraphicsContext.h"
#include "ImageData.h"
-#include "PlatformContextSkia.h"
#include "PNGImageEncoder.h"
+#include "PlatformContextSkia.h"
#include "SkColorPriv.h"
#include "SkiaUtils.h"
@@ -67,9 +69,7 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b
m_data.m_platformContext.setCanvas(&m_data.m_canvas);
m_context.set(new GraphicsContext(&m_data.m_platformContext));
-#if OS(WINDOWS)
m_context->platformContext()->setDrawingToImageBuffer(true);
-#endif
// Make the background transparent. It would be nice if this wasn't
// required, but the canvas is currently filled with the magic transparency
@@ -100,14 +100,26 @@ PassRefPtr<Image> ImageBuffer::copyImage() const
void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
{
-#if OS(LINUX) || OS(WINDOWS)
context->platformContext()->beginLayerClippedToImage(rect, this);
-#endif
}
void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
CompositeOperator op, bool useLowQualityScale)
{
+ if (m_data.m_platformContext.useGPU() && context->platformContext()->useGPU()) {
+ if (context->platformContext()->canAccelerate()) {
+ DrawingBuffer* sourceDrawingBuffer = m_data.m_platformContext.gpuCanvas()->drawingBuffer();
+ unsigned sourceTexture = sourceDrawingBuffer->getRenderingResultsAsTexture();
+ FloatRect destRectFlipped(destRect);
+ destRectFlipped.setY(destRect.y() + destRect.height());
+ destRectFlipped.setHeight(-destRect.height());
+ context->platformContext()->prepareForHardwareDraw();
+ context->platformContext()->gpuCanvas()->drawTexturedRect(sourceTexture, m_size, srcRect, destRectFlipped, styleColorSpace, op);
+ return;
+ }
+ m_data.m_platformContext.syncSoftwareCanvas();
+ }
+
RefPtr<Image> image = BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap(), context == m_context);
context->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
}
diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp
index aed289f..9625b34 100644
--- a/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -47,6 +47,7 @@
#include "SkRect.h"
#include "SkShader.h"
#include "SkiaUtils.h"
+#include "Texture.h"
#include "skia/ext/image_operations.h"
#include "skia/ext/platform_canvas.h"
@@ -468,7 +469,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect,
if (normSrcRect.isEmpty() || normDstRect.isEmpty())
return; // Nothing to draw.
- if (ctxt->platformContext()->useGPU()) {
+ if (ctxt->platformContext()->useGPU() && ctxt->platformContext()->canAccelerate()) {
drawBitmapGLES2(ctxt, bm, normSrcRect, normDstRect, colorSpace, compositeOp);
return;
}
@@ -496,7 +497,7 @@ void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt,
if (normSrcRect.isEmpty() || normDstRect.isEmpty())
return; // Nothing to draw.
- if (ctxt->platformContext()->useGPU()) {
+ if (ctxt->platformContext()->useGPU() && ctxt->platformContext()->canAccelerate()) {
drawBitmapGLES2(ctxt, &m_nativeImage, srcRect, dstRect, styleColorSpace, compositeOp);
return;
}
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index 3b1d015..88fbcdd 100644..100755
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -1,10 +1,10 @@
/*
* Copyright (c) 2008, Google Inc. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -33,12 +33,13 @@
#include "PlatformContextSkia.h"
#include "AffineTransform.h"
-#include "CanvasLayerChromium.h"
+#include "DrawingBuffer.h"
#include "GLES2Canvas.h"
#include "GraphicsContext.h"
#include "GraphicsContext3D.h"
#include "ImageBuffer.h"
#include "NativeImageSkia.h"
+#include "SharedGraphicsContext3D.h"
#include "SkiaUtils.h"
#include "Texture.h"
#include "TilingData.h"
@@ -96,18 +97,19 @@ struct PlatformContextSkia::State {
// color to produce a new output color.
SkColor applyAlpha(SkColor) const;
-#if OS(LINUX) || OS(WINDOWS)
// If non-empty, the current State is clipped to this image.
SkBitmap m_imageBufferClip;
// If m_imageBufferClip is non-empty, this is the region the image is clipped to.
FloatRect m_clip;
-#endif
// This is a list of clipping paths which are currently active, in the
// order in which they were pushed.
WTF::Vector<SkPath> m_antiAliasClipPaths;
InterpolationQuality m_interpolationQuality;
+ // If we currently have a canvas (non-antialiased path) clip applied.
+ bool m_canvasClipApplied;
+
PlatformContextSkia::State cloneInheritedProperties();
private:
// Not supported.
@@ -133,6 +135,7 @@ PlatformContextSkia::State::State()
, m_dash(0)
, m_textDrawingMode(cTextFill)
, m_interpolationQuality(InterpolationHigh)
+ , m_canvasClipApplied(false)
{
}
@@ -153,12 +156,11 @@ PlatformContextSkia::State::State(const State& other)
, m_lineJoin(other.m_lineJoin)
, m_dash(other.m_dash)
, m_textDrawingMode(other.m_textDrawingMode)
-#if OS(LINUX) || OS(WINDOWS)
, m_imageBufferClip(other.m_imageBufferClip)
, m_clip(other.m_clip)
-#endif
, m_antiAliasClipPaths(other.m_antiAliasClipPaths)
, m_interpolationQuality(other.m_interpolationQuality)
+ , m_canvasClipApplied(other.m_canvasClipApplied)
{
// Up the ref count of these. saveRef does nothing if 'this' is NULL.
m_looper->safeRef();
@@ -181,7 +183,7 @@ PlatformContextSkia::State PlatformContextSkia::State::cloneInheritedProperties(
PlatformContextSkia::State state(*this);
// Everything is inherited except for the clip paths.
- state.m_antiAliasClipPaths.clear();
+ state.m_antiAliasClipPaths.clear();
return state;
}
@@ -203,9 +205,7 @@ SkColor PlatformContextSkia::State::applyAlpha(SkColor c) const
// Danger: canvas can be NULL.
PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas)
: m_canvas(canvas)
-#if OS(WINDOWS)
, m_drawingToImageBuffer(false)
-#endif
, m_useGPU(false)
, m_gpuCanvas(0)
, m_backingStoreState(None)
@@ -216,12 +216,8 @@ PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas)
PlatformContextSkia::~PlatformContextSkia()
{
-#if USE(ACCELERATED_COMPOSITING)
- if (m_gpuCanvas) {
- CanvasLayerChromium* layer = static_cast<CanvasLayerChromium*>(m_gpuCanvas->context()->platformLayer());
- layer->setPrepareTextureCallback(0);
- }
-#endif
+ if (m_gpuCanvas)
+ m_gpuCanvas->drawingBuffer()->setWillPublishCallback(0);
}
void PlatformContextSkia::setCanvas(skia::PlatformCanvas* canvas)
@@ -229,7 +225,6 @@ void PlatformContextSkia::setCanvas(skia::PlatformCanvas* canvas)
m_canvas = canvas;
}
-#if OS(WINDOWS)
void PlatformContextSkia::setDrawingToImageBuffer(bool value)
{
m_drawingToImageBuffer = value;
@@ -239,7 +234,6 @@ bool PlatformContextSkia::isDrawingToImageBuffer() const
{
return m_drawingToImageBuffer;
}
-#endif
void PlatformContextSkia::save()
{
@@ -248,17 +242,14 @@ void PlatformContextSkia::save()
m_stateStack.append(m_state->cloneInheritedProperties());
m_state = &m_stateStack.last();
-#if OS(LINUX) || OS(WINDOWS)
// The clip image only needs to be applied once. Reset the image so that we
// don't attempt to clip multiple times.
m_state->m_imageBufferClip.reset();
-#endif
// Save our native canvas.
canvas()->save();
}
-#if OS(LINUX) || OS(WINDOWS)
void PlatformContextSkia::beginLayerClippedToImage(const FloatRect& rect,
const ImageBuffer* imageBuffer)
{
@@ -287,7 +278,6 @@ void PlatformContextSkia::beginLayerClippedToImage(const FloatRect& rect,
m_state->m_imageBufferClip = *bitmap;
}
}
-#endif
void PlatformContextSkia::clipPathAntiAliased(const SkPath& clipPath)
{
@@ -306,12 +296,10 @@ void PlatformContextSkia::clipPathAntiAliased(const SkPath& clipPath)
void PlatformContextSkia::restore()
{
-#if OS(LINUX) || OS(WINDOWS)
if (!m_state->m_imageBufferClip.empty()) {
applyClipFromImage(m_state->m_clip, m_state->m_imageBufferClip);
canvas()->restore();
}
-#endif
if (!m_state->m_antiAliasClipPaths.isEmpty())
applyAntiAliasedClipPaths(m_state->m_antiAliasClipPaths);
@@ -337,7 +325,7 @@ void PlatformContextSkia::drawRect(SkRect rect)
// We do a fill of four rects to simulate the stroke of a border.
SkColor oldFillColor = m_state->m_fillColor;
- // setFillColor() will set the shader to NULL, so save a ref to it now.
+ // setFillColor() will set the shader to NULL, so save a ref to it now.
SkShader* oldFillShader = m_state->m_fillShader;
oldFillShader->safeRef();
setFillColor(m_state->m_strokeColor);
@@ -462,7 +450,7 @@ void PlatformContextSkia::setXfermodeMode(SkXfermode::Mode pdm)
void PlatformContextSkia::setFillColor(SkColor color)
{
m_state->m_fillColor = color;
- setFillShader(NULL);
+ setFillShader(0);
}
SkDrawLooper* PlatformContextSkia::getDrawLooper() const
@@ -483,7 +471,7 @@ void PlatformContextSkia::setStrokeStyle(StrokeStyle strokeStyle)
void PlatformContextSkia::setStrokeColor(SkColor strokeColor)
{
m_state->m_strokeColor = strokeColor;
- setStrokeShader(NULL);
+ setStrokeShader(0);
}
float PlatformContextSkia::getStrokeThickness() const
@@ -559,6 +547,12 @@ SkPath PlatformContextSkia::currentPathInLocalCoordinates() const
return localPath;
}
+void PlatformContextSkia::canvasClipPath(const SkPath& path)
+{
+ m_state->m_canvasClipApplied = true;
+ m_canvas->clipPath(path);
+}
+
void PlatformContextSkia::setFillRule(SkPath::FillType fr)
{
m_path.setFillType(fr);
@@ -630,7 +624,6 @@ bool PlatformContextSkia::hasImageResamplingHint() const
return !m_imageResamplingHintSrcSize.isEmpty() && !m_imageResamplingHintDstSize.isEmpty();
}
-#if OS(LINUX) || OS(WINDOWS)
void PlatformContextSkia::applyClipFromImage(const FloatRect& rect, const SkBitmap& imageBuffer)
{
// NOTE: this assumes the image mask contains opaque black for the portions that are to be shown, as such we
@@ -639,7 +632,6 @@ void PlatformContextSkia::applyClipFromImage(const FloatRect& rect, const SkBitm
paint.setXfermodeMode(SkXfermode::kDstIn_Mode);
m_canvas->drawBitmap(imageBuffer, SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()), &paint);
}
-#endif
void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths)
{
@@ -678,33 +670,47 @@ void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths)
m_canvas->restore();
}
-#if USE(ACCELERATED_COMPOSITING)
-class PrepareTextureCallbackImpl : public CanvasLayerChromium::PrepareTextureCallback {
+bool PlatformContextSkia::canAccelerate() const
+{
+ return !m_state->m_fillShader // Can't accelerate with a fill gradient or pattern.
+ && !m_state->m_looper // Can't accelerate with a shadow.
+ && !m_state->m_canvasClipApplied; // Can't accelerate with a clip to path applied.
+}
+
+class WillPublishCallbackImpl : public DrawingBuffer::WillPublishCallback {
public:
- static PassOwnPtr<PrepareTextureCallbackImpl> create(PlatformContextSkia* pcs)
+ static PassOwnPtr<WillPublishCallback> create(PlatformContextSkia* pcs)
{
- return new PrepareTextureCallbackImpl(pcs);
+ return adoptPtr(new WillPublishCallbackImpl(pcs));
}
- virtual void willPrepareTexture()
+ virtual void willPublish()
{
m_pcs->prepareForHardwareDraw();
}
+
private:
- explicit PrepareTextureCallbackImpl(PlatformContextSkia* pcs) : m_pcs(pcs) {}
+ explicit WillPublishCallbackImpl(PlatformContextSkia* pcs)
+ : m_pcs(pcs)
+ {
+ }
+
PlatformContextSkia* m_pcs;
};
-#endif
-void PlatformContextSkia::setGraphicsContext3D(GraphicsContext3D* context, const WebCore::IntSize& size)
+void PlatformContextSkia::setSharedGraphicsContext3D(SharedGraphicsContext3D* context, DrawingBuffer* drawingBuffer, const WebCore::IntSize& size)
{
- m_useGPU = true;
- m_gpuCanvas = new GLES2Canvas(context, size);
- m_uploadTexture.clear();
-#if USE(ACCELERATED_COMPOSITING)
- CanvasLayerChromium* layer = static_cast<CanvasLayerChromium*>(context->platformLayer());
- layer->setPrepareTextureCallback(PrepareTextureCallbackImpl::create(this));
-#endif
+ if (context && drawingBuffer) {
+ m_useGPU = true;
+ m_gpuCanvas = new GLES2Canvas(context, drawingBuffer, size);
+ m_uploadTexture.clear();
+ drawingBuffer->setWillPublishCallback(WillPublishCallbackImpl::create(this));
+ } else {
+ syncSoftwareCanvas();
+ m_uploadTexture.clear();
+ m_gpuCanvas.clear();
+ m_useGPU = false;
+ }
}
void PlatformContextSkia::prepareForSoftwareDraw() const
@@ -725,9 +731,7 @@ void PlatformContextSkia::prepareForSoftwareDraw() const
// of a compositing operation).
if (m_state->m_xferMode == SkXfermode::kSrcOver_Mode) {
- // Last drawn on hardware; clear out the canvas.
- m_canvas->getDevice()->eraseColor(0);
- // Start compositing into the empty canvas.
+ // Note that we have rendering results in both the hardware and software backing stores.
m_backingStoreState = Mixed;
} else {
readbackHardwareToSoftware();
@@ -780,17 +784,42 @@ void PlatformContextSkia::syncSoftwareCanvas() const
m_backingStoreState = Software;
}
+void PlatformContextSkia::markDirtyRect(const IntRect& rect)
+{
+ if (!m_useGPU)
+ return;
+
+ switch (m_backingStoreState) {
+ case Software:
+ case Mixed:
+ m_softwareDirtyRect.unite(rect);
+ return;
+ case Hardware:
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
void PlatformContextSkia::uploadSoftwareToHardware(CompositeOperator op) const
{
const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(false);
SkAutoLockPixels lock(bitmap);
- GraphicsContext3D* context = m_gpuCanvas->context();
+ SharedGraphicsContext3D* context = m_gpuCanvas->context();
if (!m_uploadTexture || m_uploadTexture->tiles().totalSizeX() < bitmap.width() || m_uploadTexture->tiles().totalSizeY() < bitmap.height())
- m_uploadTexture = Texture::create(context, Texture::BGRA8, bitmap.width(), bitmap.height());
- m_uploadTexture->load(bitmap.getPixels());
- IntRect rect(0, 0, bitmap.width(), bitmap.height());
+ m_uploadTexture = context->createTexture(Texture::BGRA8, bitmap.width(), bitmap.height());
+
+ m_uploadTexture->updateSubRect(bitmap.getPixels(), m_softwareDirtyRect);
AffineTransform identity;
- gpuCanvas()->drawTexturedRect(m_uploadTexture.get(), rect, rect, identity, 1.0, DeviceColorSpace, op);
+ gpuCanvas()->drawTexturedRect(m_uploadTexture.get(), m_softwareDirtyRect, m_softwareDirtyRect, identity, 1.0, DeviceColorSpace, op);
+ // Clear out the region of the software canvas we just uploaded.
+ m_canvas->save();
+ m_canvas->resetMatrix();
+ SkRect bounds = m_softwareDirtyRect;
+ m_canvas->clipRect(bounds, SkRegion::kReplace_Op);
+ m_canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
+ m_canvas->restore();
+ m_softwareDirtyRect.setWidth(0); // Clear dirty rect.
}
void PlatformContextSkia::readbackHardwareToSoftware() const
@@ -799,7 +828,8 @@ void PlatformContextSkia::readbackHardwareToSoftware() const
SkAutoLockPixels lock(bitmap);
int width = bitmap.width(), height = bitmap.height();
OwnArrayPtr<uint32_t> buf(new uint32_t[width]);
- GraphicsContext3D* context = m_gpuCanvas->context();
+ SharedGraphicsContext3D* context = m_gpuCanvas->context();
+ m_gpuCanvas->bindFramebuffer();
// Flips the image vertically.
for (int y = 0; y < height; ++y) {
uint32_t* pixels = bitmap.getAddr32(0, y);
@@ -814,6 +844,7 @@ void PlatformContextSkia::readbackHardwareToSoftware() const
}
}
}
+ m_softwareDirtyRect.unite(IntRect(0, 0, width, height)); // Mark everything as dirty.
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h
index 82edc16..4ba85d1 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.h
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -1,10 +1,10 @@
/*
* Copyright (c) 2008, Google Inc. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -35,7 +35,6 @@
#include "Noncopyable.h"
#include "SkDashPathEffect.h"
-#include "SkDeque.h"
#include "SkDrawLooper.h"
#include "SkPaint.h"
#include "SkPath.h"
@@ -46,9 +45,10 @@
namespace WebCore {
enum CompositeOperator;
+class DrawingBuffer;
class GLES2Canvas;
-class Texture;
class GraphicsContext3D;
+class Texture;
// This class holds the platform-specific state for GraphicsContext. We put
// most of our Skia wrappers on this class. In theory, a lot of this stuff could
@@ -78,7 +78,6 @@ public:
// to the constructor.
void setCanvas(skia::PlatformCanvas*);
-#if OS(WINDOWS)
// 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).
// If this is true the contents have not been marked up with the magic
@@ -86,7 +85,6 @@ public:
// correctly updated.
void setDrawingToImageBuffer(bool);
bool isDrawingToImageBuffer() const;
-#endif
void save();
void restore();
@@ -95,9 +93,7 @@ public:
// |rect|. This layer is implicitly restored when the next restore is
// invoked.
// NOTE: |imageBuffer| may be deleted before the |restore| is invoked.
-#if OS(LINUX) || OS(WINDOWS)
void beginLayerClippedToImage(const FloatRect&, const ImageBuffer*);
-#endif
void clipPathAntiAliased(const SkPath&);
// Sets up the common flags on a paint for antialiasing, effects, etc.
@@ -143,6 +139,8 @@ public:
void addPath(const SkPath&);
SkPath currentPathInLocalCoordinates() const;
+ void canvasClipPath(const SkPath&);
+
// Returns the fill color. The returned color has it's alpha adjusted
// by the current alpha.
SkColor effectiveFillColor() const;
@@ -180,8 +178,10 @@ public:
void setImageResamplingHint(const IntSize& srcSize, const FloatSize& dstSize);
void clearImageResamplingHint();
bool hasImageResamplingHint() const;
+
+ bool canAccelerate() const;
bool useGPU() { return m_useGPU; }
- void setGraphicsContext3D(GraphicsContext3D*, const IntSize&);
+ void setSharedGraphicsContext3D(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&);
GLES2Canvas* gpuCanvas() const { return m_gpuCanvas.get(); }
// Call these before making a call that manipulates the underlying
@@ -190,13 +190,12 @@ public:
void prepareForHardwareDraw() const;
// Call to force the skia::PlatformCanvas to contain all rendering results.
void syncSoftwareCanvas() const;
+ void markDirtyRect(const IntRect& rect);
private:
-#if OS(LINUX) || OS(WINDOWS)
// Used when restoring and the state has an image clip. Only shows the pixels in
// m_canvas that are also in imageBuffer.
void applyClipFromImage(const FloatRect&, const SkBitmap&);
-#endif
void applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths);
void uploadSoftwareToHardware(CompositeOperator) const;
@@ -218,17 +217,16 @@ private:
// Current path in global coordinates.
SkPath m_path;
- // Stores image sizes for a hint to compute image resampling modes.
+ // Stores image sizes for a hint to compute image resampling modes.
// Values are used in ImageSkia.cpp
IntSize m_imageResamplingHintSrcSize;
FloatSize m_imageResamplingHintDstSize;
-#if OS(WINDOWS)
bool m_drawingToImageBuffer;
-#endif
bool m_useGPU;
OwnPtr<GLES2Canvas> m_gpuCanvas;
mutable enum { None, Software, Mixed, Hardware } m_backingStoreState;
mutable RefPtr<Texture> m_uploadTexture;
+ mutable IntRect m_softwareDirtyRect;
};
}
diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index 7b65e96..0203d42 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -79,37 +79,37 @@ GraphicsContext::GraphicsContext(HDC hdc, bool hasAlpha)
// suitable for all clients?
void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
- if (mayCreateBitmap && hdc && inTransparencyLayer()) {
- if (dstRect.isEmpty())
- return;
-
- HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
-
- // 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);
-
- CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
- CGContextRef bitmapContext = CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8,
- info.bmWidthBytes, deviceRGB, kCGBitmapByteOrder32Little |
- (supportAlphaBlend ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst));
- CGColorSpaceRelease(deviceRGB);
-
- CGImageRef image = CGBitmapContextCreateImage(bitmapContext);
- CGContextDrawImage(m_data->m_cgContext.get(), dstRect, image);
-
- // Delete all our junk.
- CGImageRelease(image);
- CGContextRelease(bitmapContext);
- ::DeleteDC(hdc);
- ::DeleteObject(bitmap);
-
+ bool createdBitmap = mayCreateBitmap && (!m_data->m_hdc || inTransparencyLayer());
+ if (!createdBitmap) {
+ m_data->restore();
return;
}
- m_data->restore();
+ if (dstRect.isEmpty())
+ return;
+
+ HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+
+ // 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);
+
+ CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
+ CGContextRef bitmapContext = CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8,
+ info.bmWidthBytes, deviceRGB, kCGBitmapByteOrder32Little |
+ (supportAlphaBlend ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst));
+ CGColorSpaceRelease(deviceRGB);
+
+ CGImageRef image = CGBitmapContextCreateImage(bitmapContext);
+ CGContextDrawImage(m_data->m_cgContext.get(), dstRect, image);
+
+ // Delete all our junk.
+ CGImageRelease(image);
+ CGContextRelease(bitmapContext);
+ ::DeleteDC(hdc);
+ ::DeleteObject(bitmap);
}
void GraphicsContext::drawWindowsBitmap(WindowsBitmap* image, const IntPoint& point)
diff --git a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
index 94df6ae..a989c24 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
@@ -92,7 +92,8 @@ static void setRGBABitmapAlpha(unsigned char* bytes, size_t length, unsigned cha
void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
- if (!mayCreateBitmap || !hdc || !inTransparencyLayer()) {
+ bool createdBitmap = mayCreateBitmap && (!m_data->m_hdc || inTransparencyLayer());
+ if (!hdc || !createdBitmap) {
m_data->restore();
return;
}
diff --git a/WebCore/platform/graphics/win/GraphicsContextWin.cpp b/WebCore/platform/graphics/win/GraphicsContextWin.cpp
index 161b9c6..f1953e4 100644
--- a/WebCore/platform/graphics/win/GraphicsContextWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextWin.cpp
@@ -101,7 +101,7 @@ GraphicsContext::WindowsBitmap* GraphicsContext::createWindowsBitmap(IntSize siz
HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
// FIXME: Should a bitmap be created also when a shadow is set?
- if (mayCreateBitmap && inTransparencyLayer()) {
+ if (mayCreateBitmap && (!m_data->m_hdc || inTransparencyLayer())) {
if (dstRect.isEmpty())
return 0;
diff --git a/WebCore/platform/graphics/win/IconWin.cpp b/WebCore/platform/graphics/win/IconWin.cpp
index cc9343a..05959e0 100644
--- a/WebCore/platform/graphics/win/IconWin.cpp
+++ b/WebCore/platform/graphics/win/IconWin.cpp
@@ -23,6 +23,7 @@
#include "Icon.h"
#include "GraphicsContext.h"
+#include "LocalWindowsContext.h"
#include "PlatformString.h"
#include <tchar.h>
#include <windows.h>
@@ -90,11 +91,8 @@ void Icon::paint(GraphicsContext* context, const IntRect& r)
#if OS(WINCE)
context->drawIcon(m_hIcon, r, DI_NORMAL);
#else
- HDC hdc = context->getWindowsContext(r);
-
- DrawIconEx(hdc, r.x(), r.y(), m_hIcon, r.width(), r.height(), 0, 0, DI_NORMAL);
-
- context->releaseWindowsContext(hdc, r);
+ LocalWindowsContext windowContext(context, r);
+ DrawIconEx(windowContext.hdc(), r.x(), r.y(), m_hIcon, r.width(), r.height(), 0, 0, DI_NORMAL);
#endif
}
diff --git a/WebCore/platform/graphics/win/LocalWindowsContext.h b/WebCore/platform/graphics/win/LocalWindowsContext.h
new file mode 100755
index 0000000..c216140
--- /dev/null
+++ b/WebCore/platform/graphics/win/LocalWindowsContext.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LocalWindowsContext_h
+#define LocalWindowsContext_h
+
+#include "config.h"
+#include "GraphicsContext.h"
+
+namespace WebCore {
+
+class LocalWindowsContext : public Noncopyable {
+public:
+ LocalWindowsContext(GraphicsContext* graphicsContext, const IntRect& rect, bool supportAlphaBlend = true, bool mayCreateBitmap = true)
+ : m_graphicsContext(graphicsContext)
+ , m_rect(rect)
+ , m_supportAlphaBlend(supportAlphaBlend)
+ , m_mayCreateBitmap(mayCreateBitmap)
+ {
+ m_hdc = m_graphicsContext->getWindowsContext(m_rect, m_supportAlphaBlend, m_mayCreateBitmap);
+ }
+
+ ~LocalWindowsContext()
+ {
+ m_graphicsContext->releaseWindowsContext(m_hdc, m_rect, m_supportAlphaBlend, m_mayCreateBitmap);
+ }
+
+ HDC hdc() const { return m_hdc; }
+
+private:
+ GraphicsContext* m_graphicsContext;
+ HDC m_hdc;
+ IntRect m_rect;
+ bool m_supportAlphaBlend;
+ bool m_mayCreateBitmap;
+};
+
+} // namespace WebCore
+#endif // LocalWindowsContext_h
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
index 34f1135..c37f5d5 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -600,6 +600,7 @@ void MediaPlayerPrivate::paint(GraphicsContext* p, const IntRect& r)
bool usingTempBitmap = false;
OwnPtr<GraphicsContext::WindowsBitmap> bitmap;
+ // FIXME: use LocalWindowsContext.
HDC hdc = p->getWindowsContext(r);
if (!hdc) {
// The graphics context doesn't have an associated HDC so create a temporary
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
index 2a355c2..630a8af 100644
--- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
@@ -408,10 +408,7 @@ bool WKCACFLayerRenderer::createRenderer()
m_d3dDevice = device;
- D3DXMATRIXA16 projection;
- D3DXMatrixOrthoOffCenterRH(&projection, rect.left, rect.right, rect.top, rect.bottom, -1.0f, 1.0f);
-
- m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);
+ initD3DGeometry();
m_renderer = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice.get(), 0);