diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-07 11:22:47 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-07 11:22:47 +0100 |
commit | cfd86b747d32ac22246a1aa908eaa720c63a88c1 (patch) | |
tree | 24d68c6f61c464ecba1e05670b80390ea3b0e50c /Source/WebCore/platform/graphics | |
parent | 69d7c744c9de19d152dbe2d8e46eb7dfd4511d1a (diff) |
Imported WebKit commit 20271caf2e2c016d5cef40184cddeefeac4f1876 (http://svn.webkit.org/repository/webkit/trunk@133733)
New snapshot that contains all previous fixes as well as build fix for latest QtMultimedia API changes.
Diffstat (limited to 'Source/WebCore/platform/graphics')
129 files changed, 3412 insertions, 1229 deletions
diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h index 8fedc3e50..00387d64a 100644 --- a/Source/WebCore/platform/graphics/BitmapImage.h +++ b/Source/WebCore/platform/graphics/BitmapImage.h @@ -204,8 +204,8 @@ protected: virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator); #endif virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator); -#if USE(CG) - virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator, RespectImageOrientationEnum); +#if USE(CG) || PLATFORM(CHROMIUM) || USE(CAIRO) + virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator, RespectImageOrientationEnum) OVERRIDE; #endif #if (OS(WINCE) && !PLATFORM(QT)) diff --git a/Source/WebCore/platform/graphics/Font.cpp b/Source/WebCore/platform/graphics/Font.cpp index 38ce35425..b3bf322e5 100644 --- a/Source/WebCore/platform/graphics/Font.cpp +++ b/Source/WebCore/platform/graphics/Font.cpp @@ -75,6 +75,7 @@ Font::Font() , m_wordSpacing(0) , m_isPlatformFont(false) , m_needsTranscoding(false) + , m_typesettingFeatures(0) { } @@ -84,6 +85,7 @@ Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing) , m_wordSpacing(wordSpacing) , m_isPlatformFont(false) , m_needsTranscoding(fontTranscoder().needsTranscoding(fd)) + , m_typesettingFeatures(computeTypesettingFeatures()) { } @@ -92,6 +94,7 @@ Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMo , m_letterSpacing(0) , m_wordSpacing(0) , m_isPlatformFont(true) + , m_typesettingFeatures(computeTypesettingFeatures()) { m_fontDescription.setUsePrinterFont(isPrinterFont); m_fontDescription.setFontSmoothing(fontSmoothingMode); @@ -106,6 +109,7 @@ Font::Font(const Font& other) , m_wordSpacing(other.m_wordSpacing) , m_isPlatformFont(other.m_isPlatformFont) , m_needsTranscoding(other.m_needsTranscoding) + , m_typesettingFeatures(computeTypesettingFeatures()) { } @@ -117,6 +121,7 @@ Font& Font::operator=(const Font& other) m_wordSpacing = other.m_wordSpacing; m_isPlatformFont = other.m_isPlatformFont; m_needsTranscoding = other.m_needsTranscoding; + m_typesettingFeatures = other.m_typesettingFeatures; return *this; } @@ -148,6 +153,7 @@ void Font::update(PassRefPtr<FontSelector> fontSelector) const if (!m_fontFallbackList) m_fontFallbackList = FontFallbackList::create(); m_fontFallbackList->invalidate(fontSelector); + m_typesettingFeatures = computeTypesettingFeatures(); } void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const @@ -210,11 +216,7 @@ float Font::width(const TextRun& run, int& charsConsumed, String& glyphName) con charsConsumed = run.length(); glyphName = ""; - - if (codePath(run) != Complex) - return floatWidthForSimpleText(run); - - return floatWidthForComplexText(run); + return width(run); } #if !(PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN))) diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h index aabcb2e70..b60d9dd3d 100644 --- a/Source/WebCore/platform/graphics/Font.h +++ b/Source/WebCore/platform/graphics/Font.h @@ -121,47 +121,7 @@ public: FontRenderingMode renderingMode() const { return m_fontDescription.renderingMode(); } - TypesettingFeatures typesettingFeatures() const - { - TextRenderingMode textRenderingMode = m_fontDescription.textRenderingMode(); - TypesettingFeatures features = s_defaultTypesettingFeatures; - - switch(textRenderingMode) { - case AutoTextRendering: - break; - case OptimizeSpeed: - features &= ~(Kerning | Ligatures); - break; - case GeometricPrecision: - case OptimizeLegibility: - features |= Kerning | Ligatures; - break; - } - - switch (m_fontDescription.kerning()) { - case FontDescription::NoneKerning: - features &= ~Kerning; - break; - case FontDescription::NormalKerning: - features |= Kerning; - break; - case FontDescription::AutoKerning: - break; - } - - switch (m_fontDescription.commonLigaturesState()) { - case FontDescription::DisabledLigaturesState: - features &= ~Ligatures; - break; - case FontDescription::EnabledLigaturesState: - features |= Ligatures; - break; - case FontDescription::NormalLigaturesState: - break; - } - - return features; - } + TypesettingFeatures typesettingFeatures() const { return m_typesettingFeatures; } FontFamily& firstFamily() { return m_fontDescription.firstFamily(); } const FontFamily& family() const { return m_fontDescription.family(); } @@ -287,6 +247,48 @@ private: return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); } + TypesettingFeatures computeTypesettingFeatures() const + { + TextRenderingMode textRenderingMode = m_fontDescription.textRenderingMode(); + TypesettingFeatures features = s_defaultTypesettingFeatures; + + switch (textRenderingMode) { + case AutoTextRendering: + break; + case OptimizeSpeed: + features &= ~(Kerning | Ligatures); + break; + case GeometricPrecision: + case OptimizeLegibility: + features |= Kerning | Ligatures; + break; + } + + switch (m_fontDescription.kerning()) { + case FontDescription::NoneKerning: + features &= ~Kerning; + break; + case FontDescription::NormalKerning: + features |= Kerning; + break; + case FontDescription::AutoKerning: + break; + } + + switch (m_fontDescription.commonLigaturesState()) { + case FontDescription::DisabledLigaturesState: + features &= ~Ligatures; + break; + case FontDescription::EnabledLigaturesState: + features |= Ligatures; + break; + case FontDescription::NormalLigaturesState: + break; + } + + return features; + } + #if PLATFORM(QT) void initFormatForTextLayout(QTextLayout*) const; #endif @@ -299,6 +301,7 @@ private: short m_wordSpacing; bool m_isPlatformFont; bool m_needsTranscoding; + mutable TypesettingFeatures m_typesettingFeatures; // Caches values computed from m_fontDescription. }; inline Font::~Font() diff --git a/Source/WebCore/platform/graphics/FontCache.cpp b/Source/WebCore/platform/graphics/FontCache.cpp index 3fea6c235..f60883ab3 100644 --- a/Source/WebCore/platform/graphics/FontCache.cpp +++ b/Source/WebCore/platform/graphics/FontCache.cpp @@ -293,8 +293,8 @@ static FontDataCache* gFontDataCache = 0; const int cMaxInactiveFontData = 250; const int cTargetInactiveFontData = 200; #else -const int cMaxInactiveFontData = 50; // Pretty Low Threshold -const int cTargetInactiveFontData = 30; +const int cMaxInactiveFontData = 225; +const int cTargetInactiveFontData = 200; #endif static ListHashSet<RefPtr<SimpleFontData> >* gInactiveFontData = 0; diff --git a/Source/WebCore/platform/graphics/FontFallbackList.h b/Source/WebCore/platform/graphics/FontFallbackList.h index 88f1bc796..a14fb82ed 100644 --- a/Source/WebCore/platform/graphics/FontFallbackList.h +++ b/Source/WebCore/platform/graphics/FontFallbackList.h @@ -41,6 +41,29 @@ const int cAllFamiliesScanned = -1; class FontFallbackList : public RefCounted<FontFallbackList> { WTF_MAKE_NONCOPYABLE(FontFallbackList); public: + typedef HashMap<int, GlyphPageTreeNode*, DefaultHash<int>::Hash> GlyphPages; + + class GlyphPagesStateSaver { + public: + GlyphPagesStateSaver(FontFallbackList& fallbackList) + : m_fallbackList(fallbackList) + , m_pages(fallbackList.m_pages) + , m_pageZero(fallbackList.m_pageZero) + { + } + + ~GlyphPagesStateSaver() + { + m_fallbackList.m_pages = m_pages; + m_fallbackList.m_pageZero = m_pageZero; + } + + private: + FontFallbackList& m_fallbackList; + GlyphPages& m_pages; + GlyphPageTreeNode* m_pageZero; + }; + static PassRefPtr<FontFallbackList> create() { return adoptRef(new FontFallbackList()); } ~FontFallbackList() { releaseFontData(); } @@ -56,13 +79,6 @@ public: unsigned fontSelectorVersion() const { return m_fontSelectorVersion; } unsigned generation() const { return m_generation; } - struct GlyphPagesHashTraits : HashTraits<int> { - static const int minimumTableSize = 16; - }; - typedef HashMap<int, GlyphPageTreeNode*, DefaultHash<int>::Hash, GlyphPagesHashTraits> GlyphPages; - GlyphPageTreeNode* glyphPageZero() const { return m_pageZero; } - const GlyphPages& glyphPages() const { return m_pages; } - private: FontFallbackList(); @@ -80,8 +96,6 @@ private: void setPlatformFont(const FontPlatformData&); void releaseFontData(); - void setGlyphPageZero(GlyphPageTreeNode* pageZero) { m_pageZero = pageZero; } - void setGlyphPages(const GlyphPages& pages) { m_pages = pages; } mutable Vector<RefPtr<FontData>, 1> m_fontList; mutable GlyphPages m_pages; @@ -95,7 +109,6 @@ private: mutable bool m_loadingCustomFonts : 1; friend class Font; - friend class SVGTextRunRenderingContext; }; } diff --git a/Source/WebCore/platform/graphics/FontPlatformData.h b/Source/WebCore/platform/graphics/FontPlatformData.h index f7af70617..be82845ed 100644 --- a/Source/WebCore/platform/graphics/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/FontPlatformData.h @@ -181,7 +181,7 @@ public: #if USE(CG) || USE(SKIA_ON_MAC_CHROMIUM) ASSERT(m_font || !m_cgFont); #endif - uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, m_isPrinterFont << 4 | m_textOrientation << 3 | m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique }; + uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, static_cast<uintptr_t>(m_isPrinterFont << 4 | m_textOrientation << 3 | m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique) }; return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes); #elif USE(CAIRO) return PtrHash<cairo_scaled_font_t*>::hash(m_scaledFont); diff --git a/Source/WebCore/platform/graphics/FractionalLayoutSize.h b/Source/WebCore/platform/graphics/FractionalLayoutSize.h index 1071d8ae3..9ece2ed84 100644 --- a/Source/WebCore/platform/graphics/FractionalLayoutSize.h +++ b/Source/WebCore/platform/graphics/FractionalLayoutSize.h @@ -77,6 +77,12 @@ public: m_width *= scale; m_height *= scale; } + + void scale(float widthScale, float heightScale) + { + m_width *= widthScale; + m_height *= heightScale; + } FractionalLayoutSize expandedTo(const FractionalLayoutSize& other) const { @@ -94,6 +100,14 @@ public: { *this = expandedTo(FractionalLayoutSize()); } + + void clampToMinimumSize(const FractionalLayoutSize& minimumSize) + { + if (m_width < minimumSize.width()) + m_width = minimumSize.width(); + if (m_height < minimumSize.height()) + m_height = minimumSize.height(); + } FractionalLayoutSize transposedSize() const { diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.cpp b/Source/WebCore/platform/graphics/GraphicsContext3D.cpp index bc899472c..5f6942bf5 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/Source/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -116,9 +116,7 @@ bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format, *componentsPerPixel = 1; *bytesPerComponent = sizeof(GC3Dushort); break; -#if !PLATFORM(BLACKBERRY) case GraphicsContext3D::UNSIGNED_INT_24_8: -#endif case GraphicsContext3D::UNSIGNED_INT: *bytesPerComponent = sizeof(GC3Duint); break; @@ -149,7 +147,7 @@ GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum ty } CheckedInt<uint32_t> checkedValue(bytesPerComponent * componentsPerPixel); checkedValue *= width; - if (!checkedValue.valid()) + if (!checkedValue.isValid()) return GraphicsContext3D::INVALID_VALUE; unsigned int validRowSize = checkedValue.value(); unsigned int padding = 0; @@ -161,7 +159,7 @@ GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum ty // Last row needs no padding. checkedValue *= (height - 1); checkedValue += validRowSize; - if (!checkedValue.valid()) + if (!checkedValue.isValid()) return GraphicsContext3D::INVALID_VALUE; *imageSizeInBytes = checkedValue.value(); if (paddingInBytes) diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h index 99a21a2d4..4ede0f817 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext3D.h +++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h @@ -72,6 +72,7 @@ typedef QOpenGLContext* PlatformGraphicsContext3D; typedef QSurface* PlatformGraphicsSurface3D; #else typedef void* PlatformGraphicsContext3D; +typedef void* PlatformGraphicsSurface3D; #endif #if (PLATFORM(CHROMIUM) || PLATFORM(BLACKBERRY)) && USE(SKIA) @@ -947,7 +948,7 @@ public: bool reshapeFBOs(const IntSize&); void resolveMultisamplingIfNecessary(const IntRect& = IntRect()); -#if PLATFORM(QT) && USE(GRAPHICS_SURFACE) +#if (PLATFORM(QT) || PLATFORM(EFL)) && USE(GRAPHICS_SURFACE) void createGraphicsSurfaces(const IntSize&); #endif diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.cpp b/Source/WebCore/platform/graphics/GraphicsLayer.cpp index 3a32b5145..dd3b7a9df 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayer.cpp +++ b/Source/WebCore/platform/graphics/GraphicsLayer.cpp @@ -30,10 +30,12 @@ #include "GraphicsLayer.h" #include "FloatPoint.h" +#include "FloatRect.h" #include "GraphicsContext.h" #include "LayoutTypesInlineMethods.h" #include "RotateTransformOperation.h" #include "TextStream.h" +#include <wtf/HashMap.h> #include <wtf/text/CString.h> #include <wtf/text/StringBuilder.h> #include <wtf/text/WTFString.h> @@ -44,6 +46,13 @@ namespace WebCore { +typedef HashMap<const GraphicsLayer*, Vector<FloatRect> > RepaintMap; +static RepaintMap& repaintRectMap() +{ + DEFINE_STATIC_LOCAL(RepaintMap, map, ()); + return map; +} + void KeyframeValueList::insert(const AnimationValue* value) { for (size_t i = 0; i < m_values.size(); ++i) { @@ -80,6 +89,8 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client) , m_acceleratesDrawing(false) , m_maintainsPixelAlignment(false) , m_appliesPageScale(false) + , m_showDebugBorder(false) + , m_showRepaintCounter(false) , m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip) , m_contentsOrientation(CompositingCoordinatesTopDown) , m_parent(0) @@ -96,6 +107,7 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client) GraphicsLayer::~GraphicsLayer() { + resetTrackedRepaints(); ASSERT(!m_parent); // willBeDestroyed should have been called already. } @@ -364,7 +376,7 @@ void GraphicsLayer::getDebugBorderInfo(Color& color, float& width) const void GraphicsLayer::updateDebugIndicators() { - if (!GraphicsLayer::showDebugBorders()) + if (!isShowingDebugBorder()) return; Color borderColor; @@ -536,6 +548,28 @@ double GraphicsLayer::backingStoreMemoryEstimate() const return static_cast<double>(4 * size().width()) * size().height(); } +void GraphicsLayer::resetTrackedRepaints() +{ + repaintRectMap().remove(this); +} + +void GraphicsLayer::addRepaintRect(const FloatRect& repaintRect) +{ + if (m_client->isTrackingRepaints()) { + FloatRect largestRepaintRect(FloatPoint(), m_size); + largestRepaintRect.intersect(repaintRect); + RepaintMap::iterator repaintIt = repaintRectMap().find(this); + if (repaintIt == repaintRectMap().end()) { + Vector<FloatRect> repaintRects; + repaintRects.append(largestRepaintRect); + repaintRectMap().set(this, repaintRects); + } else { + Vector<FloatRect>& repaintRects = repaintIt->value; + repaintRects.append(largestRepaintRect); + } + } +} + void GraphicsLayer::writeIndent(TextStream& ts, int indent) { for (int i = 0; i != indent; ++i) @@ -658,7 +692,25 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeAsTextBe writeIndent(ts, indent + 1); ts << "(replicated layer"; if (behavior & LayerTreeAsTextDebug) - ts << " " << m_replicatedLayer;; + ts << " " << m_replicatedLayer; + ts << ")\n"; + } + + if (behavior & LayerTreeAsTextIncludeRepaintRects && repaintRectMap().contains(this) && !repaintRectMap().get(this).isEmpty()) { + writeIndent(ts, indent + 1); + ts << "(repaint rects\n"; + for (size_t i = 0; i < repaintRectMap().get(this).size(); ++i) { + if (repaintRectMap().get(this)[i].isEmpty()) + continue; + writeIndent(ts, indent + 2); + ts << "(rect "; + ts << repaintRectMap().get(this)[i].x() << " "; + ts << repaintRectMap().get(this)[i].y() << " "; + ts << repaintRectMap().get(this)[i].width() << " "; + ts << repaintRectMap().get(this)[i].height(); + ts << ")\n"; + } + writeIndent(ts, indent + 1); ts << ")\n"; } @@ -692,7 +744,7 @@ void showGraphicsLayerTree(const WebCore::GraphicsLayer* layer) if (!layer) return; - String output = layer->layerTreeAsText(LayerTreeAsTextDebug | LayerTreeAsTextIncludeVisibleRects); + String output = layer->layerTreeAsText(LayerTreeAsTextDebug | LayerTreeAsTextIncludeVisibleRects | LayerTreeAsTextIncludeTileCaches); fprintf(stderr, "%s\n", output.utf8().data()); } #endif diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.h b/Source/WebCore/platform/graphics/GraphicsLayer.h index e67a17eae..e2c82ba1b 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayer.h +++ b/Source/WebCore/platform/graphics/GraphicsLayer.h @@ -48,12 +48,15 @@ enum LayerTreeAsTextBehaviorFlags { LayerTreeAsTextBehaviorNormal = 0, LayerTreeAsTextDebug = 1 << 0, // Dump extra debugging info like layer addresses. LayerTreeAsTextIncludeVisibleRects = 1 << 1, + LayerTreeAsTextIncludeTileCaches = 1 << 2, + LayerTreeAsTextIncludeRepaintRects = 1 << 3 }; typedef unsigned LayerTreeAsTextBehavior; namespace WebCore { class FloatPoint3D; +class FloatRect; class GraphicsContext; class GraphicsLayerFactory; class Image; @@ -349,24 +352,26 @@ public: // For hosting this GraphicsLayer in a native layer hierarchy. virtual PlatformLayer* platformLayer() const { return 0; } - void dumpLayer(TextStream&, int indent = 0, LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const; - - int repaintCount() const { return m_repaintCount; } - int incrementRepaintCount() { return ++m_repaintCount; } - enum CompositingCoordinatesOrientation { CompositingCoordinatesTopDown, CompositingCoordinatesBottomUp }; // Flippedness of the contents of this layer. Does not affect sublayer geometry. virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation) { m_contentsOrientation = orientation; } CompositingCoordinatesOrientation contentsOrientation() const { return m_contentsOrientation; } - bool showDebugBorders() const { return m_client ? m_client->showDebugBorders(this) : false; } - bool showRepaintCounter() const { return m_client ? m_client->showRepaintCounter(this) : false; } - - void updateDebugIndicators(); - + void dumpLayer(TextStream&, int indent = 0, LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const; + + virtual void setShowDebugBorder(bool show) { m_showDebugBorder = show; } + bool isShowingDebugBorder() const { return m_showDebugBorder; } + + virtual void setShowRepaintCounter(bool show) { m_showRepaintCounter = show; } + bool isShowingRepaintCounter() const { return m_showRepaintCounter; } + + int repaintCount() const { return m_repaintCount; } + int incrementRepaintCount() { return ++m_repaintCount; } + virtual void setDebugBackgroundColor(const Color&) { } virtual void setDebugBorder(const Color&, float /*borderWidth*/) { } + // z-position is the z-equivalent of position(). It's only used for debugging purposes. virtual float zPosition() const { return m_zPosition; } virtual void setZPosition(float); @@ -401,7 +406,10 @@ public: bool usingTiledLayer() const { return m_usingTiledLayer; } - virtual TiledBacking* tiledBacking() { return 0; } + virtual TiledBacking* tiledBacking() const { return 0; } + + void resetTrackedRepaints(); + void addRepaintRect(const FloatRect&); #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL) // This allows several alternative GraphicsLayer implementations in the same port, @@ -410,6 +418,8 @@ public: static void setGraphicsLayerFactory(GraphicsLayerFactoryCallback); #endif + void updateDebugIndicators(); + protected: // Should be called from derived class destructors. Should call willBeDestroyed() on super. virtual void willBeDestroyed(); @@ -480,7 +490,9 @@ protected: bool m_acceleratesDrawing : 1; bool m_maintainsPixelAlignment : 1; bool m_appliesPageScale : 1; // Set for the layer which has the page scale applied to it. - + bool m_showDebugBorder : 1; + bool m_showRepaintCounter : 1; + GraphicsLayerPaintingPhase m_paintingPhase; CompositingCoordinatesOrientation m_contentsOrientation; // affects orientation of layer contents diff --git a/Source/WebCore/platform/graphics/GraphicsLayerAnimation.cpp b/Source/WebCore/platform/graphics/GraphicsLayerAnimation.cpp index 3aa25ac40..1b05d3f64 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayerAnimation.cpp +++ b/Source/WebCore/platform/graphics/GraphicsLayerAnimation.cpp @@ -22,11 +22,59 @@ #if USE(ACCELERATED_COMPOSITING) #include "GraphicsLayerAnimation.h" +#include "FractionalLayoutSize.h" #include "UnitBezier.h" #include <wtf/CurrentTime.h> namespace WebCore { +#if ENABLE(CSS_FILTERS) +static inline PassRefPtr<FilterOperation> blendFunc(FilterOperation* fromOp, FilterOperation* toOp, double progress, const IntSize& size, bool blendToPassthrough = false) +{ + ASSERT(toOp); + if (toOp->blendingNeedsRendererSize()) + return toOp->blend(fromOp, progress, LayoutSize(size.width(), size.height()), blendToPassthrough); + + return toOp->blend(fromOp, progress, blendToPassthrough); +} + + +static FilterOperations applyFilterAnimation(const FilterOperations* from, const FilterOperations* to, double progress, const IntSize& boxSize) +{ + // First frame of an animation. + if (!progress) + return *from; + + // Last frame of an animation. + if (progress == 1) + return *to; + + if (!from->operationsMatch(*to)) + return *to; + + FilterOperations result; + + size_t fromSize = from->operations().size(); + size_t toSize = to->operations().size(); + size_t size = std::max(fromSize, toSize); + for (size_t i = 0; i < size; i++) { + RefPtr<FilterOperation> fromOp = (i < fromSize) ? from->operations()[i].get() : 0; + RefPtr<FilterOperation> toOp = (i < toSize) ? to->operations()[i].get() : 0; + RefPtr<FilterOperation> blendedOp = toOp ? blendFunc(fromOp.get(), toOp.get(), progress, boxSize) : (fromOp ? blendFunc(0, fromOp.get(), progress, boxSize, true) : 0); + if (blendedOp) + result.operations().append(blendedOp); + else { + RefPtr<FilterOperation> identityOp = PassthroughFilterOperation::create(); + if (progress > 0.5) + result.operations().append(toOp ? toOp : identityOp); + else + result.operations().append(fromOp ? fromOp : identityOp); + } + } + + return result; +} +#endif static bool shouldReverseAnimationValue(Animation::AnimationDirection direction, int loopCount) { @@ -155,14 +203,23 @@ static TransformationMatrix applyTransformAnimation(const TransformOperations* f return matrix; } +static const TimingFunction* timingFunctionForAnimationValue(const AnimationValue* animValue, const Animation* anim) +{ + if (animValue->timingFunction()) + return animValue->timingFunction(); + if (anim->timingFunction()) + return anim->timingFunction().get(); + + return CubicBezierTimingFunction::defaultTimingFunction(); +} -GraphicsLayerAnimation::GraphicsLayerAnimation(const String& name, const KeyframeValueList& keyframes, const IntSize& boxSize, const Animation* animation, double timeOffset, bool listsMatch) +GraphicsLayerAnimation::GraphicsLayerAnimation(const String& name, const KeyframeValueList& keyframes, const IntSize& boxSize, const Animation* animation, double startTime, bool listsMatch) : m_keyframes(keyframes) , m_boxSize(boxSize) , m_animation(Animation::create(animation)) , m_name(name) , m_listsMatch(listsMatch) - , m_startTime(WTF::currentTime() - timeOffset) + , m_startTime(startTime) , m_pauseTime(0) , m_state(PlayingState) { @@ -177,6 +234,11 @@ void GraphicsLayerAnimation::applyInternal(Client* client, const AnimationValue* case AnimatedPropertyWebkitTransform: client->setAnimatedTransform(applyTransformAnimation(static_cast<const TransformAnimationValue*>(from)->value(), static_cast<const TransformAnimationValue*>(to)->value(), progress, m_boxSize, m_listsMatch)); return; +#if ENABLE(CSS_FILTERS) + case AnimatedPropertyWebkitFilter: + client->setAnimatedFilters(applyFilterAnimation(static_cast<const FilterAnimationValue*>(from)->value(), static_cast<const FilterAnimationValue*>(to)->value(), progress, m_boxSize)); + return; +#endif default: ASSERT_NOT_REACHED(); } @@ -233,7 +295,8 @@ void GraphicsLayerAnimation::apply(Client* client) return; } if (m_keyframes.size() == 2) { - normalizedValue = applyTimingFunction(m_animation->timingFunction().get(), normalizedValue, m_animation->duration()); + const TimingFunction* timingFunction = timingFunctionForAnimationValue(m_keyframes.at(0), m_animation.get()); + normalizedValue = applyTimingFunction(timingFunction, normalizedValue, m_animation->duration()); applyInternal(client, m_keyframes.at(0), m_keyframes.at(1), normalizedValue); return; } @@ -245,17 +308,17 @@ void GraphicsLayerAnimation::apply(Client* client) continue; normalizedValue = (normalizedValue - from->keyTime()) / (to->keyTime() - from->keyTime()); - normalizedValue = applyTimingFunction(from->timingFunction(), normalizedValue, m_animation->duration()); + const TimingFunction* timingFunction = timingFunctionForAnimationValue(from, m_animation.get()); + normalizedValue = applyTimingFunction(timingFunction, normalizedValue, m_animation->duration()); applyInternal(client, from, to, normalizedValue); break; } } -void GraphicsLayerAnimation::pause(double offset) +void GraphicsLayerAnimation::pause(double time) { - // FIXME: should apply offset here. setState(PausedState); - m_pauseTime = WTF::currentTime() - offset; + m_pauseTime = time; } void GraphicsLayerAnimations::add(const GraphicsLayerAnimation& animation) @@ -285,6 +348,15 @@ void GraphicsLayerAnimations::apply(GraphicsLayerAnimation::Client* client) m_animations[i].apply(client); } +GraphicsLayerAnimations GraphicsLayerAnimations::getActiveAnimations() const +{ + GraphicsLayerAnimations active; + for (size_t i = 0; i < m_animations.size(); ++i) { + if (m_animations[i].isActive()) + active.add(m_animations[i]); + } + return active; +} } #endif diff --git a/Source/WebCore/platform/graphics/GraphicsLayerAnimation.h b/Source/WebCore/platform/graphics/GraphicsLayerAnimation.h index e58279c6a..fe4c44a5e 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayerAnimation.h +++ b/Source/WebCore/platform/graphics/GraphicsLayerAnimation.h @@ -36,6 +36,9 @@ public: public: virtual void setAnimatedTransform(const TransformationMatrix&) = 0; virtual void setAnimatedOpacity(float) = 0; +#if ENABLE(CSS_FILTERS) + virtual void setAnimatedFilters(const FilterOperations&) = 0; +#endif }; GraphicsLayerAnimation() @@ -45,10 +48,20 @@ public: void apply(Client*); void pause(double); AnimationState state() const { return m_state; } - void setState(AnimationState s) { m_state = s; } + void setState(AnimationState s, double pauseTime = 0) + { + m_state = s; + m_pauseTime = pauseTime; + } AnimatedPropertyID property() const { return m_keyframes.property(); } bool isActive() const; String name() const { return m_name; } + IntSize boxSize() const { return m_boxSize; } + double startTime() const { return m_startTime; } + double pauseTime() const { return m_pauseTime; } + PassRefPtr<Animation> animation() const { return m_animation.get(); } + const KeyframeValueList& keyframes() const { return m_keyframes; } + bool listsMatch() const { return m_listsMatch; } private: void applyInternal(Client*, const AnimationValue* from, const AnimationValue* to, float progress); @@ -57,7 +70,6 @@ private: RefPtr<Animation> m_animation; String m_name; bool m_listsMatch; - bool m_hasBigRotation; double m_startTime; double m_pauseTime; AnimationState m_state; @@ -72,10 +84,15 @@ public: void pause(const String&, double); void apply(GraphicsLayerAnimation::Client*); bool isEmpty() const { return m_animations.isEmpty(); } + size_t size() const { return m_animations.size(); } + const Vector<GraphicsLayerAnimation>& animations() const { return m_animations; } + Vector<GraphicsLayerAnimation>& animations() { return m_animations; } bool hasRunningAnimations() const; bool hasActiveAnimationsOfType(AnimatedPropertyID type) const; + GraphicsLayerAnimations getActiveAnimations() const; + private: Vector<GraphicsLayerAnimation> m_animations; }; diff --git a/Source/WebCore/platform/graphics/GraphicsLayerClient.h b/Source/WebCore/platform/graphics/GraphicsLayerClient.h index 3e105ce6b..8b6bffd19 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayerClient.h +++ b/Source/WebCore/platform/graphics/GraphicsLayerClient.h @@ -82,8 +82,7 @@ public: // Page scale factor. virtual float pageScaleFactor() const { return 1; } - virtual bool showDebugBorders(const GraphicsLayer*) const = 0; - virtual bool showRepaintCounter(const GraphicsLayer*) const = 0; + virtual bool isTrackingRepaints() const { return false; } #ifndef NDEBUG // RenderLayerBacking overrides this to verify that it is not diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h index fe0aee0f6..4b71c3590 100644 --- a/Source/WebCore/platform/graphics/ImageBuffer.h +++ b/Source/WebCore/platform/graphics/ImageBuffer.h @@ -119,6 +119,8 @@ namespace WebCore { PlatformLayer* platformLayer() const; #endif + // FIXME: current implementations of this method have the restriction that they only work + // with textures that are RGB or RGBA format, and UNSIGNED_BYTE type. bool copyToPlatformTexture(GraphicsContext3D&, Platform3DObject, GC3Denum, bool, bool); void reportMemoryUsage(MemoryObjectInfo*) const; diff --git a/Source/WebCore/platform/graphics/ImageObserver.h b/Source/WebCore/platform/graphics/ImageObserver.h index 8b693d984..804cdeb97 100644 --- a/Source/WebCore/platform/graphics/ImageObserver.h +++ b/Source/WebCore/platform/graphics/ImageObserver.h @@ -26,6 +26,8 @@ #ifndef ImageObserver_h #define ImageObserver_h +#include <wtf/Forward.h> + namespace WebCore { class Image; @@ -44,6 +46,8 @@ public: virtual void animationAdvanced(const Image*) = 0; virtual void changedInRect(const Image*, const IntRect&) = 0; + + virtual void reportMemoryUsage(MemoryObjectInfo*) const = 0; }; } diff --git a/Source/WebCore/platform/graphics/ImageOrientation.cpp b/Source/WebCore/platform/graphics/ImageOrientation.cpp index 8a5854e63..dc2b9782b 100644 --- a/Source/WebCore/platform/graphics/ImageOrientation.cpp +++ b/Source/WebCore/platform/graphics/ImageOrientation.cpp @@ -41,17 +41,17 @@ AffineTransform ImageOrientation::transformFromDefault(const FloatSize& drawnSiz case OriginBottomRight: return AffineTransform(-1, 0, 0, -1, w, h); case OriginLeftBottom: - return AffineTransform( 0, 1, -1, 0, w, 0); - case OriginRightTop: return AffineTransform( 0, -1, 1, 0, 0, h); + case OriginRightTop: + return AffineTransform( 0, 1, -1, 0, w, 0); case OriginTopRight: return AffineTransform(-1, 0, 0, 1, w, 0); case OriginBottomLeft: return AffineTransform( 1, 0, 0, -1, 0, h); case OriginLeftTop: - return AffineTransform( 0, -1, -1, 0, w, h); - case OriginRightBottom: return AffineTransform( 0, 1, 1, 0, 0, 0); + case OriginRightBottom: + return AffineTransform( 0, -1, -1, 0, w, h); } ASSERT_NOT_REACHED(); return AffineTransform(); diff --git a/Source/WebCore/platform/graphics/ImageOrientation.h b/Source/WebCore/platform/graphics/ImageOrientation.h index 86be5fe77..b184dc2f7 100644 --- a/Source/WebCore/platform/graphics/ImageOrientation.h +++ b/Source/WebCore/platform/graphics/ImageOrientation.h @@ -36,13 +36,13 @@ class FloatSize; enum ImageOrientationEnum { // "TopLeft" means that the 0 row starts at the Top, the 0 column starts at the Left. OriginTopLeft = 1, // default - OriginTopRight = 2, // mirror along y-axes + OriginTopRight = 2, // mirror along y-axis OriginBottomRight = 3, // 180 degree rotation - OriginBottomLeft = 4, // mirror along the x-axes - OriginLeftTop = 5, // -90 degree rotation + mirror along x-axes - OriginRightTop = 6, // 90 degree rotation - OriginRightBottom = 7, // 90 degree rotation + mirror along x-axes - OriginLeftBottom = 8, // -90 degree rotation + OriginBottomLeft = 4, // mirror along the x-axis + OriginLeftTop = 5, // mirror along x-axis + 270 degree CW rotation + OriginRightTop = 6, // 90 degree CW rotation + OriginRightBottom = 7, // mirror along x-axis + 90 degree CW rotation + OriginLeftBottom = 8, // 270 degree CW rotation // All other values are "reserved" as of EXIF 2.2 DefaultImageOrientation = OriginTopLeft, }; @@ -76,6 +76,7 @@ public: } // This transform can be used for drawing an image according to the orientation. + // It should be used in a right-handed coordinate system. AffineTransform transformFromDefault(const FloatSize& drawnSize) const; inline bool operator==(const ImageOrientation& other) const { return other.m_orientation == m_orientation; } diff --git a/Source/WebCore/platform/graphics/ImageSource.cpp b/Source/WebCore/platform/graphics/ImageSource.cpp index abfa5988b..56857a43f 100644 --- a/Source/WebCore/platform/graphics/ImageSource.cpp +++ b/Source/WebCore/platform/graphics/ImageSource.cpp @@ -106,20 +106,19 @@ bool ImageSource::isSizeAvailable() IntSize ImageSource::size(RespectImageOrientationEnum shouldRespectOrientation) const { - // The JPEG and TIFF decoders need to be taught how to read EXIF, XMP, or IPTC data. - if (shouldRespectOrientation == RespectImageOrientation) - notImplemented(); - - return m_decoder ? m_decoder->size() : IntSize(); + return frameSizeAtIndex(0, shouldRespectOrientation); } IntSize ImageSource::frameSizeAtIndex(size_t index, RespectImageOrientationEnum shouldRespectOrientation) const { - // The JPEG and TIFF decoders need to be taught how to read EXIF, XMP, or IPTC data. - if (shouldRespectOrientation == RespectImageOrientation) - notImplemented(); + if (!m_decoder) + return IntSize(); + + IntSize size = m_decoder->frameSizeAtIndex(index); + if ((shouldRespectOrientation == RespectImageOrientation) && m_decoder->orientation().usesWidthAsHeight()) + return IntSize(size.height(), size.width()); - return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize(); + return size; } bool ImageSource::getHotSpot(IntPoint&) const @@ -182,9 +181,7 @@ float ImageSource::frameDurationAtIndex(size_t index) ImageOrientation ImageSource::orientationAtIndex(size_t) const { - // The JPEG and TIFF decoders need to be taught how to read EXIF, XMP, or IPTC data. - notImplemented(); - return DefaultImageOrientation; + return m_decoder ? m_decoder->orientation() : DefaultImageOrientation; } bool ImageSource::frameHasAlphaAtIndex(size_t index) diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h index be93e8701..bdeaaa0ab 100644 --- a/Source/WebCore/platform/graphics/MediaPlayer.h +++ b/Source/WebCore/platform/graphics/MediaPlayer.h @@ -193,7 +193,10 @@ public: virtual String mediaPlayerReferrer() const { return String(); } virtual String mediaPlayerUserAgent() const { return String(); } virtual CORSMode mediaPlayerCORSMode() const { return Unspecified; } + virtual void mediaPlayerEnterFullscreen() { } virtual void mediaPlayerExitFullscreen() { } + virtual bool mediaPlayerIsFullscreen() const { return false; } + virtual bool mediaPlayerIsFullscreenPermitted() const { return false; } virtual bool mediaPlayerIsVideo() const { return false; } virtual LayoutRect mediaPlayerContentBoxRect() const { return LayoutRect(); } virtual void mediaPlayerSetSize(const IntSize&) { } diff --git a/Source/WebCore/platform/graphics/SimpleFontData.cpp b/Source/WebCore/platform/graphics/SimpleFontData.cpp index 28fa5ab15..9e19a8298 100644 --- a/Source/WebCore/platform/graphics/SimpleFontData.cpp +++ b/Source/WebCore/platform/graphics/SimpleFontData.cpp @@ -41,6 +41,9 @@ using namespace std; namespace WebCore { +const float smallCapsFontSizeMultiplier = 0.7f; +const float emphasisMarkFontSizeMultiplier = 0.5f; + SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCustomFont, bool isLoading, bool isTextOrientationFallback) : m_maxCharWidth(-1) , m_avgCharWidth(-1) @@ -193,6 +196,26 @@ PassRefPtr<SimpleFontData> SimpleFontData::uprightOrientationFontData() const return m_derivedFontData->uprightOrientation; } +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +{ + if (!m_derivedFontData) + m_derivedFontData = DerivedFontData::create(isCustomFont()); + if (!m_derivedFontData->smallCaps) + m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFontSizeMultiplier); + + return m_derivedFontData->smallCaps; +} + +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +{ + if (!m_derivedFontData) + m_derivedFontData = DerivedFontData::create(isCustomFont()); + if (!m_derivedFontData->emphasisMark) + m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, emphasisMarkFontSizeMultiplier); + + return m_derivedFontData->emphasisMark; +} + PassRefPtr<SimpleFontData> SimpleFontData::brokenIdeographFontData() const { if (!m_derivedFontData) diff --git a/Source/WebCore/platform/graphics/TiledBacking.h b/Source/WebCore/platform/graphics/TiledBacking.h index 4108f122b..5187bdd4a 100644 --- a/Source/WebCore/platform/graphics/TiledBacking.h +++ b/Source/WebCore/platform/graphics/TiledBacking.h @@ -43,6 +43,7 @@ public: CoverageForVisibleArea = 0, CoverageForVerticalScrolling = 1 << 0, CoverageForHorizontalScrolling = 1 << 1, + CoverageForSlowScrolling = 1 << 2, // Indicates that we expect to paint a lot on scrolling. CoverageForScrolling = CoverageForVerticalScrolling | CoverageForHorizontalScrolling }; typedef unsigned TileCoverage; @@ -50,10 +51,16 @@ public: virtual void setTileCoverage(TileCoverage) = 0; virtual TileCoverage tileCoverage() const = 0; + virtual IntSize tileSize() const = 0; + virtual void forceRepaint() = 0; virtual void setScrollingPerformanceLoggingEnabled(bool) = 0; virtual bool scrollingPerformanceLoggingEnabled() const = 0; + + // Exposed for testing + virtual IntRect tileCoverageRect() const = 0; + }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm index 5d9ddd9cb..c16e8d062 100644 --- a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm +++ b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm @@ -1089,7 +1089,10 @@ MediaPlayer::MediaKeyException MediaPlayerPrivateAVFoundationObjC::addKey(const RetainPtr<AVAssetResourceLoadingRequest> avRequest = m_sessionIDToRequestMap.get(sessionID); RetainPtr<NSData> keyData = adoptNS([[NSData alloc] initWithBytes:keyPtr length:keyLength]); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" [avRequest.get() finishLoadingWithResponse:nil data:keyData.get() redirect:nil]; +#pragma clang diagnostic pop m_sessionIDToRequestMap.remove(sessionID); player()->keyAdded(keySystem, sessionID); diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp index c1a703acd..12fc69df8 100644 --- a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp @@ -379,20 +379,26 @@ void GraphicsLayerBlackBerry::setOpacity(float opacity) void GraphicsLayerBlackBerry::setContentsNeedsDisplay() { - if (m_contentsLayer) + if (m_contentsLayer) { m_contentsLayer->setNeedsDisplay(); + addRepaintRect(contentsRect()); + } } void GraphicsLayerBlackBerry::setNeedsDisplay() { - if (drawsContent()) + if (drawsContent()) { m_layer->setNeedsDisplay(); + addRepaintRect(FloatRect(FloatPoint(), m_size)); + } } void GraphicsLayerBlackBerry::setNeedsDisplayInRect(const FloatRect& rect) { - if (drawsContent()) + if (drawsContent()) { m_layer->setNeedsDisplayInRect(rect); + addRepaintRect(rect); + } } void GraphicsLayerBlackBerry::setContentsRect(const IntRect& rect) diff --git a/Source/WebCore/platform/graphics/blackberry/ImageBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/ImageBlackBerry.cpp index 8793298d1..07da9915e 100644 --- a/Source/WebCore/platform/graphics/blackberry/ImageBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/ImageBlackBerry.cpp @@ -23,17 +23,20 @@ #include "ImageBuffer.h" #include "SharedBuffer.h" +#include <BlackBerryPlatformResourceStore.h> + +using BlackBerry::Platform::ResourceData; +using BlackBerry::Platform::ResourceStore; + namespace WebCore { PassRefPtr<Image> Image::loadPlatformResource(const char *name) { - // RESOURCE_PATH is set by CMake in OptionsBlackBerry.cmake - String fullPath(RESOURCE_PATH); - String extension(".png"); - - fullPath = fullPath + name + extension; + ResourceData data = ResourceStore::instance()->requestResource(BlackBerry::Platform::String(name)); + if (!data.data()) + return BitmapImage::nullImage(); - RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(fullPath); + RefPtr<SharedBuffer> buffer = SharedBuffer::create(data.data(), data.len()); if (!buffer) return BitmapImage::nullImage(); diff --git a/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp b/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp index 4fd63cedd..ff86f38e1 100644 --- a/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp +++ b/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp @@ -47,8 +47,6 @@ #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> -#define ENABLE_SCISSOR 1 - #define DEBUG_LAYER_ANIMATIONS 0 // Show running animations as green. #define DEBUG_CLIPPING 0 @@ -159,6 +157,7 @@ LayerRenderer::LayerRenderer(GLES2Context* context) , m_context(context) , m_isRobustnessSupported(false) , m_needsCommit(false) + , m_stencilCleared(false) { if (makeContextCurrent()) { m_isRobustnessSupported = String(reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS))).contains("GL_EXT_robustness"); @@ -279,7 +278,7 @@ void LayerRenderer::setViewport(const IntRect& targetRect, const IntRect& clipRe glActiveTexture(GL_TEXTURE0); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); - glEnable(GL_STENCIL_TEST); + glDisable(GL_STENCIL_TEST); // If culling is enabled then we will cull the backface. glCullFace(GL_BACK); @@ -300,21 +299,18 @@ void LayerRenderer::setViewport(const IntRect& targetRect, const IntRect& clipRe glViewport(m_viewport.x(), m_viewport.y(), m_viewport.width(), m_viewport.height()); -#if ENABLE_SCISSOR glEnable(GL_SCISSOR_TEST); #if DEBUG_CLIPPING printf("LayerRenderer::compositeLayers(): clipping to (%d,%d %dx%d)\n", m_scissorRect.x(), m_scissorRect.y(), m_scissorRect.width(), m_scissorRect.height()); fflush(stdout); #endif glScissor(m_scissorRect.x(), m_scissorRect.y(), m_scissorRect.width(), m_scissorRect.height()); -#endif - glClearStencil(0); - glClearColor(0, 0, 0, 0); - GLenum buffersToClear = GL_STENCIL_BUFFER_BIT; - if (m_clearSurfaceOnDrawLayers) - buffersToClear |= GL_COLOR_BUFFER_BIT; - glClear(buffersToClear); + if (m_clearSurfaceOnDrawLayers) { + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + } + m_stencilCleared = false; } void LayerRenderer::compositeLayers(const TransformationMatrix& matrix, LayerCompositingThread* rootLayer) @@ -378,9 +374,7 @@ void LayerRenderer::compositeLayers(const TransformationMatrix& matrix, LayerCom m_context->swapBuffers(); -#if ENABLE_SCISSOR glDisable(GL_SCISSOR_TEST); -#endif glDisable(GL_STENCIL_TEST); // PR 147254, the EGL implementation crashes when the last bound texture @@ -523,10 +517,8 @@ void LayerRenderer::drawLayersOnSurfaces(const Vector<RefPtr<LayerCompositingThr // Otherwise, we just need to set viewport. if (surfaceLayers.size()) { useSurface(0); -#if ENABLE_SCISSOR glEnable(GL_SCISSOR_TEST); glScissor(m_scissorRect.x(), m_scissorRect.y(), m_scissorRect.width(), m_scissorRect.height()); -#endif } } @@ -851,9 +843,6 @@ void LayerRenderer::compositeLayersRecursive(LayerCompositingThread* layer, int layer->setVisible(layerVisible); - glStencilFunc(GL_EQUAL, stencilValue, 0xff); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - // Note that there are two types of layers: // 1. Layers that have their own GraphicsContext and can draw their contents on demand (layer->drawsContent() == true). // 2. Layers that are just containers of images/video/etc that don't own a GraphicsContext (layer->contents() == true). @@ -861,6 +850,11 @@ void LayerRenderer::compositeLayersRecursive(LayerCompositingThread* layer, int if ((layer->needsTexture() || layer->layerRendererSurface()) && layerVisible) { updateScissorIfNeeded(clipRect); + if (stencilValue) { + glStencilFunc(GL_EQUAL, stencilValue, 0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + } + if (layer->doubleSided()) glDisable(GL_CULL_FACE); else @@ -918,13 +912,16 @@ void LayerRenderer::compositeLayersRecursive(LayerCompositingThread* layer, int // If we need to mask to bounds but the transformation has a rotational component // to it, scissoring is not enough and we need to use the stencil buffer for clipping. -#if ENABLE_SCISSOR bool stencilClip = layer->masksToBounds() && hasRotationalComponent(layer->drawTransform()); -#else - bool stencilClip = layer->masksToBounds(); -#endif if (stencilClip) { + if (!m_stencilCleared) { + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + m_stencilCleared = true; + } + + glEnable(GL_STENCIL_TEST); glStencilFunc(GL_EQUAL, stencilValue, 0xff); glStencilOp(GL_KEEP, GL_INCR, GL_INCR); @@ -977,12 +974,14 @@ void LayerRenderer::compositeLayersRecursive(LayerCompositingThread* layer, int glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, &layer->getTransformedBounds()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + if (!stencilValue) + glDisable(GL_STENCIL_TEST); } } void LayerRenderer::updateScissorIfNeeded(const FloatRect& clipRect) { -#if ENABLE_SCISSOR #if DEBUG_CLIPPING printf("LayerRenderer::updateScissorIfNeeded(): clipRect=(%.2f,%.2f %.2fx%.2f)\n", clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height()); fflush(stdout); @@ -997,7 +996,6 @@ void LayerRenderer::updateScissorIfNeeded(const FloatRect& clipRect) fflush(stdout); #endif glScissor(m_scissorRect.x(), m_scissorRect.y(), m_scissorRect.width(), m_scissorRect.height()); -#endif } bool LayerRenderer::makeContextCurrent() diff --git a/Source/WebCore/platform/graphics/blackberry/LayerRenderer.h b/Source/WebCore/platform/graphics/blackberry/LayerRenderer.h index 353b7eca8..671c4a18d 100644 --- a/Source/WebCore/platform/graphics/blackberry/LayerRenderer.h +++ b/Source/WebCore/platform/graphics/blackberry/LayerRenderer.h @@ -212,6 +212,7 @@ private: LayerRenderingResults m_lastRenderingResults; bool m_needsCommit; + bool m_stencilCleared; }; } diff --git a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp index 142991cf5..5c0375356 100644 --- a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp +++ b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp @@ -417,6 +417,7 @@ bool LayerWebKitThread::filtersCanBeComposited(const FilterOperations& filters) case FilterOperation::REFERENCE: #if ENABLE(CSS_SHADERS) case FilterOperation::CUSTOM: + case FilterOperation::VALIDATED_CUSTOM: #endif return false; default: diff --git a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp index ea3c89550..7a9e484b5 100644 --- a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp @@ -39,6 +39,7 @@ #include "TimeRanges.h" #include "WebPageClient.h" +#include <BlackBerryPlatformDeviceInfo.h> #include <BlackBerryPlatformSettings.h> #include <FrameLoaderClientBlackBerry.h> #include <set> @@ -113,6 +114,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) #endif , m_userDrivenSeekTimer(this, &MediaPlayerPrivate::userDrivenSeekTimerFired) , m_lastSeekTime(0) + , m_lastLoadingTime(0) , m_lastSeekTimePending(false) , m_isAuthenticationChallenging(false) , m_waitMetadataTimer(this, &MediaPlayerPrivate::waitMetadataTimerFired) @@ -187,8 +189,11 @@ void MediaPlayerPrivate::prepareToPlay() void MediaPlayerPrivate::play() { - if (m_platformPlayer) + if (m_platformPlayer) { m_platformPlayer->play(); + if (m_platformPlayer->isMetadataReady()) + conditionallyGoFullscreenAfterPlay(); + } } void MediaPlayerPrivate::pause() @@ -336,8 +341,15 @@ PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const bool MediaPlayerPrivate::didLoadingProgress() const { - notImplemented(); - return false; + if (!m_platformPlayer) + return false; + + float bufferLoaded = m_platformPlayer->bufferLoaded(); + if (bufferLoaded == m_lastLoadingTime) + return false; + + m_lastLoadingTime = bufferLoaded; + return true; } void MediaPlayerPrivate::setSize(const IntSize&) @@ -663,6 +675,7 @@ void MediaPlayerPrivate::waitMetadataTimerFired(Timer<MediaPlayerPrivate>*) { if (m_platformPlayer->isMetadataReady()) { m_platformPlayer->playWithMetadataReady(); + conditionallyGoFullscreenAfterPlay(); m_waitMetadataPopDialogCounter = 0; return; } @@ -679,9 +692,10 @@ void MediaPlayerPrivate::waitMetadataTimerFired(Timer<MediaPlayerPrivate>*) if (!wait) onPauseNotified(); else { - if (m_platformPlayer->isMetadataReady()) + if (m_platformPlayer->isMetadataReady()) { m_platformPlayer->playWithMetadataReady(); - else + conditionallyGoFullscreenAfterPlay(); + } else m_waitMetadataTimer.startOneShot(checkMetadataReadyInterval); } } @@ -963,6 +977,29 @@ void MediaPlayerPrivate::drawBufferingAnimation(const TransformationMatrix& matr } #endif +void MediaPlayerPrivate::conditionallyGoFullscreenAfterPlay() +{ + BlackBerry::Platform::DeviceInfo* info = BlackBerry::Platform::DeviceInfo::instance(); + if (hasVideo() && m_webCorePlayer->mediaPlayerClient()->mediaPlayerIsFullscreenPermitted() && info->isMobile()) { + // This is a mobile device (small screen), not a tablet, so we + // enter fullscreen video on user-initiated plays. + bool nothingIsFullscreen = !m_webCorePlayer->mediaPlayerClient()->mediaPlayerIsFullscreen(); +#if ENABLE(FULLSCREEN_API) + if (m_webCorePlayer->mediaPlayerClient()->mediaPlayerOwningDocument()->webkitIsFullScreen()) + nothingIsFullscreen = false; +#endif + if (nothingIsFullscreen && currentTime() == 0.0f) { + // Only enter fullscreen when playing from the beginning. Doing + // so on every play is sure to annoy the user who does not want + // to watch the video fullscreen. Note that the following call + // will fail if we are not here due to a user gesture, as per the + // check in Document::requestFullScreenForElement() to prevent + // popups. + m_webCorePlayer->mediaPlayerClient()->mediaPlayerEnterFullscreen(); + } + } +} + } // namespace WebCore #endif // ENABLE(VIDEO) diff --git a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h index 7b6654dce..c055abc5e 100644 --- a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h +++ b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h @@ -170,9 +170,11 @@ private: bool m_mediaIsBuffering; #endif + void conditionallyGoFullscreenAfterPlay(); void userDrivenSeekTimerFired(Timer<MediaPlayerPrivate>*); Timer<MediaPlayerPrivate> m_userDrivenSeekTimer; float m_lastSeekTime; + mutable float m_lastLoadingTime; bool m_lastSeekTimePending; bool m_isAuthenticationChallenging; void waitMetadataTimerFired(Timer<MediaPlayerPrivate>*); diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp index a74bb1cd0..e36b5e707 100644 --- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp +++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp @@ -286,8 +286,6 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) } m_layer = PlatformCALayer::create(layerType, this); - - updateDebugIndicators(); noteLayerPropertyChanged(ContentsScaleChanged); } @@ -520,7 +518,7 @@ void GraphicsLayerCA::setMasksToBounds(bool masksToBounds) return; GraphicsLayer::setMasksToBounds(masksToBounds); - noteLayerPropertyChanged(MasksToBoundsChanged); + noteLayerPropertyChanged(MasksToBoundsChanged | DebugIndicatorsChanged); } void GraphicsLayerCA::setDrawsContent(bool drawsContent) @@ -529,7 +527,7 @@ void GraphicsLayerCA::setDrawsContent(bool drawsContent) return; GraphicsLayer::setDrawsContent(drawsContent); - noteLayerPropertyChanged(DrawsContentChanged); + noteLayerPropertyChanged(DrawsContentChanged | DebugIndicatorsChanged); } void GraphicsLayerCA::setContentsVisible(bool contentsVisible) @@ -670,6 +668,8 @@ void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& r) m_dirtyRects[0].unite(rect); noteLayerPropertyChanged(DirtyRectsChanged); + + addRepaintRect(rect); } void GraphicsLayerCA::setContentsNeedsDisplay() @@ -910,7 +910,7 @@ void GraphicsLayerCA::flushCompositingStateForThisLayerOnly() commitLayerChangesAfterSublayers(); } -TiledBacking* GraphicsLayerCA::tiledBacking() +TiledBacking* GraphicsLayerCA::tiledBacking() const { return m_layer->tiledBacking(); } @@ -943,11 +943,14 @@ FloatRect GraphicsLayerCA::computeVisibleRect(TransformState& state) const } } - state.applyTransform(layerTransform, accumulation); + bool applyWasClamped; + state.applyTransform(layerTransform, accumulation, &applyWasClamped); - FloatRect clipRectForChildren = state.mappedQuad().boundingBox(); + bool mapWasClamped; + FloatRect clipRectForChildren = state.mappedQuad(&mapWasClamped).boundingBox(); FloatRect clipRectForSelf(0, 0, m_size.width(), m_size.height()); - clipRectForSelf.intersect(clipRectForChildren); + if (!applyWasClamped && !mapWasClamped) + clipRectForSelf.intersect(clipRectForChildren); if (masksToBounds()) { ASSERT(accumulation == TransformState::FlattenTransform); @@ -1039,7 +1042,7 @@ bool GraphicsLayerCA::platformCALayerShowRepaintCounter(PlatformCALayer* platfor if (m_isPageTileCacheLayer && platformLayer) return false; - return showRepaintCounter(); + return isShowingRepaintCounter(); } void GraphicsLayerCA::platformCALayerPaintContents(GraphicsContext& context, const IntRect& clip) @@ -1146,6 +1149,9 @@ void GraphicsLayerCA::commitLayerChangesBeforeSublayers(float pageScaleFactor, c if (m_uncommittedChanges & AcceleratesDrawingChanged) updateAcceleratesDrawing(); + if (m_uncommittedChanges & DebugIndicatorsChanged) + updateDebugBorder(); + if (m_uncommittedChanges & ChildrenChanged) { updateSublayerList(); // Sublayers may set this flag again, so clear it to avoid always updating sublayers in commitLayerChangesAfterSublayers(). @@ -1184,54 +1190,47 @@ void GraphicsLayerCA::updateLayerNames() void GraphicsLayerCA::updateSublayerList() { - PlatformCALayerList newSublayers; - const Vector<GraphicsLayer*>& childLayers = children(); + const PlatformCALayerList* customSublayers = m_layer->customSublayers(); - if (const PlatformCALayerList* customSublayers = m_layer->customSublayers()) - newSublayers.appendRange(customSublayers->begin(), customSublayers->end()); + PlatformCALayerList structuralLayerChildren; + PlatformCALayerList primaryLayerChildren; + + PlatformCALayerList& childListForSublayers = m_structuralLayer ? structuralLayerChildren : primaryLayerChildren; + + if (customSublayers) + primaryLayerChildren.append(*customSublayers); + + if (m_structuralLayer) { + if (m_replicaLayer) + structuralLayerChildren.append(static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer()); - if (m_structuralLayer || m_contentsLayer || childLayers.size() > 0) { - if (m_structuralLayer) { - // Add the replica layer first. - if (m_replicaLayer) - newSublayers.append(static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer()); - // Add the primary layer. Even if we have negative z-order children, the primary layer always comes behind. - newSublayers.append(m_layer); - } else if (m_contentsLayer && m_contentsVisible) { - // FIXME: add the contents layer in the correct order with negative z-order children. - // This does not cause visible rendering issues because currently contents layers are only used - // for replaced elements that don't have children. - newSublayers.append(m_contentsLayer); - } - - size_t numChildren = childLayers.size(); - for (size_t i = 0; i < numChildren; ++i) { - GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); - PlatformCALayer* childLayer = curChild->layerForSuperlayer(); - newSublayers.append(childLayer); - } + structuralLayerChildren.append(m_layer); + } - for (size_t i = 0; i < newSublayers.size(); --i) - newSublayers[i]->removeFromSuperlayer(); + if (m_contentsLayer && m_contentsVisible) { + // FIXME: add the contents layer in the correct order with negative z-order children. + // This does not cause visible rendering issues because currently contents layers are only used + // for replaced elements that don't have children. + primaryLayerChildren.append(m_contentsLayer); } + const Vector<GraphicsLayer*>& childLayers = children(); + size_t numChildren = childLayers.size(); + for (size_t i = 0; i < numChildren; ++i) { + GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); + PlatformCALayer* childLayer = curChild->layerForSuperlayer(); + childListForSublayers.append(childLayer); + } + #ifdef VISIBLE_TILE_WASH if (m_visibleTileWashLayer) - newSublayers.append(m_visibleTileWashLayer); + childListForSublayers.append(m_visibleTileWashLayer); #endif - if (m_structuralLayer) { - m_structuralLayer->setSublayers(newSublayers); - - if (m_contentsLayer) { - // If we have a transform layer, then the contents layer is parented in the - // primary layer (which is itself a child of the transform layer). - m_layer->removeAllSublayers(); - if (m_contentsVisible) - m_layer->appendSublayer(m_contentsLayer.get()); - } - } else - m_layer->setSublayers(newSublayers); + if (m_structuralLayer) + m_structuralLayer->setSublayers(structuralLayerChildren); + + m_layer->setSublayers(primaryLayerChildren); } void GraphicsLayerCA::updateGeometry(float pageScaleFactor, const FloatPoint& positionRelativeToBase) @@ -1345,8 +1344,6 @@ void GraphicsLayerCA::updateMasksToBounds() for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) it->value->setMasksToBounds(m_masksToBounds); } - - updateDebugIndicators(); } void GraphicsLayerCA::updateContentsVisibility() @@ -1356,7 +1353,7 @@ void GraphicsLayerCA::updateContentsVisibility() if (m_drawsContent) m_layer->setNeedsDisplay(); } else { - m_layer.get()->setContents(0); + m_layer->setContents(0); if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); @@ -1368,7 +1365,7 @@ void GraphicsLayerCA::updateContentsVisibility() void GraphicsLayerCA::updateContentsOpaque() { - m_layer.get()->setOpaque(m_contentsOpaque); + m_layer->setOpaque(m_contentsOpaque); if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); @@ -1401,9 +1398,9 @@ void GraphicsLayerCA::updateBackfaceVisibility() #if ENABLE(CSS_FILTERS) void GraphicsLayerCA::updateFilters() { - primaryLayer()->setFilters(m_filters); + m_layer->setFilters(m_filters); - if (LayerMap* layerCloneMap = primaryLayerClones()) { + if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { if (m_replicaLayer && isReplicatedRootClone(it->key)) @@ -1530,7 +1527,6 @@ void GraphicsLayerCA::updateLayerDrawsContent(float pageScaleFactor, const Float it->value->setContents(0); } } - updateDebugIndicators(); } void GraphicsLayerCA::updateAcceleratesDrawing() @@ -1538,6 +1534,14 @@ void GraphicsLayerCA::updateAcceleratesDrawing() m_layer->setAcceleratesDrawing(m_acceleratesDrawing); } +void GraphicsLayerCA::updateDebugBorder() +{ + if (isShowingDebugBorder()) + updateDebugIndicators(); + else + m_layer->setBorderWidth(0); +} + FloatRect GraphicsLayerCA::adjustTiledLayerVisibleRect(TiledBacking* tiledBacking, const FloatRect& oldVisibleRect, const FloatSize& oldSize) const { // If the old visible rect is empty, we have no information about how the visible area is changing @@ -1600,10 +1604,13 @@ FloatRect GraphicsLayerCA::adjustTiledLayerVisibleRect(TiledBacking* tiledBackin void GraphicsLayerCA::updateVisibleRect(const FloatRect& oldVisibleRect) { - if (m_layer->layerType() != PlatformCALayer::LayerTypeTileCacheLayer) + if (!m_layer->usesTileCacheLayer()) return; - FloatRect tileArea = adjustTiledLayerVisibleRect(tiledBacking(), oldVisibleRect, m_sizeAtLastVisibleRectUpdate); + FloatRect tileArea = m_visibleRect; + if (m_layer->layerType() == PlatformCALayer::LayerTypeTileCacheLayer) + tileArea = adjustTiledLayerVisibleRect(tiledBacking(), oldVisibleRect, m_sizeAtLastVisibleRectUpdate); + tiledBacking()->setVisibleRect(enclosingIntRect(tileArea)); m_sizeAtLastVisibleRectUpdate = m_size; @@ -2497,6 +2504,24 @@ void GraphicsLayerCA::updateContentsScale(float pageScaleFactor, const FloatPoin m_layer->setNeedsDisplay(); } +void GraphicsLayerCA::setShowDebugBorder(bool showBorder) +{ + if (showBorder == m_showDebugBorder) + return; + + GraphicsLayer::setShowDebugBorder(showBorder); + noteLayerPropertyChanged(DebugIndicatorsChanged); +} + +void GraphicsLayerCA::setShowRepaintCounter(bool showCounter) +{ + if (showCounter == m_showRepaintCounter) + return; + + GraphicsLayer::setShowRepaintCounter(showCounter); + noteLayerPropertyChanged(DebugIndicatorsChanged); +} + void GraphicsLayerCA::setDebugBackgroundColor(const Color& color) { if (color.isValid()) @@ -2522,6 +2547,16 @@ void GraphicsLayerCA::dumpAdditionalProperties(TextStream& textStream, int inden writeIndent(textStream, indent + 1); textStream << "(visible rect " << m_visibleRect.x() << ", " << m_visibleRect.y() << " " << m_visibleRect.width() << " x " << m_visibleRect.height() << ")\n"; } + + if (tiledBacking() && (behavior & LayerTreeAsTextIncludeTileCaches)) { + IntRect tileCoverageRect = tiledBacking()->tileCoverageRect(); + writeIndent(textStream, indent + 1); + textStream << "(tile cache coverage " << tileCoverageRect.x() << ", " << tileCoverageRect.y() << " " << tileCoverageRect.width() << " x " << tileCoverageRect.height() << ")\n"; + + IntSize tileSize = tiledBacking()->tileSize(); + writeIndent(textStream, indent + 1); + textStream << "(tile size " << tileSize.width() << " x " << tileSize.height() << ")\n"; + } } void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) @@ -2600,10 +2635,9 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer, float /*pageSca | BackgroundColorChanged | ContentsScaleChanged | AcceleratesDrawingChanged -#if ENABLE(CSS_FILTERS) | FiltersChanged -#endif - | OpacityChanged; + | OpacityChanged + | DebugIndicatorsChanged; #ifndef NDEBUG String name = String::format("%sCALayer(%p) GraphicsLayer(%p) ", (m_layer->layerType() == PlatformCALayer::LayerTypeWebTiledLayer) ? "Tiled " : "", m_layer->platformLayer(), this) + m_name; @@ -2615,8 +2649,6 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer, float /*pageSca // need to tell new layer to draw itself setNeedsDisplay(); - - updateDebugIndicators(); } GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const @@ -2640,7 +2672,7 @@ void GraphicsLayerCA::setupContentsLayer(PlatformCALayer* contentsLayer) } else contentsLayer->setAnchorPoint(FloatPoint3D()); - if (showDebugBorders()) { + if (isShowingDebugBorder()) { contentsLayer->setBorderColor(Color(0, 0, 128, 180)); contentsLayer->setBorderWidth(1.0f); } @@ -2828,13 +2860,14 @@ PassRefPtr<PlatformCALayer> GraphicsLayerCA::cloneLayer(PlatformCALayer *layer, newLayer->setOpaque(layer->isOpaque()); newLayer->setBackgroundColor(layer->backgroundColor()); newLayer->setContentsScale(layer->contentsScale()); + newLayer->copyFiltersFrom(layer); if (cloneLevel == IntermediateCloneLevel) { newLayer->setOpacity(layer->opacity()); moveOrCopyAnimations(Copy, layer, newLayer.get()); } - if (showDebugBorders()) { + if (isShowingDebugBorder()) { newLayer->setBorderColor(Color(255, 122, 251)); newLayer->setBorderWidth(2); } diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h index c6b210e5b..2deb2e28c 100644 --- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h +++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h @@ -121,6 +121,9 @@ public: virtual bool hasContentsLayer() const { return m_contentsLayer; } + virtual void setShowDebugBorder(bool) OVERRIDE; + virtual void setShowRepaintCounter(bool) OVERRIDE; + virtual void setDebugBackgroundColor(const Color&); virtual void setDebugBorder(const Color&, float borderWidth); @@ -134,7 +137,7 @@ public: virtual void flushCompositingState(const FloatRect&); virtual void flushCompositingStateForThisLayerOnly(); - virtual TiledBacking* tiledBacking() OVERRIDE; + virtual TiledBacking* tiledBacking() const OVERRIDE; bool allowTiledLayer() const { return m_allowTiledLayer; } virtual void setAllowTiledLayer(bool b); @@ -152,7 +155,7 @@ private: virtual void platformCALayerAnimationStarted(CFTimeInterval beginTime); virtual CompositingCoordinatesOrientation platformCALayerContentsOrientation() const { return contentsOrientation(); } virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& clip); - virtual bool platformCALayerShowDebugBorders() const { return showDebugBorders(); } + virtual bool platformCALayerShowDebugBorders() const { return isShowingDebugBorder(); } virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const; virtual int platformCALayerIncrementRepaintCount() { return incrementRepaintCount(); } @@ -326,6 +329,7 @@ private: void updateLayerAnimations(); void updateContentsNeedsDisplay(); void updateAcceleratesDrawing(); + void updateDebugBorder(); void updateVisibleRect(const FloatRect& oldVisibleRect); void updateContentsScale(float pixelAlignmentScale, const FloatPoint& positionRelativeToBase); @@ -377,9 +381,8 @@ private: ContentsScaleChanged = 1 << 23, ContentsVisibilityChanged = 1 << 24, VisibleRectChanged = 1 << 25, -#if ENABLE(CSS_FILTERS) FiltersChanged = 1 << 26, -#endif + DebugIndicatorsChanged = 1 << 27 }; typedef unsigned LayerChangeFlags; void noteLayerPropertyChanged(LayerChangeFlags flags); diff --git a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h index 520711681..6b0591032 100644 --- a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h +++ b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h @@ -189,6 +189,7 @@ public: #if ENABLE(CSS_FILTERS) void setFilters(const FilterOperations&); static bool filtersCanBeComposited(const FilterOperations&); + void copyFiltersFrom(const PlatformCALayer*); #endif String name() const; diff --git a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm index 1659c4dca..408766404 100644 --- a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm +++ b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm @@ -715,7 +715,6 @@ void PlatformCALayer::setFilters(const FilterOperations& filters) [m_layer.get() setShadowRadius:op->stdDeviation()]; [m_layer.get() setShadowOpacity:1]; - break; } case FilterOperation::GRAYSCALE: { @@ -838,6 +837,13 @@ void PlatformCALayer::setFilters(const FilterOperations& filters) END_BLOCK_OBJC_EXCEPTIONS } +void PlatformCALayer::copyFiltersFrom(const PlatformCALayer* sourceLayer) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS + [m_layer.get() setFilters:[sourceLayer->platformLayer() filters]]; + END_BLOCK_OBJC_EXCEPTIONS +} + bool PlatformCALayer::filtersCanBeComposited(const FilterOperations& filters) { // Return false if there are no filters to avoid needless work @@ -850,6 +856,7 @@ bool PlatformCALayer::filtersCanBeComposited(const FilterOperations& filters) case FilterOperation::REFERENCE: #if ENABLE(CSS_SHADERS) case FilterOperation::CUSTOM: + case FilterOperation::VALIDATED_CUSTOM: #endif return false; case FilterOperation::DROP_SHADOW: diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.h b/Source/WebCore/platform/graphics/ca/mac/TileCache.h index 17e98ee3c..32573c70d 100644 --- a/Source/WebCore/platform/graphics/ca/mac/TileCache.h +++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.h @@ -51,7 +51,7 @@ class TileCache : public TiledBacking { WTF_MAKE_NONCOPYABLE(TileCache); public: - static PassOwnPtr<TileCache> create(WebTileCacheLayer*, const IntSize& tileSize); + static PassOwnPtr<TileCache> create(WebTileCacheLayer*); ~TileCache(); void tileCacheLayerBoundsChanged(); @@ -79,7 +79,7 @@ public: static unsigned blankPixelCountForTiles(const WebTileLayerList&, IntRect, IntPoint); private: - TileCache(WebTileCacheLayer*, const IntSize& tileSize); + TileCache(WebTileCacheLayer*); // TiledBacking member functions. virtual void setVisibleRect(const IntRect&) OVERRIDE; @@ -87,8 +87,10 @@ private: virtual void setTileCoverage(TileCoverage) OVERRIDE; virtual TileCoverage tileCoverage() const OVERRIDE { return m_tileCoverage; } virtual void forceRepaint() OVERRIDE; + virtual IntSize tileSize() const OVERRIDE { return m_tileSize; } virtual void setScrollingPerformanceLoggingEnabled(bool flag) OVERRIDE { m_scrollingPerformanceLoggingEnabled = flag; } virtual bool scrollingPerformanceLoggingEnabled() const OVERRIDE { return m_scrollingPerformanceLoggingEnabled; } + virtual IntRect tileCoverageRect() const; IntRect bounds() const; @@ -96,7 +98,8 @@ private: IntRect rectForTileIndex(const TileIndex&) const; void getTileIndexRangeForRect(const IntRect&, TileIndex& topLeft, TileIndex& bottomRight); - IntRect tileCoverageRect() const; + IntRect computeTileCoverageRect() const; + IntSize tileSizeForCoverageRect(const IntRect&) const; void scheduleTileRevalidation(double interval); void tileRevalidationTimerFired(Timer<TileCache>*); @@ -110,7 +113,7 @@ private: WebTileCacheLayer* m_tileCacheLayer; RetainPtr<CALayer> m_tileContainerLayer; - const IntSize m_tileSize; + IntSize m_tileSize; IntRect m_visibleRect; typedef HashMap<TileIndex, RetainPtr<WebTileLayer> > TileMap; diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm index 619244da9..9638f088a 100644 --- a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm +++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm @@ -45,15 +45,18 @@ using namespace std; namespace WebCore { -PassOwnPtr<TileCache> TileCache::create(WebTileCacheLayer* tileCacheLayer, const IntSize& tileSize) +static const int defaultTileCacheWidth = 512; +static const int defaultTileCacheHeight = 512; + +PassOwnPtr<TileCache> TileCache::create(WebTileCacheLayer* tileCacheLayer) { - return adoptPtr(new TileCache(tileCacheLayer, tileSize)); + return adoptPtr(new TileCache(tileCacheLayer)); } -TileCache::TileCache(WebTileCacheLayer* tileCacheLayer, const IntSize& tileSize) +TileCache::TileCache(WebTileCacheLayer* tileCacheLayer) : m_tileCacheLayer(tileCacheLayer) , m_tileContainerLayer(adoptCF([[CALayer alloc] init])) - , m_tileSize(tileSize) + , m_tileSize(defaultTileCacheWidth, defaultTileCacheHeight) , m_tileRevalidationTimer(this, &TileCache::tileRevalidationTimerFired) , m_scale(1) , m_deviceScaleFactor(1) @@ -300,18 +303,22 @@ void TileCache::getTileIndexRangeForRect(const IntRect& rect, TileIndex& topLeft topLeft.setX(max(clampedRect.x() / m_tileSize.width(), 0)); topLeft.setY(max(clampedRect.y() / m_tileSize.height(), 0)); - bottomRight.setX(max(clampedRect.maxX() / m_tileSize.width(), 0)); - bottomRight.setY(max(clampedRect.maxY() / m_tileSize.height(), 0)); + + int bottomXRatio = ceil((float)clampedRect.maxX() / m_tileSize.width()); + bottomRight.setX(max(bottomXRatio - 1, 0)); + + int bottomYRatio = ceil((float)clampedRect.maxY() / m_tileSize.height()); + bottomRight.setY(max(bottomYRatio - 1, 0)); } -IntRect TileCache::tileCoverageRect() const +IntRect TileCache::computeTileCoverageRect() const { IntRect tileCoverageRect = m_visibleRect; // If the page is not in a window (for example if it's in a background tab), we limit the tile coverage rect to the visible rect. // Furthermore, if the page can't have scrollbars (for example if its body element has overflow:hidden) it's very unlikely that the // page will ever be scrolled so we limit the tile coverage rect as well. - if (m_isInWindow) { + if (m_isInWindow && !(m_tileCoverage & CoverageForSlowScrolling)) { // Inflate the coverage rect so that it covers 2x of the visible width and 3x of the visible height. // These values were chosen because it's more common to have tall pages and to scroll vertically, // so we keep more tiles above and below the current area. @@ -325,6 +332,13 @@ IntRect TileCache::tileCoverageRect() const return tileCoverageRect; } +IntSize TileCache::tileSizeForCoverageRect(const IntRect& coverageRect) const +{ + if (m_tileCoverage & CoverageForSlowScrolling) + return coverageRect.size(); + return IntSize(defaultTileCacheWidth, defaultTileCacheHeight); +} + void TileCache::scheduleTileRevalidation(double interval) { if (m_tileRevalidationTimer.isActive() && m_tileRevalidationTimer.nextFireInterval() < interval) @@ -377,7 +391,13 @@ void TileCache::revalidateTiles() if (m_visibleRect.isEmpty() || bounds().isEmpty()) return; - IntRect tileCoverageRect = this->tileCoverageRect(); + IntRect tileCoverageRect = computeTileCoverageRect(); + IntRect coverageRectInTileCoords(tileCoverageRect); + coverageRectInTileCoords.scale(m_scale); + + IntSize oldTileSize = m_tileSize; + m_tileSize = tileSizeForCoverageRect(tileCoverageRect); + bool tileSizeChanged = m_tileSize != oldTileSize; Vector<TileIndex> tilesToRemove; @@ -386,7 +406,7 @@ void TileCache::revalidateTiles() WebTileLayer* tileLayer = it->value.get(); - if (!rectForTileIndex(tileIndex).intersects(tileCoverageRect)) { + if (!rectForTileIndex(tileIndex).intersects(coverageRectInTileCoords) || tileSizeChanged) { // Remove this layer. [tileLayer removeFromSuperlayer]; [tileLayer setTileCache:0]; @@ -403,7 +423,7 @@ void TileCache::revalidateTiles() TileIndex topLeft; TileIndex bottomRight; - getTileIndexRangeForRect(tileCoverageRect, topLeft, bottomRight); + getTileIndexRangeForRect(coverageRectInTileCoords, topLeft, bottomRight); Vector<FloatRect> dirtyRects; @@ -442,6 +462,14 @@ void TileCache::revalidateTiles() platformLayer->owner()->platformCALayerDidCreateTiles(dirtyRects); } +// Return the rect in layer coords, not tile coords. +IntRect TileCache::tileCoverageRect() const +{ + IntRect coverageRectInLayerCoords(m_tileCoverageRect); + coverageRectInLayerCoords.scale(1 / m_scale); + return coverageRectInLayerCoords; +} + WebTileLayer* TileCache::tileLayerAtIndex(const TileIndex& index) const { return m_tiles.get(index).get(); diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm index c6aab8aff..d119f5bd2 100644 --- a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm +++ b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm @@ -40,8 +40,7 @@ using namespace WebCore; if (!self) return nil; - // FIXME: The tile size should be configurable. - _tileCache = TileCache::create(self, IntSize(512, 512)); + _tileCache = TileCache::create(self); #ifndef NDEBUG [self setName:@"WebTileCacheLayer"]; #endif diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp index 97fb0b609..856a4fcad 100644 --- a/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp +++ b/Source/WebCore/platform/graphics/ca/win/PlatformCAAnimationWin.cpp @@ -151,8 +151,7 @@ PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPa else m_animation.adoptCF(CACFAnimationCreate(kCACFKeyframeAnimation)); - RetainPtr<CFStringRef> s(AdoptCF, keyPath.createCFString()); - CACFAnimationSetKeyPath(m_animation.get(), s.get()); + CACFAnimationSetKeyPath(m_animation.get(), keyPath.createCFString().get()); } PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation) diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp index 70168b210..bba8f2c5c 100644 --- a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp +++ b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp @@ -176,10 +176,8 @@ void PlatformCALayer::animationStarted(CFTimeInterval beginTime) static void resubmitAllAnimations(PlatformCALayer* layer) { HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator end = layer->animations().end(); - for (HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator it = layer->animations().begin(); it != end; ++it) { - RetainPtr<CFStringRef> s(AdoptCF, it->key.createCFString()); - CACFLayerAddAnimation(layer->platformLayer(), s.get(), it->value->platformAnimation()); - } + for (HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator it = layer->animations().begin(); it != end; ++it) + CACFLayerAddAnimation(layer->platformLayer(), it->key.createCFString().get(), it->value->platformAnimation()); } void PlatformCALayer::ensureAnimationsSubmitted() @@ -297,8 +295,7 @@ void PlatformCALayer::addAnimationForKey(const String& key, PlatformCAAnimation* // Add it to the animation list m_animations.add(key, animation); - RetainPtr<CFStringRef> s(AdoptCF, key.createCFString()); - CACFLayerAddAnimation(m_layer.get(), s.get(), animation->platformAnimation()); + CACFLayerAddAnimation(m_layer.get(), key.createCFString().get(), animation->platformAnimation()); setNeedsCommit(); // Tell the host about it so we can fire the start animation event @@ -312,8 +309,7 @@ void PlatformCALayer::removeAnimationForKey(const String& key) // Remove it from the animation list m_animations.remove(key); - RetainPtr<CFStringRef> s(AdoptCF, key.createCFString()); - CACFLayerRemoveAnimation(m_layer.get(), s.get()); + CACFLayerRemoveAnimation(m_layer.get(), key.createCFString().get()); // We don't "remove" a layer from AbstractCACFLayerTreeHost when it loses an animation. // There may be other active animations on the layer and if an animation @@ -572,6 +568,10 @@ void PlatformCALayer::setFilters(const FilterOperations&) { } +void PlatformCALayer::copyFiltersFrom(const PlatformCALayer*) +{ +} + bool PlatformCALayer::filtersCanBeComposited(const FilterOperations&) { return false; @@ -586,8 +586,7 @@ String PlatformCALayer::name() const void PlatformCALayer::setName(const String& value) { - RetainPtr<CFStringRef> s(AdoptCF, value.createCFString()); - CACFLayerSetName(m_layer.get(), s.get()); + CACFLayerSetName(m_layer.get(), value.createCFString().get()); setNeedsCommit(); } diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp index c430cf284..15275b3ae 100644 --- a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp +++ b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp @@ -459,7 +459,7 @@ void PlatformCALayerWinInternal::updateTiles() #ifndef NDEBUG String name = "Tile (" + String::number(i) + "," + String::number(j) + ")"; - CACFLayerSetName(tile, RetainPtr<CFStringRef>(AdoptCF, name.createCFString()).get()); + CACFLayerSetName(tile, name.createCFString().get()); #endif } } diff --git a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp index 83fac1fda..225dfb2f6 100644 --- a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp @@ -73,10 +73,12 @@ BitmapImage::BitmapImage(NativeImageCairo* nativeImage, ImageObserver* observer) void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op) { - FloatRect srcRect(src); - FloatRect dstRect(dst); + draw(context, dst, src, styleColorSpace, op, DoNotRespectImageOrientation); +} - if (!dstRect.width() || !dstRect.height() || !srcRect.width() || !srcRect.height()) +void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation) +{ + if (!dst.width() || !dst.height() || !src.width() || !src.height()) return; startAnimation(); @@ -86,7 +88,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo return; if (mayFillWithSolidColor()) { - fillWithSolidColor(context, dstRect, solidColor(), styleColorSpace, op); + fillWithSolidColor(context, dst, solidColor(), styleColorSpace, op); return; } @@ -101,11 +103,29 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) cairo_surface_t* surface = nativeImage->surface(); IntSize scaledSize(cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface)); - FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(srcRect, scaledSize); + FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(src, scaledSize); #else - FloatRect adjustedSrcRect(srcRect); + FloatRect adjustedSrcRect(src); #endif + ImageOrientation orientation = DefaultImageOrientation; + if (shouldRespectImageOrientation == RespectImageOrientation) + orientation = frameOrientationAtIndex(m_currentFrame); + + FloatRect dstRect = dst; + + if (orientation != DefaultImageOrientation) { + // ImageOrientation expects the origin to be at (0, 0). + context->translate(dstRect.x(), dstRect.y()); + dstRect.setLocation(FloatPoint()); + context->concatCTM(orientation.transformFromDefault(dstRect.size())); + if (orientation.usesWidthAsHeight()) { + // The destination rectangle will have it's width and height already reversed for the orientation of + // the image, as it was needed for page layout, so we need to reverse it back here. + dstRect = FloatRect(dstRect.x(), dstRect.y(), dstRect.height(), dstRect.width()); + } + } + context->platformContext()->drawSurfaceToContext(nativeImage->surface(), dstRect, adjustedSrcRect, context); context->restore(); diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp index 8ccb8d9bc..722cb6999 100644 --- a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp @@ -175,15 +175,26 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe for (int x = 0; x < numColumns; x++) { int basex = x * 4; unsigned* pixel = row + x + originx; - Color pixelColor; - if (multiplied == Unmultiplied) - pixelColor = colorFromPremultipliedARGB(*pixel); - else - pixelColor = Color(*pixel); - destRows[basex] = pixelColor.red(); - destRows[basex + 1] = pixelColor.green(); - destRows[basex + 2] = pixelColor.blue(); - destRows[basex + 3] = pixelColor.alpha(); + + // Avoid calling Color::colorFromPremultipliedARGB() because one + // function call per pixel is too expensive. + unsigned alpha = (*pixel & 0xFF000000) >> 24; + unsigned red = (*pixel & 0x00FF0000) >> 16; + unsigned green = (*pixel & 0x0000FF00) >> 8; + unsigned blue = (*pixel & 0x000000FF); + + if (multiplied == Unmultiplied) { + if (alpha && alpha != 255) { + red = red * 255 / alpha; + green = green * 255 / alpha; + blue = blue * 255 / alpha; + } + } + + destRows[basex] = red; + destRows[basex + 1] = green; + destRows[basex + 2] = blue; + destRows[basex + 3] = alpha; } destRows += destBytesPerRow; } @@ -242,14 +253,23 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c for (int x = 0; x < numColumns; x++) { int basex = x * 4; unsigned* pixel = row + x + destx; - Color pixelColor = Color::createUnCheked(srcRows[basex], - srcRows[basex + 1], - srcRows[basex + 2], - srcRows[basex + 3]); - if (multiplied == Unmultiplied) - *pixel = premultipliedARGBFromColor(pixelColor); - else - *pixel = pixelColor.rgb(); + + // Avoid calling Color::premultipliedARGBFromColor() because one + // function call per pixel is too expensive. + unsigned red = srcRows[basex]; + unsigned green = srcRows[basex + 1]; + unsigned blue = srcRows[basex + 2]; + unsigned alpha = srcRows[basex + 3]; + + if (multiplied == Unmultiplied) { + if (alpha && alpha != 255) { + red = (red * alpha + 254) / 255; + green = (green * alpha + 254) / 255; + blue = (blue * alpha + 254) / 255; + } + } + + *pixel = (alpha << 24) | red << 16 | green << 8 | blue; } srcRows += srcBytesPerRow; } diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index 6ceace35d..1edab0c33 100644 --- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -326,9 +326,8 @@ void GraphicsContext::drawNativeImage(NativeImagePtr imagePtr, const FloatSize& setPlatformCompositeOperation(op); - // Flip the coords. - CGContextTranslateCTM(context, adjustedDestRect.x(), adjustedDestRect.maxY()); - CGContextScaleCTM(context, 1, -1); + // ImageOrientation expects the origin to be at (0, 0) + CGContextTranslateCTM(context, adjustedDestRect.x(), adjustedDestRect.y()); adjustedDestRect.setLocation(FloatPoint()); if (orientation != DefaultImageOrientation) { @@ -340,6 +339,10 @@ void GraphicsContext::drawNativeImage(NativeImagePtr imagePtr, const FloatSize& } } + // Flip the coords. + CGContextTranslateCTM(context, 0, adjustedDestRect.height()); + CGContextScaleCTM(context, 1, -1); + // Adjust the color space. image = Image::imageWithColorSpace(image.get(), styleColorSpace); @@ -485,7 +488,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) } } - const CGFloat dottedLine[2] = { patWidth, patWidth }; + const CGFloat dottedLine[2] = { static_cast<CGFloat>(patWidth), static_cast<CGFloat>(patWidth) }; CGContextSetLineDash(context, patternOffset, dottedLine, 2); } @@ -593,7 +596,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp } } - const CGFloat dottedLine[2] = { patWidth, patWidth }; + const CGFloat dottedLine[2] = { static_cast<CGFloat>(patWidth), static_cast<CGFloat>(patWidth) }; CGContextSetLineDash(context, patternOffset, dottedLine, 2); } @@ -1057,7 +1060,12 @@ void GraphicsContext::clipOut(const IntRect& rect) if (paintingDisabled()) return; - CGRect rects[2] = { CGContextGetClipBoundingBox(platformContext()), rect }; + // FIXME: Using CGRectInfinite is much faster than getting the clip bounding box. However, due + // to <rdar://problem/12584492>, CGRectInfinite can't be used with an accelerated context that + // has certain transforms that aren't just a translation or a scale. + const AffineTransform& ctm = getCTM(); + bool canUseCGRectInfinite = !isAcceleratedContext() || (!ctm.b() && !ctm.c()); + CGRect rects[2] = { canUseCGRectInfinite ? CGRectInfinite : CGContextGetClipBoundingBox(platformContext()), rect }; CGContextBeginPath(platformContext()); CGContextAddRects(platformContext(), rects, 2); CGContextEOClip(platformContext()); diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp index 21e9db4c2..dd3781597 100644 --- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp +++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp @@ -377,8 +377,7 @@ static inline CFStringRef jpegUTI() static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType) { #if PLATFORM(MAC) - RetainPtr<CFStringRef> mimeTypeCFString(AdoptCF, mimeType.createCFString()); - return RetainPtr<CFStringRef>(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeTypeCFString.get(), 0)); + return adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType.createCFString().get(), 0)); #else ASSERT(isMainThread()); // It is unclear if CFSTR is threadsafe. diff --git a/Source/WebCore/platform/graphics/cg/ImageSourceCGMac.mm b/Source/WebCore/platform/graphics/cg/ImageSourceCGMac.mm index bd50a3175..953bcb9d2 100644 --- a/Source/WebCore/platform/graphics/cg/ImageSourceCGMac.mm +++ b/Source/WebCore/platform/graphics/cg/ImageSourceCGMac.mm @@ -33,16 +33,12 @@ namespace WebCore { String MIMETypeForImageSourceType(const String& uti) { - RetainPtr<CFStringRef> utiref(AdoptCF, uti.createCFString()); - RetainPtr<CFStringRef> mime(AdoptCF, UTTypeCopyPreferredTagWithClass(utiref.get(), kUTTagClassMIMEType)); - return mime.get(); + return adoptCF(UTTypeCopyPreferredTagWithClass(uti.createCFString().get(), kUTTagClassMIMEType)).get(); } String preferredExtensionForImageSourceType(const String& uti) { - RetainPtr<CFStringRef> type(AdoptCF, uti.createCFString()); - RetainPtr<CFStringRef> extension(AdoptCF, UTTypeCopyPreferredTagWithClass(type.get(), kUTTagClassFilenameExtension)); - return extension.get(); + return adoptCF(UTTypeCopyPreferredTagWithClass(uti.createCFString().get(), kUTTagClassFilenameExtension)).get(); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/DeferredImageDecoder.cpp b/Source/WebCore/platform/graphics/chromium/DeferredImageDecoder.cpp index 7574196e7..e9424dfc5 100644 --- a/Source/WebCore/platform/graphics/chromium/DeferredImageDecoder.cpp +++ b/Source/WebCore/platform/graphics/chromium/DeferredImageDecoder.cpp @@ -151,4 +151,10 @@ unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const return m_actualDecoder ? m_actualDecoder->frameBytesAtIndex(index) : 0; } +ImageOrientation DeferredImageDecoder::orientation() const +{ + // FIXME: Make this work with deferred decoding. + return m_actualDecoder ? m_actualDecoder->orientation() : DefaultImageOrientation; +} + } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/DeferredImageDecoder.h b/Source/WebCore/platform/graphics/chromium/DeferredImageDecoder.h index 6b33fe35e..d82aec872 100644 --- a/Source/WebCore/platform/graphics/chromium/DeferredImageDecoder.h +++ b/Source/WebCore/platform/graphics/chromium/DeferredImageDecoder.h @@ -56,6 +56,7 @@ public: void clearFrameBufferCache(size_t); bool frameHasAlphaAtIndex(size_t index) const; unsigned frameBytesAtIndex(size_t index) const; + ImageOrientation orientation() const; private: explicit DeferredImageDecoder(ImageDecoder* actualDecoder); diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index 075749e9a..7a63b6801 100644 --- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -54,7 +54,9 @@ #include "NativeImageSkia.h" #include "PlatformContextSkia.h" #include "ScrollableArea.h" +#include "SkImageFilter.h" #include "SkMatrix44.h" +#include "SkiaImageFilterBuilder.h" #include "SystemTime.h" #include <public/Platform.h> #include <public/WebAnimation.h> @@ -105,6 +107,7 @@ GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client) m_layer = adoptPtr(Platform::current()->compositorSupport()->createContentLayer(m_opaqueRectTrackingContentLayerDelegate.get())); m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible); m_layer->layer()->setScrollClient(this); + m_layer->setAutomaticallyComputeRasterScale(true); updateDebugIndicators(); } @@ -299,6 +302,7 @@ void GraphicsLayerChromium::setContentsOpaque(bool opaque) { GraphicsLayer::setContentsOpaque(opaque); m_layer->layer()->setOpaque(m_contentsOpaque); + m_opaqueRectTrackingContentLayerDelegate->setOpaque(m_contentsOpaque); } static bool copyWebCoreFilterOperationsToWebFilterOperations(const FilterOperations& filters, WebFilterOperations& webFilters) @@ -366,6 +370,7 @@ static bool copyWebCoreFilterOperationsToWebFilterOperations(const FilterOperati } #if ENABLE(CSS_SHADERS) case FilterOperation::CUSTOM: + case FilterOperation::VALIDATED_CUSTOM: return false; // Not supported. #endif case FilterOperation::PASSTHROUGH: @@ -378,15 +383,25 @@ static bool copyWebCoreFilterOperationsToWebFilterOperations(const FilterOperati bool GraphicsLayerChromium::setFilters(const FilterOperations& filters) { - WebFilterOperations webFilters; - if (!copyWebCoreFilterOperationsToWebFilterOperations(filters, webFilters)) { - // Make sure the filters are removed from the platform layer, as they are - // going to fallback to software mode. - m_layer->layer()->setFilters(WebFilterOperations()); - GraphicsLayer::setFilters(FilterOperations()); - return false; + // FIXME: For now, we only use SkImageFilters if there is a reference + // filter in the chain. Once all issues have been ironed out, we should + // switch all filtering over to this path, and remove setFilters() and + // WebFilterOperations altogether. + if (filters.hasReferenceFilter()) { + SkiaImageFilterBuilder builder; + SkAutoTUnref<SkImageFilter> imageFilter(builder.build(filters)); + m_layer->layer()->setFilter(imageFilter); + } else { + WebFilterOperations webFilters; + if (!copyWebCoreFilterOperationsToWebFilterOperations(filters, webFilters)) { + // Make sure the filters are removed from the platform layer, as they are + // going to fallback to software mode. + m_layer->layer()->setFilters(WebFilterOperations()); + GraphicsLayer::setFilters(FilterOperations()); + return false; + } + m_layer->layer()->setFilters(webFilters); } - m_layer->layer()->setFilters(webFilters); return GraphicsLayer::setFilters(filters); } @@ -434,14 +449,17 @@ void GraphicsLayerChromium::setReplicatedByLayer(GraphicsLayer* layer) void GraphicsLayerChromium::setContentsNeedsDisplay() { - if (WebLayer* contentsLayer = contentsLayerIfRegistered()) + if (WebLayer* contentsLayer = contentsLayerIfRegistered()) { contentsLayer->invalidate(); + addRepaintRect(contentsRect()); + } } void GraphicsLayerChromium::setNeedsDisplay() { if (drawsContent()) { m_layer->layer()->invalidate(); + addRepaintRect(FloatRect(FloatPoint(), m_size)); if (m_linkHighlight) m_linkHighlight->invalidate(); } @@ -451,6 +469,7 @@ void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect) { if (drawsContent()) { m_layer->layer()->invalidateRect(rect); + addRepaintRect(rect); if (m_linkHighlight) m_linkHighlight->invalidate(); } @@ -841,7 +860,7 @@ void GraphicsLayerChromium::setupContentsLayer(WebLayer* contentsLayer) // shadow content that must display in front of the video. m_layer->layer()->insertChild(m_contentsLayer, 0); - if (showDebugBorders()) { + if (isShowingDebugBorder()) { m_contentsLayer->setDebugBorderColor(Color(0, 0, 128, 180).rgb()); m_contentsLayer->setDebugBorderWidth(1); } @@ -862,7 +881,6 @@ bool GraphicsLayerChromium::appliesPageScale() const void GraphicsLayerChromium::paint(GraphicsContext& context, const IntRect& clip) { - context.platformContext()->setDrawingToImageBuffer(true); paintGraphicsLayerContents(context, clip); } diff --git a/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.cpp b/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.cpp index a06ac666e..62edced17 100644 --- a/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.cpp +++ b/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.cpp @@ -49,7 +49,7 @@ OpaqueRectTrackingContentLayerDelegate::~OpaqueRectTrackingContentLayerDelegate( { } -void OpaqueRectTrackingContentLayerDelegate::paintContents(SkCanvas* canvas, const WebRect& clip, WebFloatRect& opaque) +void OpaqueRectTrackingContentLayerDelegate::paintContents(SkCanvas* canvas, const WebRect& clip, bool canPaintLCDText, WebFloatRect& opaque) { PlatformContextSkia platformContext(canvas); #if defined(SK_SUPPORT_HINTING_SCALE_FACTOR) @@ -57,6 +57,10 @@ void OpaqueRectTrackingContentLayerDelegate::paintContents(SkCanvas* canvas, con platformContext.setHintingScaleFactor(canvas->getTotalMatrix().getScaleX()); #endif platformContext.setTrackOpaqueRegion(!m_opaque); + // FIXME: Rename PlatformContextSkia::setDrawingToImageBuffer to setCanPaintLCDText. + // I also suspect that a function on PlatformContextSkia is not really needed. + // GraphicsContext::setAllowsFontSmoothing can be used for this purpose. + platformContext.setDrawingToImageBuffer(!(canPaintLCDText && m_opaque)); GraphicsContext context(&platformContext); // Record transform prior to painting, as all opaque tracking will be diff --git a/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.h b/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.h index bb5c2ae96..451b647b1 100644 --- a/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.h +++ b/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.h @@ -55,7 +55,7 @@ public: void setOpaque(bool opaque) { m_opaque = opaque; } // WebKit::WebContentLayerClient implementation. - virtual void paintContents(SkCanvas*, const WebKit::WebRect& clip, WebKit::WebFloatRect& opaque) OVERRIDE; + virtual void paintContents(SkCanvas*, const WebKit::WebRect& clip, bool canPaintLCDText, WebKit::WebFloatRect& opaque) OVERRIDE; private: GraphicsContextPainter* m_painter; diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp index 8510dfa52..a7aed729c 100644 --- a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp @@ -119,26 +119,6 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri return SimpleFontData::create(FontPlatformData(hfont, scaledSize, m_platformData.orientation()), isCustomFont(), false); } -PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->smallCaps) - m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - - return m_derivedFontData->smallCaps; -} - -PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->emphasisMark) - m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - - return m_derivedFontData->emphasisMark; -} - bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { // This used to be implemented with IMLangFontLink2, but since that code has diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp b/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp index 104b7982b..58bf38d5b 100644 --- a/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp +++ b/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp @@ -67,11 +67,13 @@ ClutterActor* GraphicsLayerClutter::platformLayer() const void GraphicsLayerClutter::setNeedsDisplay() { notImplemented(); + addRepaintRect(FloatRect(FloatPoint(), m_size)); } -void GraphicsLayerClutter::setNeedsDisplayInRect(const FloatRect&) +void GraphicsLayerClutter::setNeedsDisplayInRect(const FloatRect& rect) { notImplemented(); + addRepaintRect(rect); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp index 65f2d63b8..d1391307c 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp @@ -151,6 +151,31 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi GraphicsContext3D::~GraphicsContext3D() { + if (m_renderStyle == RenderToCurrentGLContext || !m_private) + return; + + makeContextCurrent(); + glDeleteTextures(1, &m_texture); + + if (m_attrs.antialias) { + glDeleteRenderbuffers(1, &m_multisampleColorBuffer); + + if (m_attrs.stencil || m_attrs.depth) + glDeleteRenderbuffers(1, &m_multisampleDepthStencilBuffer); + + glDeleteFramebuffers(1, &m_multisampleFBO); + } else if (m_attrs.stencil || m_attrs.depth) { + +#if USE(OPENGL_ES_2) + if (m_attrs.depth) + glDeleteRenderbuffers(1, &m_depthBuffer); + + if (m_attrs.stencil) + glDeleteRenderbuffers(1, &m_stencilBuffer); +#endif + glDeleteRenderbuffers(1, &m_depthStencilBuffer); + } + glDeleteFramebuffers(1, &m_fbo); } PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() @@ -226,7 +251,7 @@ void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imag #if USE(GRAPHICS_SURFACE) void GraphicsContext3D::createGraphicsSurfaces(const IntSize& size) { - notImplemented(); + m_private->createGraphicsSurfaces(size); } #endif diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp index 0ab98929f..62d0a6e3a 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp @@ -25,6 +25,7 @@ #include "GraphicsContext.h" #include "HostWindow.h" #include "NotImplemented.h" +#include "PlatformContextCairo.h" #include <Ecore_Evas.h> #include <Evas_GL.h> #include <wtf/OwnArrayPtr.h> @@ -87,6 +88,13 @@ GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, H return; makeContextCurrent(); + +#if USE(GRAPHICS_SURFACE) + IntSize surfaceSize(m_context->m_currentWidth, m_context->m_currentHeight); + m_surfaceFlags = GraphicsSurface::SupportsTextureTarget | GraphicsSurface::SupportsSharing; + if (!surfaceSize.isEmpty()) + m_graphicsSurface = GraphicsSurface::create(surfaceSize, m_surfaceFlags); +#endif } GraphicsContext3DPrivate::~GraphicsContext3DPrivate() @@ -101,8 +109,11 @@ GraphicsContext3DPrivate::~GraphicsContext3DPrivate() evas_gl_context_destroy(m_evasGL, m_evasGLContext); evas_gl_free(m_evasGL); -} +#if USE(GRAPHICS_SURFACE) + m_graphicsSurface.clear(); +#endif +} bool GraphicsContext3DPrivate::createSurface(PageClientEfl* pageClient, bool renderDirectlyToHostWindow) { @@ -169,6 +180,32 @@ void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper*, const FloatR notImplemented(); } #endif + +#if USE(GRAPHICS_SURFACE) +void GraphicsContext3DPrivate::createGraphicsSurfaces(const IntSize& size) +{ + if (size.isEmpty()) + m_graphicsSurface.clear(); + else + m_graphicsSurface = GraphicsSurface::create(size, m_surfaceFlags); +} + +uint32_t GraphicsContext3DPrivate::copyToGraphicsSurface() +{ + if (!m_graphicsSurface) + return 0; + + makeContextCurrent(); + m_graphicsSurface->copyFromTexture(m_context->m_texture, IntRect(0, 0, m_context->m_currentWidth, m_context->m_currentHeight)); + return m_graphicsSurface->swapBuffers(); +} + +GraphicsSurfaceToken GraphicsContext3DPrivate::graphicsSurfaceToken() const +{ + return m_graphicsSurface->exportToken(); +} +#endif + } // namespace WebCore #endif // USE(3D_GRAPHICS) || USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h index 08ccf77a6..1ae4351f9 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h @@ -26,6 +26,10 @@ #include <texmap/TextureMapperPlatformLayer.h> #endif +#if USE(GRAPHICS_SURFACE) +#include "GraphicsSurface.h" +#endif + typedef struct _Evas_GL Evas_GL; typedef struct _Evas_GL_Surface Evas_GL_Surface; typedef struct _Evas_GL_Context Evas_GL_Context; @@ -52,6 +56,12 @@ public: #if USE(TEXTURE_MAPPER_GL) virtual void paintToTextureMapper(TextureMapper*, const FloatRect& target, const TransformationMatrix&, float opacity, BitmapTexture* mask); #endif +#if USE(GRAPHICS_SURFACE) + virtual uint32_t copyToGraphicsSurface(); + virtual GraphicsSurfaceToken graphicsSurfaceToken() const; + void createGraphicsSurfaces(const IntSize&); +#endif + bool makeContextCurrent(); bool createSurface(PageClientEfl*, bool renderDirectlyToEvasGLObject); void setCurrentGLContext(void*, void*); @@ -59,6 +69,10 @@ public: GraphicsContext3D::Attributes m_attributes; GraphicsContext3D* m_context; HostWindow* m_hostWindow; +#if USE(GRAPHICS_SURFACE) + GraphicsSurface::Flags m_surfaceFlags; + RefPtr<GraphicsSurface> m_graphicsSurface; +#endif ListHashSet<GC3Denum> m_syntheticErrors; diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterArrayParameter.h b/Source/WebCore/platform/graphics/filters/CustomFilterArrayParameter.h index b52236dde..3050cb445 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterArrayParameter.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterArrayParameter.h @@ -31,6 +31,7 @@ #define CustomFilterArrayParameter_h #if ENABLE(CSS_SHADERS) +#include "AnimationUtilities.h" #include "CustomFilterParameter.h" #include <wtf/Vector.h> @@ -50,11 +51,19 @@ public: virtual PassRefPtr<CustomFilterParameter> blend(const CustomFilterParameter* from, double progress, const LayoutSize&) { - // FIXME: https://bugs.webkit.org/show_bug.cgi?id=96437 - UNUSED_PARAM(from); - UNUSED_PARAM(progress); + if (!from || !isSameType(*from)) + return this; - return this; + const CustomFilterArrayParameter* fromArray = static_cast<const CustomFilterArrayParameter*>(from); + + if (size() != fromArray->size()) + return this; + + RefPtr<CustomFilterArrayParameter> result = CustomFilterArrayParameter::create(name()); + for (size_t i = 0; i < size(); ++i) + result->addValue(WebCore::blend(fromArray->valueAt(i), valueAt(i), progress)); + + return result.release(); } virtual bool operator==(const CustomFilterParameter& o) const diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.cpp index 7e284bb83..26965d05e 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.cpp @@ -50,7 +50,6 @@ CustomFilterCompiledProgram::CustomFilterCompiledProgram(PassRefPtr<GraphicsCont , m_samplerLocation(-1) , m_samplerSizeLocation(-1) , m_contentSamplerLocation(-1) - , m_internalTexCoordAttribLocation(-1) , m_isInitialized(false) { m_context->makeContextCurrent(); @@ -130,14 +129,9 @@ void CustomFilterCompiledProgram::initializeParameterLocations(CustomFilterProgr m_samplerSizeLocation = m_context->getUniformLocation(m_program, "u_textureSize"); m_contentSamplerLocation = m_context->getUniformLocation(m_program, "u_contentTexture"); if (programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE) { - // When the author uses the CSS mix function in a custom filter, we add internal symbols to the shader code. - // One of them, css_u_texture, references the texture of the element. + // When the author uses the CSS mix function in a custom filter, WebKit adds the internal + // symbol css_u_texture to the shader code, which references the texture of the element. m_samplerLocation = m_context->getUniformLocation(m_program, "css_u_texture"); - m_internalTexCoordAttribLocation = m_context->getAttribLocation(m_program, "css_a_texCoord"); - - // These internal symbols should have been added to the validated shaders. - ASSERT(m_samplerLocation != -1); - ASSERT(m_internalTexCoordAttribLocation != -1); } } diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.h b/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.h index f31fdf040..5dbf0d451 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.h @@ -61,12 +61,6 @@ public: int samplerLocation() const { return m_samplerLocation; } int contentSamplerLocation() const { return m_contentSamplerLocation; } int samplerSizeLocation() const { return m_samplerSizeLocation; } - // FIXME: Get rid of the internal tex coord attribute "css_a_texCoord". - // If the author defined "a_texCoord", we should leverage that. - // If not, we should write "a_texCoord" in the shader. - // This requires us to first get the list of attributes from the vertex shader using ANGLE. - // https://bugs.webkit.org/show_bug.cgi?id=94358 - int internalTexCoordAttribLocation() const { return m_internalTexCoordAttribLocation; } int uniformLocationByName(const String&); @@ -94,9 +88,6 @@ private: int m_samplerLocation; int m_samplerSizeLocation; int m_contentSamplerLocation; - // FIXME: Get rid of the internal tex coord attribute "css_a_texCoord". - // https://bugs.webkit.org/show_bug.cgi?id=94358 - int m_internalTexCoordAttribLocation; bool m_isInitialized; }; diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterConstants.h b/Source/WebCore/platform/graphics/filters/CustomFilterConstants.h index 6080c38f6..cdd453a2a 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterConstants.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterConstants.h @@ -45,6 +45,18 @@ enum CustomFilterMeshConstants { TriangleAttribOffset = MeshAttribOffset + MeshAttribSize * sizeof(float) }; +enum CustomFilterMeshType { + MeshTypeAttached, + MeshTypeDetached +}; + +enum CustomFilterMeshBoxType { + MeshBoxTypeFilter, + MeshBoxTypeBorder, + MeshBoxTypePadding, + MeshBoxTypeContent +}; + } // namespace WebCore #endif // CustomFilterConstants_h diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp index 0278abad0..eff07884c 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp @@ -37,7 +37,7 @@ namespace WebCore { CustomFilterMesh::CustomFilterMesh(GraphicsContext3D* context, unsigned columns, unsigned rows, - const FloatRect& meshBox, CustomFilterOperation::MeshType meshType) + const FloatRect& meshBox, CustomFilterMeshType meshType) : m_context(context) , m_verticesBufferObject(0) , m_elementsBufferObject(0) diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h index e3c7a6bac..2bb3d5af1 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h @@ -43,7 +43,7 @@ class GraphicsContext3D; class CustomFilterMesh : public RefCounted<CustomFilterMesh> { public: - static PassRefPtr<CustomFilterMesh> create(GraphicsContext3D* context, unsigned cols, unsigned rows, const FloatRect& meshBox, CustomFilterOperation::MeshType meshType) + static PassRefPtr<CustomFilterMesh> create(GraphicsContext3D* context, unsigned cols, unsigned rows, const FloatRect& meshBox, CustomFilterMeshType meshType) { return adoptRef(new CustomFilterMesh(context, cols, rows, meshBox, meshType)); } @@ -56,10 +56,10 @@ public: unsigned indicesCount() const { return m_indicesCount; } const FloatRect& meshBox() const { return m_meshBox; } - CustomFilterOperation::MeshType meshType() const { return m_meshType; } + CustomFilterMeshType meshType() const { return m_meshType; } private: - CustomFilterMesh(GraphicsContext3D*, unsigned cols, unsigned rows, const FloatRect& meshBox, CustomFilterOperation::MeshType); + CustomFilterMesh(GraphicsContext3D*, unsigned cols, unsigned rows, const FloatRect& meshBox, CustomFilterMeshType); GraphicsContext3D* m_context; @@ -70,7 +70,7 @@ private: unsigned m_indicesCount; FloatRect m_meshBox; - CustomFilterOperation::MeshType m_meshType; + CustomFilterMeshType m_meshType; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.cpp index 3d9d4d1b2..774691457 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.cpp @@ -39,7 +39,7 @@ namespace WebCore { static bool s_dumpCustomFilterMeshBuffers = false; #endif -CustomFilterMeshGenerator::CustomFilterMeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterOperation::MeshType meshType) +CustomFilterMeshGenerator::CustomFilterMeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterMeshType meshType) : m_meshType(meshType) , m_points(columns + 1, rows + 1) , m_tiles(columns, rows) @@ -60,7 +60,7 @@ CustomFilterMeshGenerator::CustomFilterMeshGenerator(unsigned columns, unsigned // when there's no need to explode the tiles. // * detached: each triangle has its own vertices. This means each triangle can be moved independently and a vec3 // attribute is passed, so that each vertex can be uniquely identified. - if (m_meshType == CustomFilterOperation::ATTACHED) + if (m_meshType == MeshTypeAttached) generateAttachedMesh(); else generateDetachedMesh(); @@ -152,8 +152,8 @@ void CustomFilterMeshGenerator::addDetachedMeshVertexAttributes(int quadX, int q void CustomFilterMeshGenerator::dumpBuffers() const { printf("Mesh buffers: Points.width(): %d, Points.height(): %d meshBox: %f, %f, %f, %f, type: %s\n", - m_points.width(), m_points.height(), m_meshBox.x(), m_meshBox.y(), m_meshBox.width(), m_meshBox.height(), - (m_meshType == CustomFilterOperation::ATTACHED) ? "Attached" : "Detached"); + m_points.width(), m_points.height(), m_meshBox.x(), m_meshBox.y(), m_meshBox.width(), m_meshBox.height(), + (m_meshType == MeshTypeAttached) ? "Attached" : "Detached"); printf("---Vertex:\n\t"); for (unsigned i = 0; i < m_vertices.size(); ++i) { printf("%f ", m_vertices.at(i)); diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h b/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h index b3a184702..7abac12e2 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h @@ -44,7 +44,7 @@ public: // and 'columns' number of columns with a total of 'rows + 1' * 'columns + 1' vertices. // MeshBox is the filtered area calculated defined using the border-box, padding-box, content-box or filter-box // attributes. A value of (0, 0, 1, 1) will cover the entire output surface. - CustomFilterMeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterOperation::MeshType); + CustomFilterMeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterMeshType); const Vector<float>& vertices() const { return m_vertices; } const Vector<uint16_t>& indices() const { return m_indices; } @@ -66,12 +66,12 @@ public: { static const unsigned AttachedMeshVertexSize = PositionAttribSize + TexAttribSize + MeshAttribSize; static const unsigned DetachedMeshVertexSize = AttachedMeshVertexSize + TriangleAttribSize; - return m_meshType == CustomFilterOperation::ATTACHED ? AttachedMeshVertexSize : DetachedMeshVertexSize; + return m_meshType == MeshTypeAttached ? AttachedMeshVertexSize : DetachedMeshVertexSize; } unsigned verticesCount() const { - return m_meshType == CustomFilterOperation::ATTACHED ? pointsCount() : indicesCount(); + return m_meshType == MeshTypeAttached ? pointsCount() : indicesCount(); } private: @@ -110,7 +110,7 @@ private: Vector<float> m_vertices; Vector<uint16_t> m_indices; - CustomFilterOperation::MeshType m_meshType; + CustomFilterMeshType m_meshType; IntSize m_points; IntSize m_tiles; FloatSize m_tileSizeInPixels; diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h b/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h index 423ef547e..09378583c 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h @@ -31,6 +31,7 @@ #define CustomFilterNumberParameter_h #if ENABLE(CSS_SHADERS) +#include "AnimationUtilities.h" #include "CustomFilterParameter.h" #include <wtf/Vector.h> diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp index ed57b7374..2526e5820 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp @@ -36,66 +36,9 @@ #include "CustomFilterProgram.h" #include "FilterOperation.h" -#include <wtf/text/StringHash.h> - namespace WebCore { -bool customFilterParametersEqual(const CustomFilterParameterList& listA, const CustomFilterParameterList& listB) -{ - if (listA.size() != listB.size()) - return false; - for (size_t i = 0; i < listA.size(); ++i) { - if (listA.at(i).get() != listB.at(i).get() - && *listA.at(i).get() != *listB.at(i).get()) - return false; - } - return true; -} - -#if !ASSERT_DISABLED -static bool checkCustomFilterParametersOrder(const CustomFilterParameterList& parameters) -{ - for (unsigned i = 1; i < parameters.size(); ++i) { - // Break for equal or not-sorted parameters. - if (!codePointCompareLessThan(parameters.at(i - 1)->name(), parameters.at(i)->name())) - return false; - } - return true; -} -#endif - -void blendCustomFilterParameters(const CustomFilterParameterList& fromList, const CustomFilterParameterList& toList, - double progress, const LayoutSize& size, CustomFilterParameterList& resultList) -{ - // This method expects both lists to be sorted by parameter name and the result list is also sorted. - ASSERT(checkCustomFilterParametersOrder(fromList)); - ASSERT(checkCustomFilterParametersOrder(toList)); - size_t fromListIndex = 0, toListIndex = 0; - while (fromListIndex < fromList.size() && toListIndex < toList.size()) { - CustomFilterParameter* paramFrom = fromList.at(fromListIndex).get(); - CustomFilterParameter* paramTo = toList.at(toListIndex).get(); - if (paramFrom->name() == paramTo->name()) { - resultList.append(paramTo->blend(paramFrom, progress, size)); - ++fromListIndex; - ++toListIndex; - continue; - } - if (codePointCompareLessThan(paramFrom->name(), paramTo->name())) { - resultList.append(paramFrom); - ++fromListIndex; - continue; - } - resultList.append(paramTo); - ++toListIndex; - } - for (; fromListIndex < fromList.size(); ++fromListIndex) - resultList.append(fromList.at(fromListIndex)); - for (; toListIndex < toList.size(); ++toListIndex) - resultList.append(toList.at(toListIndex)); - ASSERT(checkCustomFilterParametersOrder(resultList)); -} - -CustomFilterOperation::CustomFilterOperation(PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, MeshBoxType meshBoxType, MeshType meshType) +CustomFilterOperation::CustomFilterOperation(PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType meshBoxType, CustomFilterMeshType meshType) : FilterOperation(CUSTOM) , m_program(program) , m_parameters(sortedParameters) @@ -105,7 +48,7 @@ CustomFilterOperation::CustomFilterOperation(PassRefPtr<CustomFilterProgram> pro , m_meshType(meshType) { // Make sure that the parameters are alwyas sorted by name. We use that to merge two CustomFilterOperations in animations. - ASSERT(checkCustomFilterParametersOrder(m_parameters)); + ASSERT(m_parameters.checkAlphabeticalOrder()); } CustomFilterOperation::~CustomFilterOperation() @@ -129,7 +72,7 @@ PassRefPtr<FilterOperation> CustomFilterOperation::blend(const FilterOperation* return this; CustomFilterParameterList animatedParameters; - blendCustomFilterParameters(fromOp->m_parameters, m_parameters, progress, size, animatedParameters); + m_parameters.blend(fromOp->m_parameters, progress, size, animatedParameters); return CustomFilterOperation::create(m_program, animatedParameters, m_meshRows, m_meshColumns, m_meshBoxType, m_meshType); } diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h index 0d64d2368..edf0f129c 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h @@ -31,38 +31,19 @@ #define CustomFilterOperation_h #if ENABLE(CSS_SHADERS) +#include "CustomFilterConstants.h" +#include "CustomFilterParameterList.h" #include "CustomFilterProgram.h" #include "FilterOperation.h" #include "LayoutTypes.h" -#include <wtf/text/WTFString.h> - namespace WebCore { // CSS Shaders -class CustomFilterParameter; -typedef Vector<RefPtr<CustomFilterParameter> > CustomFilterParameterList; - -bool customFilterParametersEqual(const CustomFilterParameterList&, const CustomFilterParameterList&); -void blendCustomFilterParameters(const CustomFilterParameterList& listFrom, const CustomFilterParameterList& listTo, - double progress, const LayoutSize&, CustomFilterParameterList& resultList); - class CustomFilterOperation : public FilterOperation { public: - enum MeshBoxType { - FILTER_BOX, - BORDER_BOX, - PADDING_BOX, - CONTENT_BOX - }; - - enum MeshType { - ATTACHED, - DETACHED - }; - - static PassRefPtr<CustomFilterOperation> create(PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, MeshBoxType meshBoxType, MeshType meshType) + static PassRefPtr<CustomFilterOperation> create(PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType meshBoxType, CustomFilterMeshType meshType) { return adoptRef(new CustomFilterOperation(program, sortedParameters, meshRows, meshColumns, meshBoxType, meshType)); } @@ -74,8 +55,8 @@ public: unsigned meshRows() const { return m_meshRows; } unsigned meshColumns() const { return m_meshColumns; } - MeshBoxType meshBoxType() const { return m_meshBoxType; } - MeshType meshType() const { return m_meshType; } + CustomFilterMeshBoxType meshBoxType() const { return m_meshBoxType; } + CustomFilterMeshType meshType() const { return m_meshType; } virtual ~CustomFilterOperation(); @@ -92,22 +73,22 @@ private: const CustomFilterOperation* other = static_cast<const CustomFilterOperation*>(&o); return *m_program.get() == *other->m_program.get() - && m_meshRows == other->m_meshRows - && m_meshColumns == other->m_meshColumns - && m_meshBoxType == other->m_meshBoxType - && m_meshType == other->m_meshType - && customFilterParametersEqual(m_parameters, other->m_parameters); + && m_meshRows == other->m_meshRows + && m_meshColumns == other->m_meshColumns + && m_meshBoxType == other->m_meshBoxType + && m_meshType == other->m_meshType + && m_parameters == other->m_parameters; } - CustomFilterOperation(PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&, unsigned meshRows, unsigned meshColumns, MeshBoxType, MeshType); + CustomFilterOperation(PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&, unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType, CustomFilterMeshType); RefPtr<CustomFilterProgram> m_program; CustomFilterParameterList m_parameters; unsigned m_meshRows; unsigned m_meshColumns; - MeshBoxType m_meshBoxType; - MeshType m_meshType; + CustomFilterMeshBoxType m_meshBoxType; + CustomFilterMeshType m_meshType; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterParameterList.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterParameterList.cpp new file mode 100644 index 000000000..cc633e9d9 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/CustomFilterParameterList.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(CSS_SHADERS) +#include "CustomFilterParameterList.h" + +#include "CustomFilterParameter.h" +#include <wtf/text/StringHash.h> + +namespace WebCore { + +CustomFilterParameterList::CustomFilterParameterList() +{ +} + +CustomFilterParameterList::CustomFilterParameterList(size_t size) + : CustomFilterParameterListBase(size) +{ +} + +bool CustomFilterParameterList::operator==(const CustomFilterParameterList& other) const +{ + if (size() != other.size()) + return false; + for (size_t i = 0; i < size(); ++i) { + if (at(i).get() != other.at(i).get() + && *at(i).get() != *other.at(i).get()) + return false; + } + return true; +} + +bool CustomFilterParameterList::checkAlphabeticalOrder() const +{ + for (unsigned i = 1; i < size(); ++i) { + // Break for equal or not-sorted parameters. + if (!codePointCompareLessThan(at(i - 1)->name(), at(i)->name())) + return false; + } + return true; +} + +void CustomFilterParameterList::blend(const CustomFilterParameterList& fromList, + double progress, const LayoutSize& frameSize, CustomFilterParameterList& resultList) const +{ + // This method expects both lists to be sorted by parameter name and the result list is also sorted. + ASSERT(checkAlphabeticalOrder()); + ASSERT(fromList.checkAlphabeticalOrder()); + size_t fromListIndex = 0, toListIndex = 0; + while (fromListIndex < fromList.size() && toListIndex < size()) { + CustomFilterParameter* paramFrom = fromList.at(fromListIndex).get(); + CustomFilterParameter* paramTo = at(toListIndex).get(); + if (paramFrom->name() == paramTo->name()) { + resultList.append(paramTo->blend(paramFrom, progress, frameSize)); + ++fromListIndex; + ++toListIndex; + continue; + } + if (codePointCompareLessThan(paramFrom->name(), paramTo->name())) { + resultList.append(paramFrom); + ++fromListIndex; + continue; + } + resultList.append(paramTo); + ++toListIndex; + } + for (; fromListIndex < fromList.size(); ++fromListIndex) + resultList.append(fromList.at(fromListIndex)); + for (; toListIndex < size(); ++toListIndex) + resultList.append(at(toListIndex)); + ASSERT(resultList.checkAlphabeticalOrder()); +} + +} // namespace WebCore + +#endif // ENABLE(CSS_SHADERS) diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterParameterList.h b/Source/WebCore/platform/graphics/filters/CustomFilterParameterList.h new file mode 100644 index 000000000..426756e79 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/CustomFilterParameterList.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CustomFilterParameterList_h +#define CustomFilterParameterList_h + +#if ENABLE(CSS_SHADERS) +#include "LayoutTypes.h" +#include <wtf/Vector.h> + +namespace WebCore { + +class CustomFilterParameter; +typedef Vector<RefPtr<CustomFilterParameter> > CustomFilterParameterListBase; + +class CustomFilterParameterList : public CustomFilterParameterListBase { +public: + CustomFilterParameterList(); + explicit CustomFilterParameterList(size_t); + + bool checkAlphabeticalOrder() const; + void blend(const CustomFilterParameterList& from, double progress, const LayoutSize&, CustomFilterParameterList& resultList) const; + bool operator==(const CustomFilterParameterList&) const; +}; + +} // namespace WebCore + +#endif // ENABLE(CSS_SHADERS) + +#endif // CustomFilterParameterList_h diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp index c9990d98d..2a8fce076 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp @@ -38,9 +38,10 @@ namespace WebCore { -CustomFilterProgram::CustomFilterProgram(CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings) +CustomFilterProgram::CustomFilterProgram(CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType) : m_programType(programType) , m_mixSettings(mixSettings) + , m_meshType(meshType) { // Keep the constructor protected to prevent creating this object directly. } @@ -82,7 +83,14 @@ void CustomFilterProgram::notifyClients() CustomFilterProgramInfo CustomFilterProgram::programInfo() const { ASSERT(isLoaded()); - return CustomFilterProgramInfo(vertexShaderString(), fragmentShaderString(), m_programType, m_mixSettings); + return CustomFilterProgramInfo(vertexShaderString(), fragmentShaderString(), m_programType, m_mixSettings, m_meshType); +} + +bool CustomFilterProgram::operator==(const CustomFilterProgram& o) const +{ + return m_programType == o.m_programType + && (m_programType != PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE || m_mixSettings == o.m_mixSettings) + && m_meshType == o.m_meshType; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h index 0492d476d..b755bb7ac 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h @@ -51,38 +51,37 @@ public: virtual ~CustomFilterProgram(); virtual bool isLoaded() const = 0; - - CustomFilterProgramMixSettings mixSettings() const { return m_mixSettings; } void addClient(CustomFilterProgramClient*); void removeClient(CustomFilterProgramClient*); CustomFilterProgramInfo programInfo() const; + + virtual String vertexShaderString() const = 0; + virtual String fragmentShaderString() const = 0; CustomFilterProgramType programType() const { return m_programType; } + CustomFilterProgramMixSettings mixSettings() const { return m_mixSettings; } + CustomFilterMeshType meshType() const { return m_meshType; } - // StyleCustomFilterProgram has the only implementation for the following method. That means, it casts to StyleCustomFilterProgram - // withouth checking the type. If you add another implementation, also add a mechanism to check for the correct type. - virtual bool operator==(const CustomFilterProgram&) const = 0; + virtual bool operator==(const CustomFilterProgram&) const; bool operator!=(const CustomFilterProgram& o) const { return !(*this == o); } protected: // StyleCustomFilterProgram can notify the clients that the cached resources are // loaded and it is ready to create CustomFilterCompiledProgram objects. void notifyClients(); - - virtual String vertexShaderString() const = 0; - virtual String fragmentShaderString() const = 0; - + virtual void willHaveClients() = 0; virtual void didRemoveLastClient() = 0; // Keep the constructor protected to prevent creating this object directly. - CustomFilterProgram(CustomFilterProgramType, const CustomFilterProgramMixSettings&); + CustomFilterProgram(CustomFilterProgramType, const CustomFilterProgramMixSettings&, CustomFilterMeshType); private: typedef HashCountedSet<CustomFilterProgramClient*> CustomFilterProgramClientList; CustomFilterProgramClientList m_clients; CustomFilterProgramType m_programType; CustomFilterProgramMixSettings m_mixSettings; + CustomFilterMeshType m_meshType; }; } diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp index bc1494faf..ddab9a787 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp @@ -64,11 +64,12 @@ bool CustomFilterProgramInfo::isHashTableDeletedValue() const && m_fragmentShaderString.isHashTableDeletedValue(); } -CustomFilterProgramInfo::CustomFilterProgramInfo(const String& vertexShader, const String& fragmentShader, CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings) +CustomFilterProgramInfo::CustomFilterProgramInfo(const String& vertexShader, const String& fragmentShader, CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType) : m_vertexShaderString(vertexShader) , m_fragmentShaderString(fragmentShader) , m_programType(programType) , m_mixSettings(mixSettings) + , m_meshType(meshType) { // At least one of the shaders needs to be non-null. ASSERT(!m_vertexShaderString.isNull() || !m_fragmentShaderString.isNull()); @@ -78,12 +79,15 @@ unsigned CustomFilterProgramInfo::hash() const { // At least one of the shaders needs to be non-null. ASSERT(!m_vertexShaderString.isNull() || !m_fragmentShaderString.isNull()); - uintptr_t hashCodes[5] = { + + bool blendsElementTexture = (m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE); + uintptr_t hashCodes[6] = { hashPossiblyNullString(m_vertexShaderString), hashPossiblyNullString(m_fragmentShaderString), - m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE, - m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE ? m_mixSettings.blendMode : 0, - m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE ? m_mixSettings.compositeOperator : 0 + blendsElementTexture, + static_cast<uintptr_t>(blendsElementTexture ? m_mixSettings.blendMode : 0), + static_cast<uintptr_t>(blendsElementTexture ? m_mixSettings.compositeOperator : 0), + m_meshType }; return StringHasher::hashMemory<sizeof(hashCodes)>(&hashCodes); } @@ -93,15 +97,11 @@ bool CustomFilterProgramInfo::operator==(const CustomFilterProgramInfo& o) const ASSERT(!isHashTableDeletedValue()); ASSERT(!o.isHashTableDeletedValue()); - if (m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE) - return m_vertexShaderString == o.m_vertexShaderString - && m_fragmentShaderString == o.m_fragmentShaderString - && m_programType == o.m_programType - && m_mixSettings == o.m_mixSettings; - - return m_vertexShaderString == o.m_vertexShaderString - && m_fragmentShaderString == o.m_fragmentShaderString - && m_programType == o.m_programType; + return m_programType == o.m_programType + && (m_programType != PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE || m_mixSettings == o.m_mixSettings) + && m_meshType == o.m_meshType + && m_vertexShaderString == o.m_vertexShaderString + && m_fragmentShaderString == o.m_fragmentShaderString; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h index 3b544c5ad..cc60cca52 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h @@ -31,6 +31,7 @@ #define CustomFilterProgramInfo_h #if ENABLE(CSS_SHADERS) +#include "CustomFilterConstants.h" #include "GraphicsTypes.h" #include <wtf/HashTraits.h> @@ -46,7 +47,7 @@ enum CustomFilterProgramType { struct CustomFilterProgramMixSettings { CustomFilterProgramMixSettings() : blendMode(BlendModeNormal) - , compositeOperator(CompositeSourceOver) + , compositeOperator(CompositeSourceAtop) { } @@ -64,7 +65,7 @@ struct CustomFilterProgramMixSettings { // Null strings are placeholders for the default shader. class CustomFilterProgramInfo { public: - CustomFilterProgramInfo(const String&, const String&, CustomFilterProgramType, const CustomFilterProgramMixSettings&); + CustomFilterProgramInfo(const String&, const String&, CustomFilterProgramType, const CustomFilterProgramMixSettings&, CustomFilterMeshType); CustomFilterProgramInfo(); bool isEmptyValue() const; @@ -79,11 +80,13 @@ public: const String& fragmentShaderString() const { return m_fragmentShaderString; } CustomFilterProgramType programType() const { return m_programType; } const CustomFilterProgramMixSettings& mixSettings() const { return m_mixSettings; } + CustomFilterMeshType meshType() const { return m_meshType; } private: String m_vertexShaderString; String m_fragmentShaderString; CustomFilterProgramType m_programType; CustomFilterProgramMixSettings m_mixSettings; + CustomFilterMeshType m_meshType; }; struct CustomFilterProgramInfoHash { diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterRenderer.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterRenderer.cpp new file mode 100644 index 000000000..1b32852cd --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/CustomFilterRenderer.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. + * Copyright (C) 2012 Company 100, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) +#include "CustomFilterRenderer.h" + +#include "CustomFilterArrayParameter.h" +#include "CustomFilterConstants.h" +#include "CustomFilterMesh.h" +#include "CustomFilterNumberParameter.h" +#include "CustomFilterParameter.h" +#include "CustomFilterTransformParameter.h" +#include "CustomFilterValidatedProgram.h" +#include "GraphicsContext3D.h" +#include "TransformationMatrix.h" + +namespace WebCore { + +static void orthogonalProjectionMatrix(TransformationMatrix& matrix, float left, float right, float bottom, float top) +{ + ASSERT(matrix.isIdentity()); + + float deltaX = right - left; + float deltaY = top - bottom; + if (!deltaX || !deltaY) + return; + matrix.setM11(2.0f / deltaX); + matrix.setM41(-(right + left) / deltaX); + matrix.setM22(2.0f / deltaY); + matrix.setM42(-(top + bottom) / deltaY); + + // Use big enough near/far values, so that simple rotations of rather large objects will not + // get clipped. 10000 should cover most of the screen resolutions. + const float farValue = 10000; + const float nearValue = -10000; + matrix.setM33(-2.0f / (farValue - nearValue)); + matrix.setM43(- (farValue + nearValue) / (farValue - nearValue)); + matrix.setM44(1.0f); +} + +PassRefPtr<CustomFilterRenderer> CustomFilterRenderer::create(PassRefPtr<GraphicsContext3D> context, PassRefPtr<CustomFilterValidatedProgram> validatedProgram, const CustomFilterParameterList& parameters, + unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType meshBoxType, CustomFilterMeshType meshType) +{ + return adoptRef(new CustomFilterRenderer(context, validatedProgram, parameters, meshRows, meshColumns, meshBoxType, meshType)); +} + +CustomFilterRenderer::CustomFilterRenderer(PassRefPtr<GraphicsContext3D> context, PassRefPtr<CustomFilterValidatedProgram> validatedProgram, const CustomFilterParameterList& parameters, + unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType, CustomFilterMeshType meshType) + : m_context(context) + , m_validatedProgram(validatedProgram) + , m_compiledProgram(0) // Don't compile the program unless we need to paint. + , m_parameters(parameters) + , m_meshRows(meshRows) + , m_meshColumns(meshColumns) + , m_meshType(meshType) +{ +} + +CustomFilterRenderer::~CustomFilterRenderer() +{ +} + +bool CustomFilterRenderer::premultipliedAlpha() const +{ + return m_validatedProgram->programInfo().programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE; +} + +bool CustomFilterRenderer::programNeedsInputTexture() const +{ + ASSERT(m_compiledProgram.get()); + return m_compiledProgram->samplerLocation() != -1; +} + +void CustomFilterRenderer::draw(Platform3DObject inputTexture, const IntSize& size) +{ + // FIXME: We would need something like CustomFilterRendererState that will contain the size and other parameters in the future. We should pass that to bindProgramBuffers instead of storing it. + // https://bugs.webkit.org/show_bug.cgi?id=100107 + m_contextSize = size; + + bindProgramAndBuffers(inputTexture); + m_context->drawElements(GraphicsContext3D::TRIANGLES, m_mesh->indicesCount(), GraphicsContext3D::UNSIGNED_SHORT, 0); + unbindVertexAttributes(); +} + +bool CustomFilterRenderer::prepareForDrawing() +{ + m_context->makeContextCurrent(); + initializeCompiledProgramIfNeeded(); + + // If the shader had compiler errors we cannot draw anything. + if (!m_compiledProgram->isInitialized()) + return false; + + initializeMeshIfNeeded(); + return true; +} + +void CustomFilterRenderer::initializeCompiledProgramIfNeeded() +{ + if (m_compiledProgram.get()) + return; + + m_compiledProgram = m_validatedProgram->compiledProgram(); +} + +void CustomFilterRenderer::initializeMeshIfNeeded() +{ + if (m_mesh.get()) + return; + + // FIXME: Sharing the mesh would just save the time needed to upload it to the GPU, so I assume we could + // benchmark that for performance. + // https://bugs.webkit.org/show_bug.cgi?id=88429 + m_mesh = CustomFilterMesh::create(m_context.get(), m_meshColumns, m_meshRows, FloatRect(0, 0, 1, 1), m_meshType); +} + +void CustomFilterRenderer::bindVertexAttribute(int attributeLocation, unsigned size, unsigned offset) +{ + if (attributeLocation != -1) { + m_context->vertexAttribPointer(attributeLocation, size, GraphicsContext3D::FLOAT, false, m_mesh->bytesPerVertex(), offset); + m_context->enableVertexAttribArray(attributeLocation); + } +} + +void CustomFilterRenderer::unbindVertexAttribute(int attributeLocation) +{ + if (attributeLocation != -1) + m_context->disableVertexAttribArray(attributeLocation); +} + +void CustomFilterRenderer::bindProgramArrayParameters(int uniformLocation, CustomFilterArrayParameter* arrayParameter) +{ + unsigned parameterSize = arrayParameter->size(); + Vector<GC3Dfloat> floatVector; + + for (unsigned i = 0; i < parameterSize; ++i) + floatVector.append(arrayParameter->valueAt(i)); + + m_context->uniform1fv(uniformLocation, parameterSize, floatVector.data()); +} + +void CustomFilterRenderer::bindProgramNumberParameters(int uniformLocation, CustomFilterNumberParameter* numberParameter) +{ + switch (numberParameter->size()) { + case 1: + m_context->uniform1f(uniformLocation, numberParameter->valueAt(0)); + break; + case 2: + m_context->uniform2f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1)); + break; + case 3: + m_context->uniform3f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1), numberParameter->valueAt(2)); + break; + case 4: + m_context->uniform4f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1), numberParameter->valueAt(2), numberParameter->valueAt(3)); + break; + default: + ASSERT_NOT_REACHED(); + } +} + +void CustomFilterRenderer::bindProgramTransformParameter(int uniformLocation, CustomFilterTransformParameter* transformParameter) +{ + TransformationMatrix matrix; + if (m_contextSize.width() && m_contextSize.height()) { + // The viewport is a box with the size of 1 unit, so we are scaling up here to make sure that translations happen using real pixel + // units. At the end we scale back down in order to map it back to the original box. Note that transforms come in reverse order, because it is + // supposed to multiply to the left of the coordinates of the vertices. + // Note that the origin (0, 0) of the viewport is in the middle of the context, so there's no need to change the origin of the transform + // in order to rotate around the middle of mesh. + matrix.scale3d(1.0 / m_contextSize.width(), 1.0 / m_contextSize.height(), 1); + transformParameter->applyTransform(matrix, m_contextSize); + matrix.scale3d(m_contextSize.width(), m_contextSize.height(), 1); + } + float glMatrix[16]; + matrix.toColumnMajorFloatArray(glMatrix); + m_context->uniformMatrix4fv(uniformLocation, 1, false, &glMatrix[0]); +} + +void CustomFilterRenderer::bindProgramParameters() +{ + // FIXME: Find a way to reset uniforms that are not specified in CSS. This is needed to avoid using values + // set by other previous rendered filters. + // https://bugs.webkit.org/show_bug.cgi?id=76440 + + size_t parametersSize = m_parameters.size(); + for (size_t i = 0; i < parametersSize; ++i) { + CustomFilterParameter* parameter = m_parameters.at(i).get(); + int uniformLocation = m_compiledProgram->uniformLocationByName(parameter->name()); + if (uniformLocation == -1) + continue; + switch (parameter->parameterType()) { + case CustomFilterParameter::ARRAY: + bindProgramArrayParameters(uniformLocation, static_cast<CustomFilterArrayParameter*>(parameter)); + break; + case CustomFilterParameter::NUMBER: + bindProgramNumberParameters(uniformLocation, static_cast<CustomFilterNumberParameter*>(parameter)); + break; + case CustomFilterParameter::TRANSFORM: + bindProgramTransformParameter(uniformLocation, static_cast<CustomFilterTransformParameter*>(parameter)); + break; + } + } +} + +void CustomFilterRenderer::bindProgramAndBuffers(Platform3DObject inputTexture) +{ + ASSERT(m_compiledProgram->isInitialized()); + + m_context->useProgram(m_compiledProgram->program()); + + if (programNeedsInputTexture()) { + // We should be binding the DOM element texture sampler only if the author is using the CSS mix function. + ASSERT(m_validatedProgram->programInfo().programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE); + ASSERT(m_compiledProgram->samplerLocation() != -1); + + m_context->activeTexture(GraphicsContext3D::TEXTURE0); + m_context->uniform1i(m_compiledProgram->samplerLocation(), 0); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, inputTexture); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + } + + if (m_compiledProgram->projectionMatrixLocation() != -1) { + TransformationMatrix projectionMatrix; + orthogonalProjectionMatrix(projectionMatrix, -0.5, 0.5, -0.5, 0.5); + float glProjectionMatrix[16]; + projectionMatrix.toColumnMajorFloatArray(glProjectionMatrix); + m_context->uniformMatrix4fv(m_compiledProgram->projectionMatrixLocation(), 1, false, &glProjectionMatrix[0]); + } + + ASSERT(m_meshColumns); + ASSERT(m_meshRows); + + if (m_compiledProgram->meshSizeLocation() != -1) + m_context->uniform2f(m_compiledProgram->meshSizeLocation(), m_meshColumns, m_meshRows); + + if (m_compiledProgram->tileSizeLocation() != -1) + m_context->uniform2f(m_compiledProgram->tileSizeLocation(), 1.0 / m_meshColumns, 1.0 / m_meshRows); + + if (m_compiledProgram->meshBoxLocation() != -1) { + // FIXME: This will change when filter margins will be implemented, + // see https://bugs.webkit.org/show_bug.cgi?id=71400 + m_context->uniform4f(m_compiledProgram->meshBoxLocation(), -0.5, -0.5, 1.0, 1.0); + } + + if (m_compiledProgram->samplerSizeLocation() != -1) + m_context->uniform2f(m_compiledProgram->samplerSizeLocation(), m_contextSize.width(), m_contextSize.height()); + + m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_mesh->verticesBufferObject()); + m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_mesh->elementsBufferObject()); + + bindVertexAttribute(m_compiledProgram->positionAttribLocation(), PositionAttribSize, PositionAttribOffset); + bindVertexAttribute(m_compiledProgram->texAttribLocation(), TexAttribSize, TexAttribOffset); + bindVertexAttribute(m_compiledProgram->meshAttribLocation(), MeshAttribSize, MeshAttribOffset); + if (m_meshType == MeshTypeDetached) + bindVertexAttribute(m_compiledProgram->triangleAttribLocation(), TriangleAttribSize, TriangleAttribOffset); + + bindProgramParameters(); +} + +void CustomFilterRenderer::unbindVertexAttributes() +{ + unbindVertexAttribute(m_compiledProgram->positionAttribLocation()); + unbindVertexAttribute(m_compiledProgram->texAttribLocation()); + unbindVertexAttribute(m_compiledProgram->meshAttribLocation()); + if (m_meshType == MeshTypeDetached) + unbindVertexAttribute(m_compiledProgram->triangleAttribLocation()); +} + +} // namespace WebCore + +#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterRenderer.h b/Source/WebCore/platform/graphics/filters/CustomFilterRenderer.h new file mode 100644 index 000000000..c0622ee04 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/CustomFilterRenderer.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. + * Copyright (C) 2012 Company 100, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CustomFilterRenderer_h +#define CustomFilterRenderer_h + +#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) + +#include "CustomFilterConstants.h" +#include "CustomFilterParameterList.h" +#include "GraphicsTypes3D.h" +#include "IntSize.h" +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CustomFilterArrayParameter; +class CustomFilterCompiledProgram; +class CustomFilterMesh; +class CustomFilterNumberParameter; +class CustomFilterTransformParameter; +class CustomFilterValidatedProgram; +class GraphicsContext3D; + +class CustomFilterRenderer : public RefCounted<CustomFilterRenderer> { +public: + static PassRefPtr<CustomFilterRenderer> create(PassRefPtr<GraphicsContext3D>, PassRefPtr<CustomFilterValidatedProgram>, const CustomFilterParameterList&, + unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType, CustomFilterMeshType); + ~CustomFilterRenderer(); + + bool premultipliedAlpha() const; + bool programNeedsInputTexture() const; + + bool prepareForDrawing(); + + void draw(Platform3DObject, const IntSize&); + +private: + CustomFilterRenderer(PassRefPtr<GraphicsContext3D>, PassRefPtr<CustomFilterValidatedProgram>, const CustomFilterParameterList&, + unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType, CustomFilterMeshType); + + void initializeCompiledProgramIfNeeded(); + void initializeMeshIfNeeded(); + + void bindVertexAttribute(int attributeLocation, unsigned size, unsigned offset); + void unbindVertexAttribute(int attributeLocation); + void bindProgramArrayParameters(int uniformLocation, CustomFilterArrayParameter*); + void bindProgramNumberParameters(int uniformLocation, CustomFilterNumberParameter*); + void bindProgramTransformParameter(int uniformLocation, CustomFilterTransformParameter*); + void bindProgramParameters(); + void bindProgramAndBuffers(Platform3DObject inputTexture); + void unbindVertexAttributes(); + + RefPtr<GraphicsContext3D> m_context; + RefPtr<CustomFilterValidatedProgram> m_validatedProgram; + RefPtr<CustomFilterCompiledProgram> m_compiledProgram; + RefPtr<CustomFilterMesh> m_mesh; + IntSize m_contextSize; + + CustomFilterParameterList m_parameters; + + unsigned m_meshRows; + unsigned m_meshColumns; + CustomFilterMeshType m_meshType; +}; + +} // namespace WebCore + +#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) + +#endif // CustomFilterRenderer_h diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp index 26e8b7e5f..f5ef6cff9 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp @@ -34,10 +34,12 @@ #include "CustomFilterValidatedProgram.h" #include "ANGLEWebKitBridge.h" +#include "CustomFilterConstants.h" #include "CustomFilterGlobalContext.h" #include "CustomFilterProgramInfo.h" #include "NotImplemented.h" #include <wtf/HashMap.h> +#include <wtf/Vector.h> #include <wtf/text/StringBuilder.h> #include <wtf/text/StringHash.h> @@ -45,8 +47,6 @@ namespace WebCore { #define SHADER(Src) (#Src) -// FIXME: Reuse this type when we validate the types of built-in uniforms. -// https://bugs.webkit.org/show_bug.cgi?id=98974 typedef HashMap<String, ShDataType> SymbolNameToTypeMap; static SymbolNameToTypeMap* builtInAttributeNameToTypeMap() @@ -62,7 +62,21 @@ static SymbolNameToTypeMap* builtInAttributeNameToTypeMap() return nameToTypeMap; } -static bool validateSymbols(const Vector<ANGLEShaderSymbol>& symbols) +static SymbolNameToTypeMap* builtInUniformNameToTypeMap() +{ + static SymbolNameToTypeMap* nameToTypeMap = 0; + if (!nameToTypeMap) { + nameToTypeMap = new SymbolNameToTypeMap; + nameToTypeMap->set("u_meshBox", SH_FLOAT_VEC4); + nameToTypeMap->set("u_meshSize", SH_FLOAT_VEC2); + nameToTypeMap->set("u_projectionMatrix", SH_FLOAT_MAT4); + nameToTypeMap->set("u_textureSize", SH_FLOAT_VEC2); + nameToTypeMap->set("u_tileSize", SH_FLOAT_VEC2); + } + return nameToTypeMap; +} + +static bool validateSymbols(const Vector<ANGLEShaderSymbol>& symbols, CustomFilterMeshType meshType) { for (size_t i = 0; i < symbols.size(); ++i) { const ANGLEShaderSymbol& symbol = symbols[i]; @@ -70,16 +84,27 @@ static bool validateSymbols(const Vector<ANGLEShaderSymbol>& symbols) case SHADER_SYMBOL_TYPE_ATTRIBUTE: { SymbolNameToTypeMap* attributeNameToTypeMap = builtInAttributeNameToTypeMap(); SymbolNameToTypeMap::iterator builtInAttribute = attributeNameToTypeMap->find(symbol.name); - if (builtInAttribute != attributeNameToTypeMap->end() && symbol.dataType != builtInAttribute->value) { + if (builtInAttribute == attributeNameToTypeMap->end()) { + // The author defined a custom attribute. + // FIXME: Report the validation error. + // https://bugs.webkit.org/show_bug.cgi?id=74416 + return false; + } + if (meshType == MeshTypeAttached && symbol.name == "a_triangleCoord") { + // a_triangleCoord is only available for detached meshes. + // FIXME: Report the validation error. + // https://bugs.webkit.org/show_bug.cgi?id=74416 + return false; + } + if (symbol.dataType != builtInAttribute->value) { // The author defined one of the built-in attributes with the wrong type. + // FIXME: Report the validation error. + // https://bugs.webkit.org/show_bug.cgi?id=74416 return false; } - - // FIXME: Return false when the attribute is not one of the built-in attributes. - // https://bugs.webkit.org/show_bug.cgi?id=98973 break; } - case SHADER_SYMBOL_TYPE_UNIFORM: + case SHADER_SYMBOL_TYPE_UNIFORM: { if (symbol.isSampler()) { // FIXME: For now, we restrict shaders with any sampler defined. // When we implement texture parameters, we will allow shaders whose samplers are bound to valid textures. @@ -89,9 +114,16 @@ static bool validateSymbols(const Vector<ANGLEShaderSymbol>& symbols) return false; } - // FIXME: Validate the types of built-in uniforms. - // https://bugs.webkit.org/show_bug.cgi?id=98974 + SymbolNameToTypeMap* uniformNameToTypeMap = builtInUniformNameToTypeMap(); + SymbolNameToTypeMap::iterator builtInUniform = uniformNameToTypeMap->find(symbol.name); + if (builtInUniform != uniformNameToTypeMap->end() && (symbol.isArray || symbol.dataType != builtInUniform->value)) { + // The author defined one of the built-in uniforms with the wrong type. + // FIXME: Report the validation error. + // https://bugs.webkit.org/show_bug.cgi?id=74416 + return false; + } break; + } default: ASSERT_NOT_REACHED(); break; @@ -153,7 +185,7 @@ CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalCon return; } - if (!validateSymbols(symbols)) { + if (!validateSymbols(symbols, m_programInfo.meshType())) { // FIXME: Report validation errors. // https://bugs.webkit.org/show_bug.cgi?id=74416 return; @@ -161,7 +193,7 @@ CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalCon // We need to add texture access, blending, and compositing code to shaders that are referenced from the CSS mix function. if (blendsElementTexture) { - rewriteMixVertexShader(); + rewriteMixVertexShader(symbols); rewriteMixFragmentShader(); } @@ -171,26 +203,46 @@ CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalCon PassRefPtr<CustomFilterCompiledProgram> CustomFilterValidatedProgram::compiledProgram() { ASSERT(m_isInitialized && m_globalContext && !m_validatedVertexShader.isNull() && !m_validatedFragmentShader.isNull()); - if (!m_compiledProgram) + if (!m_compiledProgram) { m_compiledProgram = CustomFilterCompiledProgram::create(m_globalContext->context(), m_validatedVertexShader, m_validatedFragmentShader, m_programInfo.programType()); + ASSERT(m_compiledProgram->samplerLocation() != -1 || !needsInputTexture()); + } return m_compiledProgram; } -void CustomFilterValidatedProgram::rewriteMixVertexShader() +bool CustomFilterValidatedProgram::needsInputTexture() const +{ + return m_programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE + && m_programInfo.mixSettings().compositeOperator != CompositeClear + && m_programInfo.mixSettings().compositeOperator != CompositeCopy; +} + +void CustomFilterValidatedProgram::rewriteMixVertexShader(const Vector<ANGLEShaderSymbol>& symbols) { ASSERT(m_programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE); + // If the author defined a_texCoord, we can use it to shuttle the texture coordinate to the fragment shader. + // Note that vertex attributes are read-only in GLSL, so the author could not have changed a_texCoord's value. + // Also, note that we would have already rejected the shader if the author defined a_texCoord with the wrong type. + bool texCoordAttributeDefined = false; + for (size_t i = 0; i < symbols.size(); ++i) { + if (symbols[i].name == "a_texCoord") + texCoordAttributeDefined = true; + } + + if (!texCoordAttributeDefined) + m_validatedVertexShader.append("attribute mediump vec2 a_texCoord;"); + // During validation, ANGLE renamed the author's "main" function to "css_main". // We write our own "main" function and call "css_main" from it. // This makes rewriting easy and ensures that our code runs after all author code. m_validatedVertexShader.append(SHADER( - attribute mediump vec2 css_a_texCoord; varying mediump vec2 css_v_texCoord; void main() { css_main(); - css_v_texCoord = css_a_texCoord; + css_v_texCoord = a_texCoord; } )); } @@ -222,7 +274,7 @@ void CustomFilterValidatedProgram::rewriteMixFragmentShader() css_main(); mediump vec4 originalColor = texture2D(css_u_texture, css_v_texCoord); mediump vec4 multipliedColor = css_ColorMatrix * originalColor; - mediump vec3 blendedColor = css_Blend(multipliedColor.rgb, css_MixColor.rgb); + mediump vec3 blendedColor = css_BlendColor(multipliedColor.rgb, css_MixColor.rgb); gl_FragColor = css_Composite(multipliedColor.rgb, multipliedColor.a, blendedColor.rgb, css_MixColor.a); } )); @@ -233,36 +285,124 @@ String CustomFilterValidatedProgram::blendFunctionString(BlendMode blendMode) { // Implemented using the same symbol names as the Compositing and Blending spec: // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnormal - // Cs: is the source color - // Cb: is the backdrop color - const char* expression = 0; + // Cs: is the source color in css_BlendColor() and the source color component in css_BlendComponent() + // Cb: is the backdrop color in css_BlendColor() and the backdrop color component in css_BlendComponent() + const char* blendColorExpression = "vec3(css_BlendComponent(Cb.r, Cs.r), css_BlendComponent(Cb.g, Cs.g), css_BlendComponent(Cb.b, Cs.b))"; + const char* blendComponentExpression = "Co = 0.0;"; switch (blendMode) { case BlendModeNormal: - expression = "Cs"; + blendColorExpression = "Cs"; break; case BlendModeMultiply: - expression = "Cs * Cb"; + blendColorExpression = "Cs * Cb"; break; case BlendModeScreen: - expression = "Cb + Cs - (Cb * Cs)"; + blendColorExpression = "Cb + Cs - (Cb * Cs)"; break; case BlendModeDarken: - expression = "min(Cb, Cs)"; + blendColorExpression = "min(Cb, Cs)"; break; case BlendModeLighten: - expression = "max(Cb, Cs)"; + blendColorExpression = "max(Cb, Cs)"; break; case BlendModeDifference: - expression = "abs(Cb - Cs)"; + blendColorExpression = "abs(Cb - Cs)"; break; case BlendModeExclusion: - expression = "Cb + Cs - 2.0 * Cb * Cs"; + blendColorExpression = "Cb + Cs - 2.0 * Cb * Cs"; break; case BlendModeOverlay: + /* + Co = HardLight(Cs, Cb) + = if(Cb <= 0.5) + Multiply(Cs, 2 x Cb) + else + Screen(Cs, 2 x Cb - 1) + = if(Cb <= 0.5) + Cs x (2 x Cb) + else + Cs + (2 x Cb - 1) - (Cs x (2 x Cb - 1)) + */ + blendComponentExpression = SHADER( + if (Cb <= 0.5) + Co = Cs * (2.0 * Cb); + else + Co = Cs + (2.0 * Cb - 1.0) - (Cs * (2.0 * Cb - 1.0)); + ); + break; case BlendModeColorDodge: + /* + Co = if(Cs < 1) + min(1, Cb / (1 - Cs)) + else + 1 + */ + blendComponentExpression = SHADER( + if (Cs < 1.0) + Co = min(1.0, Cb / (1.0 - Cs)); + else + Co = 1.0; + ); + break; case BlendModeColorBurn: + /* + Co = if(Cs > 0) + 1 - min(1, (1 - Cb) / Cs) + else + 0 + */ + blendComponentExpression = SHADER( + if (Cs > 0.0) + Co = 1.0 - min(1.0, (1.0 - Cb) / Cs); + else + Co = 0.0; + ); + break; case BlendModeHardLight: + /* + Co = if(Cs <= 0.5) + Multiply(Cb, 2 x Cs) + else + Screen(Cb, 2 x Cs -1) + = if(Cs <= 0.5) + Cb x (2 x Cs) + else + Cb + (2 x Cs - 1) - (Cb x (2 x Cs - 1)) + */ + blendComponentExpression = SHADER( + if (Cs <= 0.5) + Co = Cb * (2.0 * Cs); + else + Co = Cb + (2.0 * Cs - 1.0) - (Cb * (2.0 * Cs - 1.0)); + ); + break; case BlendModeSoftLight: + /* + Co = if(Cs <= 0.5) + Cb - (1 - 2 x Cs) x Cb x (1 - Cb) + else + Cb + (2 x Cs - 1) x (D(Cb) - Cb) + + with + + D(Cb) = if(Cb <= 0.25) + (16 * Cb - 12) x Cb + 4) x Cb + else + sqrt(Cb) + */ + blendComponentExpression = SHADER( + mediump float D; + if (Cb <= 0.25) + D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb; + else + D = sqrt(Cb); + + if (Cs <= 0.5) + Co = Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb); + else + Co = Cb + (2.0 * Cs - 1.0) * (D - Cb); + ); + break; case BlendModeHue: case BlendModeSaturation: case BlendModeColor: @@ -271,13 +411,18 @@ String CustomFilterValidatedProgram::blendFunctionString(BlendMode blendMode) return String(); } - ASSERT(expression); return String::format(SHADER( - mediump vec3 css_Blend(mediump vec3 Cb, mediump vec3 Cs) + mediump float css_BlendComponent(mediump float Cb, mediump float Cs) + { + mediump float Co; + %s + return Co; + } + mediump vec3 css_BlendColor(mediump vec3 Cb, mediump vec3 Cs) { return %s; } - ), expression); + ), blendComponentExpression, blendColorExpression); } String CustomFilterValidatedProgram::compositeFunctionString(CompositeOperator compositeOperator) @@ -298,15 +443,45 @@ String CustomFilterValidatedProgram::compositeFunctionString(CompositeOperator c Fb = "1.0 - as"; break; case CompositeClear: + Fa = "0.0"; + Fb = "0.0"; + break; case CompositeCopy: + Fa = "1.0"; + Fb = "0.0"; + break; case CompositeSourceOver: + Fa = "1.0"; + Fb = "1.0 - as"; + break; case CompositeSourceIn: + Fa = "ab"; + Fb = "0.0"; + break; case CompositeSourceOut: + Fa = "1.0 - ab"; + Fb = "0.0"; + break; case CompositeDestinationOver: + Fa = "1.0 - ab"; + Fb = "1.0"; + break; case CompositeDestinationIn: + Fa = "0.0"; + Fb = "as"; + break; case CompositeDestinationOut: + Fa = "0.0"; + Fb = "1.0 - as"; + break; case CompositeDestinationAtop: + Fa = "1.0 - ab"; + Fb = "as"; + break; case CompositeXOR: + Fa = "1.0 - ab"; + Fb = "1.0 - as"; + break; case CompositePlusLighter: notImplemented(); return String(); diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.h b/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.h index 610884d6e..b722ac35c 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.h @@ -49,7 +49,7 @@ typedef WebCore::LayerCompiledProgram PlatformCompiledProgram; namespace WebCore { -class ANGLEWebKitBridge; +struct ANGLEShaderSymbol; class CustomFilterCompiledProgram; class CustomFilterGlobalContext; @@ -100,9 +100,11 @@ private: static String blendFunctionString(BlendMode); static String compositeFunctionString(CompositeOperator); - void rewriteMixVertexShader(); + void rewriteMixVertexShader(const Vector<ANGLEShaderSymbol>& symbols); void rewriteMixFragmentShader(); + bool needsInputTexture() const; + CustomFilterGlobalContext* m_globalContext; CustomFilterProgramInfo m_programInfo; diff --git a/Source/WebCore/platform/graphics/filters/FEBlend.h b/Source/WebCore/platform/graphics/filters/FEBlend.h index e58c8a3d0..5c71c2b72 100644 --- a/Source/WebCore/platform/graphics/filters/FEBlend.h +++ b/Source/WebCore/platform/graphics/filters/FEBlend.h @@ -51,6 +51,7 @@ public: unsigned colorArrayLength); #if USE(SKIA) virtual bool platformApplySkia(); + virtual SkImageFilter* createImageFilter(SkiaImageFilterBuilder*); #endif virtual void platformApplySoftware(); diff --git a/Source/WebCore/platform/graphics/filters/FEColorMatrix.h b/Source/WebCore/platform/graphics/filters/FEColorMatrix.h index 27a4ac843..99b650b9c 100644 --- a/Source/WebCore/platform/graphics/filters/FEColorMatrix.h +++ b/Source/WebCore/platform/graphics/filters/FEColorMatrix.h @@ -51,6 +51,7 @@ public: virtual void platformApplySoftware(); #if USE(SKIA) virtual bool platformApplySkia(); + virtual SkImageFilter* createImageFilter(SkiaImageFilterBuilder*); #endif virtual void dump(); diff --git a/Source/WebCore/platform/graphics/filters/FEComponentTransfer.h b/Source/WebCore/platform/graphics/filters/FEComponentTransfer.h index 18183e6cc..68454fd35 100644 --- a/Source/WebCore/platform/graphics/filters/FEComponentTransfer.h +++ b/Source/WebCore/platform/graphics/filters/FEComponentTransfer.h @@ -81,6 +81,7 @@ public: virtual void platformApplySoftware(); #if USE(SKIA) virtual bool platformApplySkia(); + virtual SkImageFilter* createImageFilter(SkiaImageFilterBuilder*); #endif virtual void dump(); diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp index 707edb866..45a110fb2 100644 --- a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp +++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp @@ -33,61 +33,22 @@ #if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #include "FECustomFilter.h" -#include "CustomFilterArrayParameter.h" -#include "CustomFilterCompiledProgram.h" -#include "CustomFilterConstants.h" -#include "CustomFilterGlobalContext.h" -#include "CustomFilterMesh.h" -#include "CustomFilterNumberParameter.h" -#include "CustomFilterParameter.h" -#include "CustomFilterProgram.h" -#include "CustomFilterTransformParameter.h" +#include "CustomFilterRenderer.h" #include "CustomFilterValidatedProgram.h" -#include "DrawingBuffer.h" #include "Extensions3D.h" #include "GraphicsContext3D.h" -#include "ImageData.h" -#include "NotImplemented.h" #include "RenderTreeAsText.h" #include "TextStream.h" -#include "TilingData.h" -#include "TransformationMatrix.h" #include <wtf/Uint8ClampedArray.h> namespace WebCore { -static const int kMaxSampleCount = 4; - -static void orthogonalProjectionMatrix(TransformationMatrix& matrix, float left, float right, float bottom, float top) -{ - ASSERT(matrix.isIdentity()); - - float deltaX = right - left; - float deltaY = top - bottom; - if (!deltaX || !deltaY) - return; - matrix.setM11(2.0f / deltaX); - matrix.setM41(-(right + left) / deltaX); - matrix.setM22(2.0f / deltaY); - matrix.setM42(-(top + bottom) / deltaY); - - // Use big enough near/far values, so that simple rotations of rather large objects will not - // get clipped. 10000 should cover most of the screen resolutions. - const float farValue = 10000; - const float nearValue = -10000; - matrix.setM33(-2.0f / (farValue - nearValue)); - matrix.setM43(- (farValue + nearValue) / (farValue - nearValue)); - matrix.setM44(1.0f); -} - -FECustomFilter::FECustomFilter(Filter* filter, CustomFilterGlobalContext* customFilterGlobalContext, PassRefPtr<CustomFilterValidatedProgram> validatedProgram, const CustomFilterParameterList& parameters, - unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType, - CustomFilterOperation::MeshType meshType) +FECustomFilter::FECustomFilter(Filter* filter, PassRefPtr<GraphicsContext3D> context, PassRefPtr<CustomFilterValidatedProgram> validatedProgram, const CustomFilterParameterList& parameters, + unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType meshBoxType, CustomFilterMeshType meshType) : FilterEffect(filter) - , m_globalContext(customFilterGlobalContext) - , m_validatedProgram(validatedProgram) - , m_compiledProgram(0) // Don't compile the program unless we need to paint. + , m_context(context) + , m_customFilterRenderer(CustomFilterRenderer::create(m_context, validatedProgram, parameters, meshRows, meshColumns, meshBoxType, meshType)) , m_inputTexture(0) , m_frameBuffer(0) , m_depthBuffer(0) @@ -96,20 +57,13 @@ FECustomFilter::FECustomFilter(Filter* filter, CustomFilterGlobalContext* custom , m_multisampleFrameBuffer(0) , m_multisampleRenderBuffer(0) , m_multisampleDepthBuffer(0) - , m_parameters(parameters) - , m_meshRows(meshRows) - , m_meshColumns(meshColumns) - , m_meshType(meshType) { - // An FECustomFilter shouldn't have been created unless the program passed validation. - ASSERT(m_validatedProgram->isInitialized()); } -PassRefPtr<FECustomFilter> FECustomFilter::create(Filter* filter, CustomFilterGlobalContext* customFilterGlobalContext, PassRefPtr<CustomFilterValidatedProgram> validatedProgram, const CustomFilterParameterList& parameters, - unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType meshBoxType, - CustomFilterOperation::MeshType meshType) +PassRefPtr<FECustomFilter> FECustomFilter::create(Filter* filter, PassRefPtr<GraphicsContext3D> context, PassRefPtr<CustomFilterValidatedProgram> validatedProgram, const CustomFilterParameterList& parameters, + unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType meshBoxType, CustomFilterMeshType meshType) { - return adoptRef(new FECustomFilter(filter, customFilterGlobalContext, validatedProgram, parameters, meshRows, meshColumns, meshBoxType, meshType)); + return adoptRef(new FECustomFilter(filter, context, validatedProgram, parameters, meshRows, meshColumns, meshBoxType, meshType)); } FECustomFilter::~FECustomFilter() @@ -119,8 +73,7 @@ FECustomFilter::~FECustomFilter() void FECustomFilter::deleteRenderBuffers() { - if (!m_context) - return; + ASSERT(m_context); m_context->makeContextCurrent(); if (m_inputTexture) { m_context->deleteTexture(m_inputTexture); @@ -187,45 +140,33 @@ void FECustomFilter::drawFilterMesh(Platform3DObject inputTexture) bool multisample = canUseMultisampleBuffers(); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, multisample ? m_multisampleFrameBuffer : m_frameBuffer); m_context->viewport(0, 0, m_contextSize.width(), m_contextSize.height()); - + m_context->clearColor(0, 0, 0, 0); m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT); - - bindProgramAndBuffers(inputTexture); - m_context->drawElements(GraphicsContext3D::TRIANGLES, m_mesh->indicesCount(), GraphicsContext3D::UNSIGNED_SHORT, 0); - unbindVertexAttributes(); + + m_customFilterRenderer->draw(inputTexture, m_contextSize); if (multisample) resolveMultisampleBuffer(); } -bool FECustomFilter::prepareForDrawing(CustomFilterDrawType filterDrawType) +bool FECustomFilter::prepareForDrawing() { - if (!m_context && !initializeContext()) - return false; m_context->makeContextCurrent(); - // If the shader had compiler errors we cannot draw anything. - if (!m_compiledProgram->isInitialized()) + if (!m_customFilterRenderer->prepareForDrawing()) return false; - + // Only allocate a texture if the program needs one and the caller doesn't allocate one by itself. - if ((programNeedsInputTexture() && (filterDrawType == NEEDS_INPUT_TEXTURE) && !ensureInputTexture()) - || !ensureFrameBuffer()) + if ((m_customFilterRenderer->programNeedsInputTexture() && !ensureInputTexture()) || !ensureFrameBuffer()) return false; - - return true; -} -bool FECustomFilter::programNeedsInputTexture() const -{ - ASSERT(m_compiledProgram.get()); - return m_compiledProgram->samplerLocation() != -1; + return true; } bool FECustomFilter::applyShader() { - Uint8ClampedArray* dstPixelArray = m_validatedProgram->programInfo().programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE ? createPremultipliedImageResult() : createUnmultipliedImageResult(); + Uint8ClampedArray* dstPixelArray = m_customFilterRenderer->premultipliedAlpha() ? createPremultipliedImageResult() : createUnmultipliedImageResult(); if (!dstPixelArray) return false; @@ -238,7 +179,7 @@ bool FECustomFilter::applyShader() if (!resizeContextIfNeeded(newContextSize)) return false; - bool needsInputTexture = programNeedsInputTexture(); + bool needsInputTexture = m_customFilterRenderer->programNeedsInputTexture(); if (needsInputTexture) { RefPtr<Uint8ClampedArray> srcPixelArray = in->asUnmultipliedImage(effectDrawingRect); uploadInputTexture(srcPixelArray.get()); @@ -251,25 +192,6 @@ bool FECustomFilter::applyShader() return true; } -bool FECustomFilter::initializeContext() -{ - ASSERT(!m_context.get()); - m_context = m_globalContext->context(); - if (!m_context) - return false; - m_context->makeContextCurrent(); - m_compiledProgram = m_validatedProgram->compiledProgram(); - - // FIXME: Sharing the mesh would just save the time needed to upload it to the GPU, so I assume we could - // benchmark that for performance. - // https://bugs.webkit.org/show_bug.cgi?id=88429 - m_mesh = CustomFilterMesh::create(m_context.get(), m_meshColumns, m_meshRows, - FloatRect(0, 0, 1, 1), - m_meshType); - - return true; -} - bool FECustomFilter::ensureInputTexture() { if (!m_inputTexture) @@ -332,7 +254,7 @@ void FECustomFilter::resolveMultisampleBuffer() m_context->bindFramebuffer(Extensions3D::READ_FRAMEBUFFER, 0); m_context->bindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, 0); - + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_frameBuffer); } @@ -344,11 +266,12 @@ bool FECustomFilter::canUseMultisampleBuffers() const bool FECustomFilter::resizeMultisampleBuffers(const IntSize& newContextSize) { if (!m_triedMultisampleBuffer && !createMultisampleBuffer()) - return false; - + return false; + if (!canUseMultisampleBuffers()) return false; + static const int kMaxSampleCount = 4; int maxSupportedSampleCount = 0; m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSupportedSampleCount); int sampleCount = std::min(kMaxSampleCount, maxSupportedSampleCount); @@ -359,7 +282,7 @@ bool FECustomFilter::resizeMultisampleBuffers(const IntSize& newContextSize) Extensions3D* extensions = m_context->getExtensions(); ASSERT(extensions); - + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFrameBuffer); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleRenderBuffer); @@ -409,7 +332,7 @@ bool FECustomFilter::resizeContext(const IntSize& newContextSize) m_context->texImage2DDirect(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, newContextSize.width(), newContextSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0); #endif m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_destTexture, 0); - + // We don't need the depth buffer for the texture framebuffer, if we already // have a multisample buffer. if (!multisample) { @@ -428,171 +351,11 @@ bool FECustomFilter::resizeContext(const IntSize& newContextSize) } m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); - + m_contextSize = newContextSize; return true; } -void FECustomFilter::bindVertexAttribute(int attributeLocation, unsigned size, unsigned offset) -{ - if (attributeLocation != -1) { - m_context->vertexAttribPointer(attributeLocation, size, GraphicsContext3D::FLOAT, false, m_mesh->bytesPerVertex(), offset); - m_context->enableVertexAttribArray(attributeLocation); - } -} - -void FECustomFilter::unbindVertexAttribute(int attributeLocation) -{ - if (attributeLocation != -1) - m_context->disableVertexAttribArray(attributeLocation); -} - -void FECustomFilter::bindProgramArrayParameters(int uniformLocation, CustomFilterArrayParameter* arrayParameter) -{ - unsigned parameterSize = arrayParameter->size(); - Vector<GC3Dfloat> floatVector; - - for (unsigned i = 0; i < parameterSize; ++i) - floatVector.append(arrayParameter->valueAt(i)); - - m_context->uniform1fv(uniformLocation, parameterSize, floatVector.data()); -} - -void FECustomFilter::bindProgramNumberParameters(int uniformLocation, CustomFilterNumberParameter* numberParameter) -{ - switch (numberParameter->size()) { - case 1: - m_context->uniform1f(uniformLocation, numberParameter->valueAt(0)); - break; - case 2: - m_context->uniform2f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1)); - break; - case 3: - m_context->uniform3f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1), numberParameter->valueAt(2)); - break; - case 4: - m_context->uniform4f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1), numberParameter->valueAt(2), numberParameter->valueAt(3)); - break; - default: - ASSERT_NOT_REACHED(); - } -} - -void FECustomFilter::bindProgramTransformParameter(int uniformLocation, CustomFilterTransformParameter* transformParameter) -{ - TransformationMatrix matrix; - if (m_contextSize.width() && m_contextSize.height()) { - // The viewport is a box with the size of 1 unit, so we are scalling up here to make sure that translations happen using real pixel - // units. At the end we scale back down in order to map it back to the original box. Note that transforms come in reverse order, because it is - // supposed to multiply to the left of the coordinates of the vertices. - // Note that the origin (0, 0) of the viewport is in the middle of the context, so there's no need to change the origin of the transform - // in order to rotate around the middle of mesh. - matrix.scale3d(1.0 / m_contextSize.width(), 1.0 / m_contextSize.height(), 1); - transformParameter->applyTransform(matrix, m_contextSize); - matrix.scale3d(m_contextSize.width(), m_contextSize.height(), 1); - } - float glMatrix[16]; - matrix.toColumnMajorFloatArray(glMatrix); - m_context->uniformMatrix4fv(uniformLocation, 1, false, &glMatrix[0]); -} - -void FECustomFilter::bindProgramParameters() -{ - // FIXME: Find a way to reset uniforms that are not specified in CSS. This is needed to avoid using values - // set by other previous rendered filters. - // https://bugs.webkit.org/show_bug.cgi?id=76440 - - size_t parametersSize = m_parameters.size(); - for (size_t i = 0; i < parametersSize; ++i) { - CustomFilterParameter* parameter = m_parameters.at(i).get(); - int uniformLocation = m_compiledProgram->uniformLocationByName(parameter->name()); - if (uniformLocation == -1) - continue; - switch (parameter->parameterType()) { - case CustomFilterParameter::ARRAY: - bindProgramArrayParameters(uniformLocation, static_cast<CustomFilterArrayParameter*>(parameter)); - break; - case CustomFilterParameter::NUMBER: - bindProgramNumberParameters(uniformLocation, static_cast<CustomFilterNumberParameter*>(parameter)); - break; - case CustomFilterParameter::TRANSFORM: - bindProgramTransformParameter(uniformLocation, static_cast<CustomFilterTransformParameter*>(parameter)); - break; - } - } -} - -void FECustomFilter::bindProgramAndBuffers(Platform3DObject inputTexture) -{ - ASSERT(m_compiledProgram->isInitialized()); - - m_context->useProgram(m_compiledProgram->program()); - - if (programNeedsInputTexture()) { - // We should be binding the DOM element texture sampler only if the author is using the CSS mix function. - ASSERT(m_validatedProgram->programInfo().programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE); - ASSERT(m_compiledProgram->samplerLocation() != -1); - - m_context->activeTexture(GraphicsContext3D::TEXTURE0); - m_context->uniform1i(m_compiledProgram->samplerLocation(), 0); - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, inputTexture); - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); - } - - if (m_compiledProgram->projectionMatrixLocation() != -1) { - TransformationMatrix projectionMatrix; - orthogonalProjectionMatrix(projectionMatrix, -0.5, 0.5, -0.5, 0.5); - float glProjectionMatrix[16]; - projectionMatrix.toColumnMajorFloatArray(glProjectionMatrix); - m_context->uniformMatrix4fv(m_compiledProgram->projectionMatrixLocation(), 1, false, &glProjectionMatrix[0]); - } - - ASSERT(m_meshColumns); - ASSERT(m_meshRows); - - if (m_compiledProgram->meshSizeLocation() != -1) - m_context->uniform2f(m_compiledProgram->meshSizeLocation(), m_meshColumns, m_meshRows); - - if (m_compiledProgram->tileSizeLocation() != -1) - m_context->uniform2f(m_compiledProgram->tileSizeLocation(), 1.0 / m_meshColumns, 1.0 / m_meshRows); - - if (m_compiledProgram->meshBoxLocation() != -1) { - // FIXME: This will change when filter margins will be implemented, - // see https://bugs.webkit.org/show_bug.cgi?id=71400 - m_context->uniform4f(m_compiledProgram->meshBoxLocation(), -0.5, -0.5, 1.0, 1.0); - } - - if (m_compiledProgram->samplerSizeLocation() != -1) - m_context->uniform2f(m_compiledProgram->samplerSizeLocation(), m_contextSize.width(), m_contextSize.height()); - - m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_mesh->verticesBufferObject()); - m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_mesh->elementsBufferObject()); - - bindVertexAttribute(m_compiledProgram->positionAttribLocation(), PositionAttribSize, PositionAttribOffset); - bindVertexAttribute(m_compiledProgram->texAttribLocation(), TexAttribSize, TexAttribOffset); - // FIXME: Get rid of the internal tex coord attribute "css_a_texCoord". - // https://bugs.webkit.org/show_bug.cgi?id=94358 - bindVertexAttribute(m_compiledProgram->internalTexCoordAttribLocation(), TexAttribSize, TexAttribOffset); - bindVertexAttribute(m_compiledProgram->meshAttribLocation(), MeshAttribSize, MeshAttribOffset); - if (m_meshType == CustomFilterOperation::DETACHED) - bindVertexAttribute(m_compiledProgram->triangleAttribLocation(), TriangleAttribSize, TriangleAttribOffset); - - bindProgramParameters(); -} - -void FECustomFilter::unbindVertexAttributes() -{ - unbindVertexAttribute(m_compiledProgram->positionAttribLocation()); - unbindVertexAttribute(m_compiledProgram->texAttribLocation()); - unbindVertexAttribute(m_compiledProgram->internalTexCoordAttribLocation()); - unbindVertexAttribute(m_compiledProgram->meshAttribLocation()); - if (m_meshType == CustomFilterOperation::DETACHED) - unbindVertexAttribute(m_compiledProgram->triangleAttribLocation()); -} - void FECustomFilter::dump() { } diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.h b/Source/WebCore/platform/graphics/filters/FECustomFilter.h index 09da5f1c7..44e68f1ca 100644 --- a/Source/WebCore/platform/graphics/filters/FECustomFilter.h +++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.h @@ -32,6 +32,7 @@ #if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) +#include "CustomFilterConstants.h" #include "CustomFilterOperation.h" #include "Filter.h" #include "FilterEffect.h" @@ -44,23 +45,15 @@ class Uint8ClampedArray; namespace WebCore { -class CachedShader; -class CustomFilterArrayParameter; -class CustomFilterCompiledProgram; -class CustomFilterGlobalContext; -class CustomFilterMesh; -class CustomFilterNumberParameter; -class CustomFilterTransformParameter; +class CustomFilterRenderer; class CustomFilterValidatedProgram; -class DrawingBuffer; class GraphicsContext3D; class IntSize; class FECustomFilter : public FilterEffect { public: - static PassRefPtr<FECustomFilter> create(Filter*, CustomFilterGlobalContext*, PassRefPtr<CustomFilterValidatedProgram>, const CustomFilterParameterList&, - unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType, - CustomFilterOperation::MeshType); + static PassRefPtr<FECustomFilter> create(Filter*, PassRefPtr<GraphicsContext3D>, PassRefPtr<CustomFilterValidatedProgram>, const CustomFilterParameterList&, + unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType, CustomFilterMeshType); virtual void platformApplySoftware(); virtual void dump(); @@ -68,23 +61,17 @@ public: virtual TextStream& externalRepresentation(TextStream&, int indention) const; private: - FECustomFilter(Filter*, CustomFilterGlobalContext*, PassRefPtr<CustomFilterValidatedProgram>, const CustomFilterParameterList&, - unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType, - CustomFilterOperation::MeshType); + FECustomFilter(Filter*, PassRefPtr<GraphicsContext3D>, PassRefPtr<CustomFilterValidatedProgram>, const CustomFilterParameterList&, + unsigned meshRows, unsigned meshColumns, CustomFilterMeshBoxType, CustomFilterMeshType); ~FECustomFilter(); - + bool applyShader(); void clearShaderResult(); bool initializeContext(); - - enum CustomFilterDrawType { - NEEDS_INPUT_TEXTURE, - NO_INPUT_TEXTURE - }; - bool prepareForDrawing(CustomFilterDrawType = NEEDS_INPUT_TEXTURE); + + bool prepareForDrawing(); void drawFilterMesh(Platform3DObject inputTexture); - bool programNeedsInputTexture() const; bool ensureInputTexture(); void uploadInputTexture(Uint8ClampedArray* srcPixelArray); bool resizeContextIfNeeded(const IntSize&); @@ -99,22 +86,8 @@ private: bool ensureFrameBuffer(); void deleteRenderBuffers(); - void bindVertexAttribute(int attributeLocation, unsigned size, unsigned offset); - void unbindVertexAttribute(int attributeLocation); - void bindProgramArrayParameters(int uniformLocation, CustomFilterArrayParameter*); - void bindProgramNumberParameters(int uniformLocation, CustomFilterNumberParameter*); - void bindProgramTransformParameter(int uniformLocation, CustomFilterTransformParameter*); - void bindProgramParameters(); - void bindProgramAndBuffers(Platform3DObject inputTexture); - void unbindVertexAttributes(); - - // No need to keep a reference here. It is owned by the RenderView. - CustomFilterGlobalContext* m_globalContext; - RefPtr<GraphicsContext3D> m_context; - RefPtr<CustomFilterValidatedProgram> m_validatedProgram; - RefPtr<CustomFilterCompiledProgram> m_compiledProgram; - RefPtr<CustomFilterMesh> m_mesh; + RefPtr<CustomFilterRenderer> m_customFilterRenderer; IntSize m_contextSize; Platform3DObject m_inputTexture; @@ -126,12 +99,6 @@ private: Platform3DObject m_multisampleFrameBuffer; Platform3DObject m_multisampleRenderBuffer; Platform3DObject m_multisampleDepthBuffer; - - CustomFilterParameterList m_parameters; - - unsigned m_meshRows; - unsigned m_meshColumns; - CustomFilterOperation::MeshType m_meshType; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h index 7b3bdce29..daf3ef17a 100644 --- a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h +++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h @@ -75,6 +75,7 @@ private: inline void platformApplyGeneric(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize); #if USE(SKIA) virtual bool platformApplySkia(); + virtual SkImageFilter* createImageFilter(SkiaImageFilterBuilder*); #endif float m_stdX; diff --git a/Source/WebCore/platform/graphics/filters/FELighting.h b/Source/WebCore/platform/graphics/filters/FELighting.h index 4487835e8..288985d42 100644 --- a/Source/WebCore/platform/graphics/filters/FELighting.h +++ b/Source/WebCore/platform/graphics/filters/FELighting.h @@ -47,6 +47,7 @@ class FELighting : public FilterEffect { public: virtual void platformApplySoftware(); #if USE(SKIA) + virtual SkImageFilter* createImageFilter(SkiaImageFilterBuilder*); virtual bool platformApplySkia(); #endif diff --git a/Source/WebCore/platform/graphics/filters/FEMorphology.h b/Source/WebCore/platform/graphics/filters/FEMorphology.h index 19da635a2..b38e673c3 100644 --- a/Source/WebCore/platform/graphics/filters/FEMorphology.h +++ b/Source/WebCore/platform/graphics/filters/FEMorphology.h @@ -49,6 +49,8 @@ public: virtual void platformApplySoftware(); #if USE(SKIA) virtual bool platformApplySkia(); + virtual SkImageFilter* createImageFilter(SkiaImageFilterBuilder*); + #endif virtual void dump(); diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.h b/Source/WebCore/platform/graphics/filters/FilterEffect.h index 1620abf1e..069ede3ee 100644 --- a/Source/WebCore/platform/graphics/filters/FilterEffect.h +++ b/Source/WebCore/platform/graphics/filters/FilterEffect.h @@ -35,6 +35,10 @@ static const float kMaxFilterSize = 5000.0f; +#if USE(SKIA) +class SkImageFilter; +#endif + namespace WebCore { class Filter; @@ -42,6 +46,10 @@ class FilterEffect; class ImageBuffer; class TextStream; +#if USE(SKIA) +class SkiaImageFilterBuilder; +#endif + typedef Vector<RefPtr<FilterEffect> > FilterEffectVector; enum FilterEffectType { @@ -95,6 +103,7 @@ public: virtual void platformApplySoftware() = 0; #if USE(SKIA) virtual bool platformApplySkia() { return false; } + virtual SkImageFilter* createImageFilter(SkiaImageFilterBuilder*) { return 0; } #endif virtual void dump() = 0; diff --git a/Source/WebCore/platform/graphics/filters/FilterOperation.h b/Source/WebCore/platform/graphics/filters/FilterOperation.h index 6d2503ac3..906706bea 100644 --- a/Source/WebCore/platform/graphics/filters/FilterOperation.h +++ b/Source/WebCore/platform/graphics/filters/FilterOperation.h @@ -29,6 +29,7 @@ #if ENABLE(CSS_FILTERS) #include "Color.h" +#include "FilterEffect.h" #include "LayoutTypes.h" #include "Length.h" #include <wtf/OwnPtr.h> @@ -69,6 +70,7 @@ public: DROP_SHADOW, #if ENABLE(CSS_SHADERS) CUSTOM, + VALIDATED_CUSTOM, #endif PASSTHROUGH, NONE @@ -161,14 +163,21 @@ public: return adoptRef(new ReferenceFilterOperation(url, fragment, type)); } + class Data { + public: + virtual ~Data() { } + }; + virtual bool affectsOpacity() const { return true; } virtual bool movesPixels() const { return true; } const String& url() const { return m_url; } const String& fragment() const { return m_fragment; } - void* data() const { return m_data; } - void setData(void* data) { m_data = data; } + Data* data() const { return m_data.get(); } + void setData(PassOwnPtr<Data> data) { m_data = data; } + FilterEffect* filterEffect() const { return m_filterEffect.get(); } + void setFilterEffect(PassRefPtr<FilterEffect> filterEffect) { m_filterEffect = filterEffect; } private: @@ -184,13 +193,13 @@ private: : FilterOperation(type) , m_url(url) , m_fragment(fragment) - , m_data(0) { } String m_url; String m_fragment; - void* m_data; + OwnPtr<Data> m_data; + RefPtr<FilterEffect> m_filterEffect; }; // GRAYSCALE, SEPIA, SATURATE and HUE_ROTATE are variations on a basic color matrix effect. diff --git a/Source/WebCore/platform/graphics/filters/FilterOperations.cpp b/Source/WebCore/platform/graphics/filters/FilterOperations.cpp index c4b876593..fcb74fc32 100644 --- a/Source/WebCore/platform/graphics/filters/FilterOperations.cpp +++ b/Source/WebCore/platform/graphics/filters/FilterOperations.cpp @@ -91,7 +91,8 @@ bool FilterOperations::operationsMatch(const FilterOperations& other) const bool FilterOperations::hasCustomFilter() const { for (size_t i = 0; i < m_operations.size(); ++i) { - if (m_operations.at(i)->getOperationType() == FilterOperation::CUSTOM) + FilterOperation::OperationType type = m_operations.at(i)->getOperationType(); + if (type == FilterOperation::CUSTOM || type == FilterOperation::VALIDATED_CUSTOM) return true; } return false; @@ -146,8 +147,10 @@ void FilterOperations::getOutsets(int& top, int& right, int& bottom, int& left) break; } #if ENABLE(CSS_SHADERS) - case FilterOperation::CUSTOM: { - // Need to include the filter margins here. + case FilterOperation::CUSTOM: + case FilterOperation::VALIDATED_CUSTOM: { + // FIXME: Need to include the filter margins here. + // https://bugs.webkit.org/show_bug.cgi?id=71400 break; } #endif diff --git a/Source/WebCore/platform/graphics/filters/ValidatedCustomFilterOperation.cpp b/Source/WebCore/platform/graphics/filters/ValidatedCustomFilterOperation.cpp new file mode 100644 index 000000000..35def2f38 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/ValidatedCustomFilterOperation.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(CSS_SHADERS) +#include "ValidatedCustomFilterOperation.h" + +#include "CustomFilterParameter.h" +#include "CustomFilterValidatedProgram.h" +#include "FractionalLayoutSize.h" +#include <wtf/UnusedParam.h> + +namespace WebCore { + +ValidatedCustomFilterOperation::ValidatedCustomFilterOperation(PassRefPtr<CustomFilterValidatedProgram> validatedProgram, + const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType) + : FilterOperation(VALIDATED_CUSTOM) + , m_validatedProgram(validatedProgram) + , m_parameters(sortedParameters) + , m_meshRows(meshRows) + , m_meshColumns(meshColumns) + , m_meshType(meshType) +{ +} + +ValidatedCustomFilterOperation::~ValidatedCustomFilterOperation() +{ +} + +PassRefPtr<FilterOperation> ValidatedCustomFilterOperation::blend(const FilterOperation*, double progress, const LayoutSize& size, bool blendToPassthrough) +{ + UNUSED_PARAM(progress); + UNUSED_PARAM(size); + UNUSED_PARAM(blendToPassthrough); + + ASSERT_NOT_REACHED(); + return this; +} + +} // namespace WebCore + +#endif // ENABLE(CSS_SHADERS) diff --git a/Source/WebCore/platform/graphics/filters/ValidatedCustomFilterOperation.h b/Source/WebCore/platform/graphics/filters/ValidatedCustomFilterOperation.h new file mode 100644 index 000000000..cf88d5144 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/ValidatedCustomFilterOperation.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ValidatedCustomFilterOperation_h +#define ValidatedCustomFilterOperation_h + +#if ENABLE(CSS_SHADERS) +#include "CustomFilterConstants.h" +#include "CustomFilterParameterList.h" +#include "FilterOperation.h" +#include "LayoutTypes.h" + +namespace WebCore { + +class CustomFilterValidatedProgram; + +class ValidatedCustomFilterOperation : public FilterOperation { +public: + static PassRefPtr<ValidatedCustomFilterOperation> create(PassRefPtr<CustomFilterValidatedProgram> validatedProgram, + const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType) + { + return adoptRef(new ValidatedCustomFilterOperation(validatedProgram, sortedParameters, meshRows, meshColumns, meshType)); + } + + virtual ~ValidatedCustomFilterOperation(); + + virtual bool affectsOpacity() const { return true; } + virtual bool movesPixels() const { return true; } + virtual bool blendingNeedsRendererSize() const { return true; } + + virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, const LayoutSize&, bool blendToPassthrough = false); + + CustomFilterValidatedProgram* validatedProgram() const { return m_validatedProgram.get(); } + const CustomFilterParameterList& parameters() const { return m_parameters; } + + unsigned meshRows() const { return m_meshRows; } + unsigned meshColumns() const { return m_meshColumns; } + + CustomFilterMeshType meshType() const { return m_meshType; } + +private: + virtual bool operator==(const FilterOperation& o) const + { + if (!isSameType(o)) + return false; + + const ValidatedCustomFilterOperation* other = static_cast<const ValidatedCustomFilterOperation*>(&o); + return m_validatedProgram.get() == other->m_validatedProgram.get() + && m_meshRows == other->m_meshRows + && m_meshColumns == other->m_meshColumns + && m_meshType == other->m_meshType + && m_parameters == other->m_parameters; + } + + ValidatedCustomFilterOperation(PassRefPtr<CustomFilterValidatedProgram>, const CustomFilterParameterList&, unsigned meshRows, unsigned meshColumns, CustomFilterMeshType); + + RefPtr<CustomFilterValidatedProgram> m_validatedProgram; + + CustomFilterParameterList m_parameters; + unsigned m_meshRows; + unsigned m_meshColumns; + CustomFilterMeshType m_meshType; + + // FIXME: Add CustomFilterMeshBoxType after 100782 is landed. + // https://bugs.webkit.org/show_bug.cgi?id=100890 +}; + +} // namespace WebCore + +#endif // ENABLE(CSS_SHADERS) + +#endif // ValidatedCustomFilterOperation_h diff --git a/Source/WebCore/platform/graphics/filters/skia/FEBlendSkia.cpp b/Source/WebCore/platform/graphics/filters/skia/FEBlendSkia.cpp index fdca432f4..8089f3b50 100644 --- a/Source/WebCore/platform/graphics/filters/skia/FEBlendSkia.cpp +++ b/Source/WebCore/platform/graphics/filters/skia/FEBlendSkia.cpp @@ -31,6 +31,7 @@ #include "NativeImageSkia.h" #include "SkBitmapSource.h" #include "SkBlendImageFilter.h" +#include "SkiaImageFilterBuilder.h" namespace WebCore { @@ -84,6 +85,14 @@ bool FEBlend::platformApplySkia() return true; } +SkImageFilter* FEBlend::createImageFilter(SkiaImageFilterBuilder* builder) +{ + SkImageFilter* foreground = builder->build(inputEffect(0)); + SkImageFilter* background = builder->build(inputEffect(1)); + SkBlendImageFilter::Mode mode = toSkiaMode(m_mode); + return new SkBlendImageFilter(mode, background, foreground); +} + } // namespace WebCore #endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/skia/FEColorMatrixSkia.cpp b/Source/WebCore/platform/graphics/filters/skia/FEColorMatrixSkia.cpp index 0fd07776e..affbaead0 100644 --- a/Source/WebCore/platform/graphics/filters/skia/FEColorMatrixSkia.cpp +++ b/Source/WebCore/platform/graphics/filters/skia/FEColorMatrixSkia.cpp @@ -28,7 +28,9 @@ #include "FEColorMatrix.h" #include "NativeImageSkia.h" +#include "SkColorFilterImageFilter.h" #include "SkColorMatrixFilter.h" +#include "SkiaImageFilterBuilder.h" namespace WebCore { @@ -80,24 +82,15 @@ static void luminanceToAlphaMatrix(SkScalar matrix[20]) matrix[17] = 0.0721f; } -bool FEColorMatrix::platformApplySkia() +static SkColorFilter* createColorFilter(ColorMatrixType type, const float* values) { - ImageBuffer* resultImage = createImageBufferResult(); - if (!resultImage) - return false; - - FilterEffect* in = inputEffect(0); - - IntRect imageRect(IntPoint(), absolutePaintRect().size()); - SkScalar matrix[20]; - - switch (m_type) { + switch (type) { case FECOLORMATRIX_TYPE_UNKNOWN: break; case FECOLORMATRIX_TYPE_MATRIX: for (int i = 0; i < 20; ++i) - matrix[i] = m_values[i]; + matrix[i] = values[i]; matrix[4] *= SkScalar(255); matrix[9] *= SkScalar(255); @@ -105,15 +98,29 @@ bool FEColorMatrix::platformApplySkia() matrix[19] *= SkScalar(255); break; case FECOLORMATRIX_TYPE_SATURATE: - saturateMatrix(m_values[0], matrix); + saturateMatrix(values[0], matrix); break; case FECOLORMATRIX_TYPE_HUEROTATE: - hueRotateMatrix(m_values[0], matrix); + hueRotateMatrix(values[0], matrix); break; case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: luminanceToAlphaMatrix(matrix); break; } + return new SkColorMatrixFilter(matrix); +} + +bool FEColorMatrix::platformApplySkia() +{ + ImageBuffer* resultImage = createImageBufferResult(); + if (!resultImage) + return false; + + FilterEffect* in = inputEffect(0); + + IntRect imageRect(IntPoint(), absolutePaintRect().size()); + + SkAutoTUnref<SkColorFilter> filter(createColorFilter(m_type, m_values.data())); RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore); NativeImageSkia* nativeImage = image->nativeImageForCurrentFrame(); @@ -122,12 +129,19 @@ bool FEColorMatrix::platformApplySkia() SkCanvas* canvas = resultImage->context()->platformContext()->canvas(); SkPaint paint; - paint.setColorFilter(new SkColorMatrixFilter(matrix))->unref(); + paint.setColorFilter(filter); paint.setXfermodeMode(SkXfermode::kSrc_Mode); canvas->drawBitmap(nativeImage->bitmap(), 0, 0, &paint); return true; } +SkImageFilter* FEColorMatrix::createImageFilter(SkiaImageFilterBuilder* builder) +{ + SkAutoTUnref<SkImageFilter> input(builder->build(inputEffect(0))); + SkAutoTUnref<SkColorFilter> filter(createColorFilter(m_type, m_values.data())); + return SkColorFilterImageFilter::Create(filter, input); +} + } // namespace WebCore #endif // ENABLE(FILTERS) && USE(SKIA) diff --git a/Source/WebCore/platform/graphics/filters/skia/FEComponentTransferSkia.cpp b/Source/WebCore/platform/graphics/filters/skia/FEComponentTransferSkia.cpp index 577a5b065..86d5d7e66 100644 --- a/Source/WebCore/platform/graphics/filters/skia/FEComponentTransferSkia.cpp +++ b/Source/WebCore/platform/graphics/filters/skia/FEComponentTransferSkia.cpp @@ -29,7 +29,9 @@ #include "FEComponentTransfer.h" #include "NativeImageSkia.h" +#include "SkColorFilterImageFilter.h" #include "SkTableColorFilter.h" +#include "SkiaImageFilterBuilder.h" namespace WebCore { @@ -55,6 +57,18 @@ bool FEComponentTransfer::platformApplySkia() return true; } +SkImageFilter* FEComponentTransfer::createImageFilter(SkiaImageFilterBuilder* builder) +{ + SkImageFilter* input = builder->build(inputEffect(0)); + + unsigned char rValues[256], gValues[256], bValues[256], aValues[256]; + getValues(rValues, gValues, bValues, aValues); + + SkAutoTUnref<SkColorFilter> colorFilter(SkTableColorFilter::CreateARGB(aValues, rValues, gValues, bValues)); + + return SkColorFilterImageFilter::Create(colorFilter, input); +} + } // namespace WebCore #endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp b/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp index b694c9b1c..f5f46daed 100644 --- a/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp +++ b/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp @@ -29,6 +29,7 @@ #include "BitmapImageSingleFrameSkia.h" #include "SkBlurImageFilter.h" +#include "SkiaImageFilterBuilder.h" namespace WebCore { @@ -61,5 +62,11 @@ bool FEGaussianBlur::platformApplySkia() return true; } +SkImageFilter* FEGaussianBlur::createImageFilter(SkiaImageFilterBuilder* builder) +{ + SkAutoTUnref<SkImageFilter> input(builder->build(inputEffect(0))); + return new SkBlurImageFilter(SkFloatToScalar(m_stdX), SkFloatToScalar(m_stdY), input); +} + }; #endif diff --git a/Source/WebCore/platform/graphics/filters/skia/FELightingSkia.cpp b/Source/WebCore/platform/graphics/filters/skia/FELightingSkia.cpp index 1a6a2d70e..167234d3b 100644 --- a/Source/WebCore/platform/graphics/filters/skia/FELightingSkia.cpp +++ b/Source/WebCore/platform/graphics/filters/skia/FELightingSkia.cpp @@ -31,32 +31,14 @@ #include "NativeImageSkia.h" #include "PointLightSource.h" #include "SkLightingImageFilter.h" +#include "SkiaImageFilterBuilder.h" #include "SpotLightSource.h" namespace WebCore { -bool FELighting::platformApplySkia() +SkImageFilter* FELighting::createImageFilter(SkiaImageFilterBuilder* builder) { - // For now, only use the skia implementation for accelerated rendering. - if (filter()->renderingMode() != Accelerated) - return false; - - ImageBuffer* resultImage = createImageBufferResult(); - if (!resultImage) - return false; - - FilterEffect* in = inputEffect(0); - - IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); - - setIsAlphaImage(in->isAlphaImage()); - - RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore); - NativeImageSkia* nativeImage = image->nativeImageForCurrentFrame(); - - GraphicsContext* dstContext = resultImage->context(); - - SkPaint paint; + SkImageFilter* input = builder ? builder->build(inputEffect(0)) : 0; switch (m_lightSource->type()) { case LS_DISTANT: { DistantLightSource* distantLightSource = static_cast<DistantLightSource*>(m_lightSource.get()); @@ -66,20 +48,18 @@ bool FELighting::platformApplySkia() sinf(azimuthRad) * cosf(elevationRad), sinf(elevationRad)); if (m_specularConstant > 0) - paint.setImageFilter(SkLightingImageFilter::CreateDistantLitSpecular(direction, m_lightingColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent))->unref(); + return SkLightingImageFilter::CreateDistantLitSpecular(direction, m_lightingColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent, input); else - paint.setImageFilter(SkLightingImageFilter::CreateDistantLitDiffuse(direction, m_lightingColor.rgb(), m_surfaceScale, m_diffuseConstant))->unref(); - break; + return SkLightingImageFilter::CreateDistantLitDiffuse(direction, m_lightingColor.rgb(), m_surfaceScale, m_diffuseConstant, input); } case LS_POINT: { PointLightSource* pointLightSource = static_cast<PointLightSource*>(m_lightSource.get()); FloatPoint3D position = pointLightSource->position(); SkPoint3 skPosition(position.x(), position.y(), position.z()); if (m_specularConstant > 0) - paint.setImageFilter(SkLightingImageFilter::CreatePointLitSpecular(skPosition, m_lightingColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent))->unref(); + return SkLightingImageFilter::CreatePointLitSpecular(skPosition, m_lightingColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent, input); else - paint.setImageFilter(SkLightingImageFilter::CreatePointLitDiffuse(skPosition, m_lightingColor.rgb(), m_surfaceScale, m_diffuseConstant))->unref(); - break; + return SkLightingImageFilter::CreatePointLitDiffuse(skPosition, m_lightingColor.rgb(), m_surfaceScale, m_diffuseConstant, input); } case LS_SPOT: { SpotLightSource* spotLightSource = static_cast<SpotLightSource*>(m_lightSource.get()); @@ -90,15 +70,39 @@ bool FELighting::platformApplySkia() if (!limitingConeAngle || limitingConeAngle > 90 || limitingConeAngle < -90) limitingConeAngle = 90; if (m_specularConstant > 0) - paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(location, target, specularExponent, limitingConeAngle, m_lightingColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent))->unref(); + return SkLightingImageFilter::CreateSpotLitSpecular(location, target, specularExponent, limitingConeAngle, m_lightingColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent, input); else - paint.setImageFilter(SkLightingImageFilter::CreateSpotLitDiffuse(location, target, specularExponent, limitingConeAngle, m_lightingColor.rgb(), m_surfaceScale, m_diffuseConstant))->unref(); - break; + return SkLightingImageFilter::CreateSpotLitDiffuse(location, target, specularExponent, limitingConeAngle, m_lightingColor.rgb(), m_surfaceScale, m_diffuseConstant, input); } default: ASSERT_NOT_REACHED(); - return false; + return 0; } +} + +bool FELighting::platformApplySkia() +{ + // For now, only use the skia implementation for accelerated rendering. + if (filter()->renderingMode() != Accelerated) + return false; + + ImageBuffer* resultImage = createImageBufferResult(); + if (!resultImage) + return false; + + FilterEffect* in = inputEffect(0); + + IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); + + setIsAlphaImage(in->isAlphaImage()); + + RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore); + NativeImageSkia* nativeImage = image->nativeImageForCurrentFrame(); + + GraphicsContext* dstContext = resultImage->context(); + + SkPaint paint; + paint.setImageFilter(createImageFilter(0))->unref(); dstContext->platformContext()->canvas()->drawBitmap(nativeImage->bitmap(), drawingRegion.location().x(), drawingRegion.location().y(), &paint); return true; } diff --git a/Source/WebCore/platform/graphics/filters/skia/FEMorphologySkia.cpp b/Source/WebCore/platform/graphics/filters/skia/FEMorphologySkia.cpp index e7290bec7..b2e9f4fcf 100644 --- a/Source/WebCore/platform/graphics/filters/skia/FEMorphologySkia.cpp +++ b/Source/WebCore/platform/graphics/filters/skia/FEMorphologySkia.cpp @@ -28,6 +28,7 @@ #include "FEMorphology.h" #include "SkMorphologyImageFilter.h" +#include "SkiaImageFilterBuilder.h" namespace WebCore { @@ -62,5 +63,15 @@ bool FEMorphology::platformApplySkia() return true; } +SkImageFilter* FEMorphology::createImageFilter(SkiaImageFilterBuilder* builder) +{ + SkAutoTUnref<SkImageFilter> input(builder->build(inputEffect(0))); + SkScalar radiusX = SkFloatToScalar(m_radiusX); + SkScalar radiusY = SkFloatToScalar(m_radiusY); + if (m_type == FEMORPHOLOGY_OPERATOR_DILATE) + return new SkDilateImageFilter(radiusX, radiusY, input); + return new SkErodeImageFilter(radiusX, radiusY, input); +} + }; #endif diff --git a/Source/WebCore/platform/graphics/filters/skia/SkiaImageFilterBuilder.cpp b/Source/WebCore/platform/graphics/filters/skia/SkiaImageFilterBuilder.cpp new file mode 100644 index 000000000..da891fb85 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/skia/SkiaImageFilterBuilder.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 "SkiaImageFilterBuilder.h" + +#include "FilterEffect.h" +#include "FilterOperations.h" +#include "SkBlurImageFilter.h" +#include "SkColorFilterImageFilter.h" +#include "SkColorMatrixFilter.h" +#include "SkMatrix.h" + +namespace { + +void getBrightnessMatrix(float amount, SkScalar matrix[20]) +{ + memset(matrix, 0, 20 * sizeof(SkScalar)); + matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1; + matrix[4] = matrix[9] = matrix[14] = amount * 255; +} + +void getContrastMatrix(float amount, SkScalar matrix[20]) +{ + memset(matrix, 0, 20 * sizeof(SkScalar)); + matrix[0] = matrix[6] = matrix[12] = amount; + matrix[4] = matrix[9] = matrix[14] = (-0.5f * amount + 0.5f) * 255; + matrix[18] = 1; +} + +void getSaturateMatrix(float amount, SkScalar matrix[20]) +{ + // Note, these values are computed to ensure matrixNeedsClamping is false + // for amount in [0..1] + matrix[0] = 0.213f + 0.787f * amount; + matrix[1] = 0.715f - 0.715f * amount; + matrix[2] = 1.f - (matrix[0] + matrix[1]); + matrix[3] = matrix[4] = 0; + matrix[5] = 0.213f - 0.213f * amount; + matrix[6] = 0.715f + 0.285f * amount; + matrix[7] = 1.f - (matrix[5] + matrix[6]); + matrix[8] = matrix[9] = 0; + matrix[10] = 0.213f - 0.213f * amount; + matrix[11] = 0.715f - 0.715f * amount; + matrix[12] = 1.f - (matrix[10] + matrix[11]); + matrix[13] = matrix[14] = 0; + matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; + matrix[18] = 1; +} + +void getHueRotateMatrix(float hue, SkScalar matrix[20]) +{ + float cosHue = cosf(hue * piFloat / 180); + float sinHue = sinf(hue * piFloat / 180); + matrix[0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f; + matrix[1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f; + matrix[2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f; + matrix[3] = matrix[4] = 0; + matrix[5] = 0.213f - cosHue * 0.213f + sinHue * 0.143f; + matrix[6] = 0.715f + cosHue * 0.285f + sinHue * 0.140f; + matrix[7] = 0.072f - cosHue * 0.072f - sinHue * 0.283f; + matrix[8] = matrix[9] = 0; + matrix[10] = 0.213f - cosHue * 0.213f - sinHue * 0.787f; + matrix[11] = 0.715f - cosHue * 0.715f + sinHue * 0.715f; + matrix[12] = 0.072f + cosHue * 0.928f + sinHue * 0.072f; + matrix[13] = matrix[14] = 0; + matrix[15] = matrix[16] = matrix[17] = 0; + matrix[18] = 1; + matrix[19] = 0; +} + +void getInvertMatrix(float amount, SkScalar matrix[20]) +{ + memset(matrix, 0, 20 * sizeof(SkScalar)); + matrix[0] = matrix[6] = matrix[12] = 1 - 2 * amount; + matrix[4] = matrix[9] = matrix[14] = amount * 255; + matrix[18] = 1; +} + +void getOpacityMatrix(float amount, SkScalar matrix[20]) +{ + memset(matrix, 0, 20 * sizeof(SkScalar)); + matrix[0] = matrix[6] = matrix[12] = 1; + matrix[18] = amount; +} + +void getGrayscaleMatrix(float amount, SkScalar matrix[20]) +{ + // Note, these values are computed to ensure matrixNeedsClamping is false + // for amount in [0..1] + matrix[0] = 0.2126f + 0.7874f * amount; + matrix[1] = 0.7152f - 0.7152f * amount; + matrix[2] = 1.f - (matrix[0] + matrix[1]); + matrix[3] = matrix[4] = 0; + + matrix[5] = 0.2126f - 0.2126f * amount; + matrix[6] = 0.7152f + 0.2848f * amount; + matrix[7] = 1.f - (matrix[5] + matrix[6]); + matrix[8] = matrix[9] = 0; + + matrix[10] = 0.2126f - 0.2126f * amount; + matrix[11] = 0.7152f - 0.7152f * amount; + matrix[12] = 1.f - (matrix[10] + matrix[11]); + matrix[13] = matrix[14] = 0; + + matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; + matrix[18] = 1; +} + +void getSepiaMatrix(float amount, SkScalar matrix[20]) +{ + matrix[0] = 0.393f + 0.607f * amount; + matrix[1] = 0.769f - 0.769f * amount; + matrix[2] = 0.189f - 0.189f * amount; + matrix[3] = matrix[4] = 0; + + matrix[5] = 0.349f - 0.349f * amount; + matrix[6] = 0.686f + 0.314f * amount; + matrix[7] = 0.168f - 0.168f * amount; + matrix[8] = matrix[9] = 0; + + matrix[10] = 0.272f - 0.272f * amount; + matrix[11] = 0.534f - 0.534f * amount; + matrix[12] = 0.131f + 0.869f * amount; + matrix[13] = matrix[14] = 0; + + matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; + matrix[18] = 1; +} + +SkImageFilter* createMatrixImageFilter(SkScalar matrix[20], SkImageFilter* input) +{ + SkAutoTUnref<SkColorFilter> colorFilter(new SkColorMatrixFilter(matrix)); + return SkColorFilterImageFilter::Create(colorFilter, input); +} + +}; + +namespace WebCore { + +SkiaImageFilterBuilder::SkiaImageFilterBuilder() +{ +} + +SkImageFilter* SkiaImageFilterBuilder::build(FilterEffect* effect) +{ + if (!effect) + return 0; + + FilterBuilderHashMap::iterator it = m_map.find(effect); + if (it != m_map.end()) + return it->value; + + SkImageFilter* filter = effect->createImageFilter(this); + m_map.set(effect, filter); + return filter; +} + +SkImageFilter* SkiaImageFilterBuilder::build(const FilterOperations& operations) +{ + SkImageFilter* filter = 0; + SkScalar matrix[20]; + for (size_t i = 0; i < operations.size(); ++i) { + const FilterOperation& op = *operations.at(i); + switch (op.getOperationType()) { + case FilterOperation::REFERENCE: { + FilterEffect* filterEffect = static_cast<const ReferenceFilterOperation*>(&op)->filterEffect(); + // FIXME: hook up parent filter to image source + filter = SkiaImageFilterBuilder::build(filterEffect); + break; + } + case FilterOperation::GRAYSCALE: { + float amount = static_cast<const BasicColorMatrixFilterOperation*>(&op)->amount(); + getGrayscaleMatrix(amount, matrix); + filter = createMatrixImageFilter(matrix, filter); + break; + } + case FilterOperation::SEPIA: { + float amount = static_cast<const BasicColorMatrixFilterOperation*>(&op)->amount(); + getSepiaMatrix(amount, matrix); + filter = createMatrixImageFilter(matrix, filter); + break; + } + case FilterOperation::SATURATE: { + float amount = static_cast<const BasicColorMatrixFilterOperation*>(&op)->amount(); + getSaturateMatrix(amount, matrix); + filter = createMatrixImageFilter(matrix, filter); + break; + } + case FilterOperation::HUE_ROTATE: { + float amount = static_cast<const BasicColorMatrixFilterOperation*>(&op)->amount(); + getHueRotateMatrix(amount, matrix); + filter = createMatrixImageFilter(matrix, filter); + break; + } + case FilterOperation::INVERT: { + float amount = static_cast<const BasicComponentTransferFilterOperation*>(&op)->amount(); + getInvertMatrix(amount, matrix); + filter = createMatrixImageFilter(matrix, filter); + break; + } + case FilterOperation::OPACITY: { + float amount = static_cast<const BasicComponentTransferFilterOperation*>(&op)->amount(); + getOpacityMatrix(amount, matrix); + filter = createMatrixImageFilter(matrix, filter); + break; + } + case FilterOperation::BRIGHTNESS: { + float amount = static_cast<const BasicComponentTransferFilterOperation*>(&op)->amount(); + getBrightnessMatrix(amount, matrix); + filter = createMatrixImageFilter(matrix, filter); + break; + } + case FilterOperation::CONTRAST: { + float amount = static_cast<const BasicComponentTransferFilterOperation*>(&op)->amount(); + getContrastMatrix(amount, matrix); + filter = createMatrixImageFilter(matrix, filter); + break; + } + case FilterOperation::BLUR: { + float pixelRadius = static_cast<const BlurFilterOperation*>(&op)->stdDeviation().getFloatValue(); + filter = new SkBlurImageFilter(pixelRadius, pixelRadius, filter); + break; + } + case FilterOperation::DROP_SHADOW: { +// const DropShadowFilterOperation& dropShadowOp = *static_cast<const DropShadowFilterOperation*>(&op); + // FIXME: do offset and blur + break; + } +#if ENABLE(CSS_SHADERS) + case FilterOperation::VALIDATED_CUSTOM: + case FilterOperation::CUSTOM: + // Not supported. +#endif + case FilterOperation::PASSTHROUGH: + case FilterOperation::NONE: + break; + } + } + return filter; +} + +}; diff --git a/Source/WebCore/platform/graphics/filters/skia/SkiaImageFilterBuilder.h b/Source/WebCore/platform/graphics/filters/skia/SkiaImageFilterBuilder.h new file mode 100644 index 000000000..27bd68320 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/skia/SkiaImageFilterBuilder.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 SkiaImageFilterBuilder_h +#define SkiaImageFilterBuilder_h + +#include <wtf/HashMap.h> + +class SkImageFilter; + +namespace WebCore { +class FilterEffect; +class FilterOperations; + +class SkiaImageFilterBuilder { +public: + SkiaImageFilterBuilder(); + + SkImageFilter* build(FilterEffect*); + SkImageFilter* build(const FilterOperations&); +private: + typedef HashMap<FilterEffect*, SkImageFilter*> FilterBuilderHashMap; + FilterBuilderHashMap m_map; +}; + +}; + +#endif diff --git a/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp b/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp index 30d889f5c..a16ad17df 100644 --- a/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp +++ b/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp @@ -98,27 +98,6 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri m_platformData.syntheticOblique()), isCustomFont(), false); } -PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - // FIXME: I think we want to ask FontConfig for the right font again. - if (!m_derivedFontData->smallCaps) - m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - - return m_derivedFontData->smallCaps; -} - -PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->emphasisMark) - m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - - return m_derivedFontData->emphasisMark; -} - bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { ASSERT(m_platformData.scaledFont()); diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp index e0686166d..b7d444f08 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp @@ -322,6 +322,14 @@ bool HarfBuzzShaper::shapeHarfBuzzRuns() HarfBuzzRun* currentRun = m_harfbuzzRuns[runIndex].get(); const SimpleFontData* currentFontData = currentRun->fontData(); + // This #if should be removed after all ports update harfbuzz-ng. +#if PLATFORM(CHROMIUM) + // Add a space as pre-context to the buffer. This prevents showing dotted-circle + // for combining marks at the beginning of runs. + static const uint16_t preContext = ' '; + hb_buffer_add_utf16(harfbuzzBuffer.get(), &preContext, 1, 1, 0); +#endif + if (m_font->isSmallCaps() && u_islower(m_normalizedBuffer[currentRun->startIndex()])) { String upperText = String(m_normalizedBuffer.get() + currentRun->startIndex(), currentRun->numCharacters()); upperText.makeUpper(); diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index f8bb43ba7..fc23bbd9b 100644 --- a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -52,8 +52,6 @@ using namespace std; namespace WebCore { -const float smallCapsFontSizeMultiplier = 0.7f; - static bool fontHasVerticalGlyphs(CTFontRef ctFont) { // The check doesn't look neat but this is what AppKit does for vertical writing... @@ -352,26 +350,6 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri return 0; } -PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->smallCaps) - m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFontSizeMultiplier); - - return m_derivedFontData->smallCaps; -} - -PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->emphasisMark) - m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5f); - - return m_derivedFontData->emphasisMark; -} - bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { NSString *string = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(characters) length:length freeWhenDone:NO]; diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp index db9fe43b6..58cfd7f7e 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp @@ -222,7 +222,7 @@ void GraphicsContext3D::reshape(int width, int height) if (width == m_currentWidth && height == m_currentHeight) return; -#if PLATFORM(QT) && USE(GRAPHICS_SURFACE) +#if (PLATFORM(QT) || PLATFORM(EFL)) && USE(GRAPHICS_SURFACE) ::glFlush(); // Make sure all GL calls have been committed before resizing. createGraphicsSurfaces(IntSize(width, height)); #endif @@ -1406,6 +1406,8 @@ void GraphicsContext3D::deleteShader(Platform3DObject shader) void GraphicsContext3D::deleteTexture(Platform3DObject texture) { makeContextCurrent(); + if (m_boundTexture0 == texture) + m_boundTexture0 = 0; glDeleteTextures(1, &texture); } diff --git a/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp b/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp index 4fc1fbe3e..f88cbbb7a 100644 --- a/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp +++ b/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp @@ -92,26 +92,6 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri return SimpleFontData::create(platformData); } -PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->smallCaps) - m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - - return m_derivedFontData->smallCaps; -} - -PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->emphasisMark) - m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - - return m_derivedFontData->emphasisMark; -} - bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { bool result = true; diff --git a/Source/WebCore/platform/graphics/qt/FontQt.cpp b/Source/WebCore/platform/graphics/qt/FontQt.cpp index f5bacddcc..e2cde765b 100644 --- a/Source/WebCore/platform/graphics/qt/FontQt.cpp +++ b/Source/WebCore/platform/graphics/qt/FontQt.cpp @@ -210,7 +210,10 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon QTextLine line = setupLayout(&layout, run); float x1 = line.cursorToX(0); float x2 = line.cursorToX(run.length()); - const float width = qAbs(x2 - x1); + float width = qAbs(x2 - x1); + // RenderBlockLineLayout expects us to only add word-spacing for trailing spaces, not for leading spaces. + if (treatAsSpace(run[0])) + width -= m_wordSpacing; return width + run.expansion(); } @@ -275,6 +278,9 @@ void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const { + if (!fontData->platformData().size()) + return; + if (context->paintingDisabled()) return; diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 9ec765caa..e083e2973 100644 --- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -45,6 +45,8 @@ #include <QTimer> #include <QUrl> #include <limits> +#include <qmediametadata.h> +#include <qmultimedia.h> #include <wtf/HashSet.h> #include <wtf/text/CString.h> @@ -92,7 +94,7 @@ MediaPlayer::SupportsType MediaPlayerPrivateQt::supportsType(const String& mime, codecListTrimmed.append(codecStrTrimmed); } - if (QMediaPlayer::hasSupport(mime, codecListTrimmed) >= QtMultimedia::ProbablySupported) + if (QMediaPlayer::hasSupport(mime, codecListTrimmed) >= QMultimedia::ProbablySupported) return MediaPlayer::IsSupported; return MediaPlayer::MayBeSupported; @@ -366,8 +368,8 @@ bool MediaPlayerPrivateQt::didLoadingProgress() const unsigned MediaPlayerPrivateQt::totalBytes() const { - if (m_mediaPlayer->availableMetaData().contains(QtMultimedia::MetaData::Size)) - return m_mediaPlayer->metaData(QtMultimedia::MetaData::Size).toInt(); + if (m_mediaPlayer->availableMetaData().contains(QMediaMetaData::Size)) + return m_mediaPlayer->metaData(QMediaMetaData::Size).toInt(); return 100; } diff --git a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp index 677d6086c..415f00d44 100644 --- a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp +++ b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp @@ -34,9 +34,6 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = false; } -static const float smallCapsFraction = 0.7; -static const float emphasisMarkFraction = 0.5; - bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { QRawFont rawFont(m_platformData.rawFont()); @@ -67,26 +64,6 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false); } -PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->smallCaps) - m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFraction); - - return m_derivedFontData->smallCaps; -} - -PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->emphasisMark) - m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, emphasisMarkFraction); - - return m_derivedFontData->emphasisMark; -} - FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const { notImplemented(); diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index 697fde224..ad47cf4b2 100644 --- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -194,6 +194,7 @@ bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DOb context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, false); context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false); + context.flush(); return true; } diff --git a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp index e5a52411d..1dbda0fda 100644 --- a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -389,9 +389,9 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag } if (resampling == RESAMPLE_NONE) { - // FIXME: This is to not break tests (it results in the filter bitmap flag - // being set to true). We need to decide if we respect RESAMPLE_NONE - // being returned from computeResamplingMode. + // FIXME: This is to not break tests (it results in the filter bitmap flag + // being set to true). We need to decide if we respect RESAMPLE_NONE + // being returned from computeResamplingMode. resampling = RESAMPLE_LINEAR; } resampling = limitResamplingMode(platformContext, resampling); @@ -449,6 +449,8 @@ bool FrameData::clear(bool clearMetadata) if (clearMetadata) m_haveMetadata = false; + m_orientation = DefaultImageOrientation; + if (m_frame) { // ImageSource::createFrameAtIndex() allocated |m_frame| and passed // ownership to BitmapImage; we must delete it here. @@ -470,14 +472,15 @@ void Image::drawPattern(GraphicsContext* context, #if PLATFORM(CHROMIUM) TRACE_EVENT0("skia", "Image::drawPattern"); #endif - FloatRect normSrcRect = normalizeRect(floatSrcRect); - if (destRect.isEmpty() || normSrcRect.isEmpty()) - return; // nothing to draw - NativeImageSkia* bitmap = nativeImageForCurrentFrame(); if (!bitmap) return; + FloatRect normSrcRect = normalizeRect(floatSrcRect); + normSrcRect.intersect(FloatRect(0, 0, bitmap->bitmap().width(), bitmap->bitmap().height())); + if (destRect.isEmpty() || normSrcRect.isEmpty()) + return; // nothing to draw + SkMatrix ctm = context->platformContext()->canvas()->getTotalMatrix(); SkMatrix totalMatrix; totalMatrix.setConcat(ctm, patternTransform); @@ -582,8 +585,12 @@ void BitmapImage::checkForSolidColor() } } -void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, - const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp) +void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp) +{ + draw(ctxt, dstRect, srcRect, colorSpace, compositeOp, DoNotRespectImageOrientation); +} + +void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp, RespectImageOrientationEnum shouldRespectImageOrientation) { if (!m_source.initialized()) return; @@ -599,10 +606,32 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, FloatRect normDstRect = normalizeRect(dstRect); FloatRect normSrcRect = normalizeRect(srcRect); + normSrcRect.intersect(FloatRect(0, 0, bm->bitmap().width(), bm->bitmap().height())); if (normSrcRect.isEmpty() || normDstRect.isEmpty()) return; // Nothing to draw. + ImageOrientation orientation = DefaultImageOrientation; + if (shouldRespectImageOrientation == RespectImageOrientation) + orientation = frameOrientationAtIndex(m_currentFrame); + + GraphicsContextStateSaver saveContext(*ctxt, false); + if (orientation != DefaultImageOrientation) { + saveContext.save(); + + // ImageOrientation expects the origin to be at (0, 0) + ctxt->translate(normDstRect.x(), normDstRect.y()); + normDstRect.setLocation(FloatPoint()); + + ctxt->concatCTM(orientation.transformFromDefault(normDstRect.size())); + + if (orientation.usesWidthAsHeight()) { + // The destination rect will have it's width and height already reversed for the orientation of + // the image, as it was needed for page layout, so we need to reverse it back here. + normDstRect = FloatRect(normDstRect.x(), normDstRect.y(), normDstRect.height(), normDstRect.width()); + } + } + paintSkBitmap(ctxt->platformContext(), *bm, normSrcRect, @@ -623,6 +652,7 @@ void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt, { FloatRect normDstRect = normalizeRect(dstRect); FloatRect normSrcRect = normalizeRect(srcRect); + normSrcRect.intersect(FloatRect(0, 0, m_nativeImage.bitmap().width(), m_nativeImage.bitmap().height())); if (normSrcRect.isEmpty() || normDstRect.isEmpty()) return; // Nothing to draw. diff --git a/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp b/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp index 4d32c74db..4fc098124 100644 --- a/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp @@ -47,9 +47,6 @@ namespace WebCore { -// Smallcaps versions of fonts are 70% the size of the normal font. -static const float smallCapsFraction = 0.7f; -static const float emphasisMarkFraction = .5; // This is the largest VDMX table which we'll try to load and parse. static const size_t maxVDMXTableSize = 1024 * 1024; // 1 MB @@ -183,26 +180,6 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false); } -PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->smallCaps) - m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFraction); - - return m_derivedFontData->smallCaps; -} - -PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->emphasisMark) - m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, emphasisMarkFraction); - - return m_derivedFontData->emphasisMark; -} - bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { SkPaint paint; @@ -234,9 +211,26 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = platformData().isFixedPitch(); } -FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const { - return FloatRect(); + if (!m_platformData.size()) + return FloatRect(); + + SkASSERT(sizeof(glyph) == 2); // compile-time assert + + SkPaint paint; + + m_platformData.setupPaint(&paint); + + paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + SkRect bounds; + paint.measureText(&glyph, 2, &bounds); + if (!paint.isSubpixelText()) { + SkIRect ir; + bounds.round(&ir); + bounds.set(ir); + } + return FloatRect(bounds); } float SimpleFontData::platformWidthForGlyph(Glyph glyph) const diff --git a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h index 13ac33051..5602cf521 100644 --- a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h +++ b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h @@ -35,10 +35,15 @@ typedef struct __IOSurface* IOSurfaceRef; typedef IOSurfaceRef PlatformGraphicsSurface; #endif + #if OS(LINUX) typedef uint32_t PlatformGraphicsSurface; #endif +#if OS(WINDOWS) +typedef HANDLE PlatformGraphicsSurface; +#endif + namespace WebCore { class BitmapTexture; diff --git a/Source/WebCore/platform/graphics/surfaces/GraphicsSurfaceToken.h b/Source/WebCore/platform/graphics/surfaces/GraphicsSurfaceToken.h index 45342f141..c97f368bd 100644 --- a/Source/WebCore/platform/graphics/surfaces/GraphicsSurfaceToken.h +++ b/Source/WebCore/platform/graphics/surfaces/GraphicsSurfaceToken.h @@ -33,7 +33,13 @@ namespace WebCore { struct GraphicsSurfaceToken { -typedef uint32_t BufferHandle; +#if OS(DARWIN) + typedef mach_port_t BufferHandle; +#elif OS(LINUX) + typedef uint32_t BufferHandle; +#elif OS(WINDOWS) + typedef HANDLE BufferHandle; +#endif #if HAVE(GLX) GraphicsSurfaceToken(uint32_t windowID = 0) @@ -52,7 +58,7 @@ typedef uint32_t BufferHandle; #endif -#if OS(DARWIN) +#if OS(DARWIN) || OS(WINDOWS) GraphicsSurfaceToken(BufferHandle frontBuffer = 0, BufferHandle backBuffer = 0) : frontBufferHandle(frontBuffer) , backBufferHandle(backBuffer) diff --git a/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp b/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp index d869eb5cf..8597eb4e2 100644 --- a/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp +++ b/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp @@ -29,6 +29,7 @@ #include <IOSurface/IOSurface.h> #include <OpenGL/OpenGL.h> #include <OpenGL/gl.h> +#include <mach/mach.h> #if PLATFORM(QT) #include <QGuiApplication> @@ -79,8 +80,8 @@ public: , m_readFbo(0) , m_drawFbo(0) { - m_frontBuffer = IOSurfaceLookup(m_token.frontBufferHandle); - m_backBuffer = IOSurfaceLookup(m_token.backBufferHandle); + m_frontBuffer = IOSurfaceLookupFromMachPort(m_token.frontBufferHandle); + m_backBuffer = IOSurfaceLookupFromMachPort(m_token.backBufferHandle); } GraphicsSurfacePrivate(const PlatformGraphicsContext3D shareContext, const IntSize& size, GraphicsSurface::Flags flags) @@ -91,22 +92,11 @@ public: , m_drawFbo(0) { #if PLATFORM(QT) -#if 0 - // This code path requires QCocoaNativeInterface::nativeResourceForContext() which is not availble in Qt5 on the build bots yet. QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface(); CGLContextObj shareContextObject = static_cast<CGLContextObj>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("cglContextObj"), shareContext)); if (!shareContextObject) return; -#else - // This code path should be removed as soon as QCocoaNativeInterface::nativeResourceForContext() has become available in Qt5 on the build bots. - CGLContextObj previousContext = CGLGetCurrentContext(); - QSurface* currentSurface = shareContext->surface(); - shareContext->makeCurrent(currentSurface); - CGLContextObj shareContextObject = CGLGetCurrentContext(); - - CGLSetCurrentContext(previousContext); -#endif CGLPixelFormatObj pixelFormatObject = CGLGetPixelFormat(shareContextObject); if (kCGLNoError != CGLCreateContext(pixelFormatObject, shareContextObject, &m_context)) return; @@ -127,8 +117,8 @@ public: if (!allocSize) return; - const void *keys[7]; - const void *values[7]; + const void *keys[6]; + const void *values[6]; keys[0] = kIOSurfaceWidth; values[0] = CFNumberCreate(0, kCFNumberIntType, &width); keys[1] = kIOSurfaceHeight; @@ -141,17 +131,18 @@ public: values[4] = CFNumberCreate(0, kCFNumberLongType, &bytesPerRow); keys[5] = kIOSurfaceAllocSize; values[5] = CFNumberCreate(0, kCFNumberLongType, &allocSize); - keys[6] = kIOSurfaceIsGlobal; - values[6] = (flags & GraphicsSurface::SupportsSharing) ? kCFBooleanTrue : kCFBooleanFalse; - CFDictionaryRef dict = CFDictionaryCreate(0, keys, values, 7, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - for (unsigned i = 0; i < 7; i++) + CFDictionaryRef dict = CFDictionaryCreate(0, keys, values, 6, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + for (unsigned i = 0; i < 6; i++) CFRelease(values[i]); m_frontBuffer = IOSurfaceCreate(dict); m_backBuffer = IOSurfaceCreate(dict); - m_token = GraphicsSurfaceToken(IOSurfaceGetID(m_frontBuffer), IOSurfaceGetID(m_backBuffer)); + if (!(flags & GraphicsSurface::SupportsSharing)) + return; + + m_token = GraphicsSurfaceToken(IOSurfaceCreateMachPort(m_frontBuffer), IOSurfaceCreateMachPort(m_backBuffer)); } ~GraphicsSurfacePrivate() @@ -177,6 +168,11 @@ public: if (m_context) CGLReleaseContext(m_context); + if (m_token.frontBufferHandle) + mach_port_deallocate(mach_task_self(), m_token.frontBufferHandle); + if (m_token.backBufferHandle) + mach_port_deallocate(mach_task_self(), m_token.backBufferHandle); + } uint32_t swapBuffers() diff --git a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp index fd62a0038..64077ba9c 100644 --- a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp +++ b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp @@ -22,13 +22,18 @@ #if USE(GRAPHICS_SURFACE) +#include "NotImplemented.h" #include "TextureMapperGL.h" + +#if PLATFORM(QT) // Qt headers must be included before glx headers. -#include <QCoreApplication> +#include <QGuiApplication> #include <QOpenGLContext> -#include <QVector> -#include <QWindow> -#include <qpa/qplatformwindow.h> +#include <qpa/qplatformnativeinterface.h> +#elif PLATFORM(EFL) +#include <GL/gl.h> +#endif + #include <GL/glext.h> #include <GL/glx.h> #include <X11/extensions/Xcomposite.h> @@ -50,39 +55,55 @@ class OffScreenRootWindow { public: OffScreenRootWindow() { - ++refCount; + ++m_refCount; } - QWindow* get(Display* dpy) + Window getXWindow() { - if (!window) { - window = new QWindow; - window->setGeometry(QRect(-1, -1, 1, 1)); - window->create(); + if (!m_window) { + Display* dpy = display(); + m_window = XCreateSimpleWindow(dpy, XDefaultRootWindow(dpy), -1, -1, 1, 1, 0, BlackPixel(dpy, 0), WhitePixel(dpy, 0)); XSetWindowAttributes attributes; attributes.override_redirect = true; - XChangeWindowAttributes(dpy, window->handle()->winId(), X11OverrideRedirect, &attributes); - window->show(); + XChangeWindowAttributes(dpy, m_window, X11OverrideRedirect, &attributes); + // Map window to the screen + XMapWindow(dpy, m_window); } - return window; + return m_window; + } + + Display* display() + { + if (!m_display) + m_display = XOpenDisplay(0); + return m_display; } ~OffScreenRootWindow() { - if (!--refCount) { - delete window; - window = 0; + if (--m_refCount || !m_display) + return; + + if (m_window) { + XUnmapWindow(m_display, m_window); + XDestroyWindow(m_display, m_window); + m_window = 0; } + + XCloseDisplay(m_display); + m_display = 0; } private: - static int refCount; - static QWindow* window; + static int m_refCount; + static Window m_window; + static Display* m_display; }; -int OffScreenRootWindow::refCount = 0; -QWindow* OffScreenRootWindow::window = 0; +int OffScreenRootWindow::m_refCount = 0; +Window OffScreenRootWindow::m_window = 0; +Display* OffScreenRootWindow::m_display = 0; static const int glxSpec[] = { // The specification is a set key value pairs stored in a simple array. @@ -106,25 +127,54 @@ struct GraphicsSurfacePrivate { : m_display(0) , m_xPixmap(0) , m_glxPixmap(0) - , m_glContext(adoptPtr(new QOpenGLContext)) + , m_glContext(0) , m_detachedContext(0) , m_detachedSurface(0) , m_textureIsYInverted(false) , m_hasAlpha(false) { - QSurface* currentSurface = 0; - QOpenGLContext* currentContext = QOpenGLContext::currentContext(); - if (currentContext) - currentSurface = currentContext->surface(); - - m_display = XOpenDisplay(0); - m_glContext->setShareContext(shareContext); - m_glContext->create(); - - // The GLX implementation of QOpenGLContext will reset the current context when create is being called. - // Therefore we have to make the previous context current again. - if (currentContext) - currentContext->makeCurrent(currentSurface); + GLXContext shareContextObject = 0; + m_display = m_offScreenWindow.display(); + +#if PLATFORM(QT) + if (shareContext) { +#if 0 + // This code path requires QXcbNativeInterface::nativeResourceForContext() which is not availble in Qt5 on the build bots yet. + QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface(); + shareContextObject = static_cast<GLXContext>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("glxcontext"), shareContext)); + if (!shareContextObject) + return; +#else + // This code path should be removed as soon as QXcbNativeInterface::nativeResourceForContext() can provide the GLXContext. + QOpenGLContext* previousContext = QOpenGLContext::currentContext(); + QSurface* previousSurface = previousContext->surface(); + QSurface* currentSurface = shareContext->surface(); + shareContext->makeCurrent(currentSurface); + + shareContextObject = glXGetCurrentContext(); + + previousContext->makeCurrent(previousSurface); +#endif + } +#else + UNUSED_PARAM(shareContext); +#endif + + int attributes[] = { + GLX_LEVEL, 0, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, True, + None + }; + + int numReturned; + m_fbConfigs = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &numReturned); + // Create a GLX context for OpenGL rendering + m_glContext = glXCreateNewContext(m_display, m_fbConfigs[0], GLX_RGBA_TYPE, shareContextObject, true); } ~GraphicsSurfacePrivate() @@ -137,27 +187,34 @@ struct GraphicsSurfacePrivate { XFreePixmap(m_display, m_xPixmap); m_xPixmap = 0; - if (m_display) - XCloseDisplay(m_display); - m_display = 0; + if (m_glContext) + glXDestroyContext(m_display, m_glContext); } uint32_t createSurface(const IntSize& size) { - m_surface = adoptPtr(new QWindow(m_offScreenWindow.get(m_display))); - m_surface->setSurfaceType(QSurface::OpenGLSurface); - m_surface->setGeometry(0, 0, size.width(), size.height()); - m_surface->create(); - XCompositeRedirectWindow(m_display, m_surface->handle()->winId(), CompositeRedirectManual); + XVisualInfo* visualInfo = glXGetVisualFromFBConfig(m_display, m_fbConfigs[0]); + if (!visualInfo) + return 0; + + Colormap cmap = XCreateColormap(m_display, m_offScreenWindow.getXWindow(), visualInfo->visual, AllocNone); + XSetWindowAttributes a; + a.background_pixel = WhitePixel(m_display, 0); + a.border_pixel = BlackPixel(m_display, 0); + a.colormap = cmap; + m_surface = XCreateWindow(m_display, m_offScreenWindow.getXWindow(), 0, 0, size.width(), size.height(), + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWBackPixel | CWBorderPixel | CWColormap, &a); + XSetWindowBackgroundPixmap(m_display, m_surface, 0); + XCompositeRedirectWindow(m_display, m_surface, CompositeRedirectManual); // Make sure the XRender Extension is available. int eventBasep, errorBasep; if (!XRenderQueryExtension(m_display, &eventBasep, &errorBasep)) return 0; - m_surface->show(); - - return m_surface->handle()->winId(); + XMapWindow(m_display, m_surface); + return m_surface; } void createPixmap(uint32_t winId) @@ -184,18 +241,17 @@ struct GraphicsSurfacePrivate { void makeCurrent() { - m_detachedContext = QOpenGLContext::currentContext(); - if (m_detachedContext) - m_detachedSurface = m_detachedContext->surface(); - + m_detachedContext = glXGetCurrentContext(); + m_detachedSurface = glXGetCurrentDrawable(); if (m_surface && m_glContext) - m_glContext->makeCurrent(m_surface.get()); + glXMakeCurrent(m_display, m_surface, m_glContext); } void doneCurrent() { if (m_detachedContext) - m_detachedContext->makeCurrent(m_detachedSurface); + glXMakeCurrent(m_display, m_detachedSurface, m_detachedContext); + m_detachedContext = 0; } void swapBuffers() @@ -206,20 +262,13 @@ struct GraphicsSurfacePrivate { if (m_xPixmap) return; - if (!m_surface->isVisible()) - return; - - // Creating and exposing the surface is asynchronous. Therefore we have to wait here - // before swapping the buffers. This should only be the case for the very first frame. - while (!m_surface->isExposed()) - QCoreApplication::processEvents(); + GLXContext glContext = glXGetCurrentContext(); - QOpenGLContext* glContext = QOpenGLContext::currentContext(); if (m_surface && glContext) { GLint oldFBO; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO); - pGlBindFramebuffer(GL_FRAMEBUFFER, glContext->defaultFramebufferObject()); - glContext->swapBuffers(m_surface.get()); + pGlBindFramebuffer(GL_FRAMEBUFFER, 0); + glXSwapBuffers(m_display, m_surface); pGlBindFramebuffer(GL_FRAMEBUFFER, oldFBO); } } @@ -242,7 +291,7 @@ struct GraphicsSurfacePrivate { glBindTexture(GL_TEXTURE_2D, texture); pGlFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - pGlBindFramebuffer(GL_DRAW_FRAMEBUFFER, glContext()->defaultFramebufferObject()); + pGlBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); pGlBlitFramebuffer(x, y, width, height, x, y, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR); pGlFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); @@ -254,45 +303,40 @@ struct GraphicsSurfacePrivate { doneCurrent(); } - Display* display() const { return m_display; } GLXPixmap glxPixmap() const { return m_glxPixmap; } IntSize size() const { return m_size; } - QOpenGLContext* glContext() { return m_glContext.get(); } - private: OffScreenRootWindow m_offScreenWindow; IntSize m_size; Display* m_display; Pixmap m_xPixmap; GLXPixmap m_glxPixmap; - OwnPtr<QWindow> m_surface; - OwnPtr<QOpenGLContext> m_glContext; - QOpenGLContext* m_detachedContext; - QSurface* m_detachedSurface; + Window m_surface; + GLXContext m_glContext; + GLXContext m_detachedContext; + GLXDrawable m_detachedSurface; + GLXFBConfig* m_fbConfigs; bool m_textureIsYInverted; bool m_hasAlpha; }; -static bool resolveGLMethods(GraphicsSurfacePrivate* p) +static bool resolveGLMethods(GraphicsSurfacePrivate*) { static bool resolved = false; if (resolved) return true; - - QOpenGLContext* glContext = p->glContext(); - pGlXBindTexImageEXT = reinterpret_cast<PFNGLXBINDTEXIMAGEEXTPROC>(glContext->getProcAddress("glXBindTexImageEXT")); - pGlXReleaseTexImageEXT = reinterpret_cast<PFNGLXRELEASETEXIMAGEEXTPROC>(glContext->getProcAddress("glXReleaseTexImageEXT")); - pGlBindFramebuffer = reinterpret_cast<PFNGLBINDFRAMEBUFFERPROC>(glContext->getProcAddress("glBindFramebuffer")); - pGlBlitFramebuffer = reinterpret_cast<PFNGLBLITFRAMEBUFFERPROC>(glContext->getProcAddress("glBlitFramebuffer")); - - pGlGenFramebuffers = reinterpret_cast<PFNGLGENFRAMEBUFFERSPROC>(glContext->getProcAddress("glGenFramebuffers")); - pGlDeleteFramebuffers = reinterpret_cast<PFNGLDELETEFRAMEBUFFERSPROC>(glContext->getProcAddress("glDeleteFramebuffers")); - pGlFramebufferTexture2D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DPROC>(glContext->getProcAddress("glFramebufferTexture2D")); - + pGlXBindTexImageEXT = reinterpret_cast<PFNGLXBINDTEXIMAGEEXTPROC>(glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXBindTexImageEXT"))); + pGlXReleaseTexImageEXT = reinterpret_cast<PFNGLXRELEASETEXIMAGEEXTPROC>(glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXReleaseTexImageEXT"))); + pGlBindFramebuffer = reinterpret_cast<PFNGLBINDFRAMEBUFFERPROC>(glXGetProcAddress(reinterpret_cast<const GLubyte*>("glBindFramebuffer"))); + pGlBlitFramebuffer = reinterpret_cast<PFNGLBLITFRAMEBUFFERPROC>(glXGetProcAddress(reinterpret_cast<const GLubyte*>("glBlitFramebuffer"))); + + pGlGenFramebuffers = reinterpret_cast<PFNGLGENFRAMEBUFFERSPROC>(glXGetProcAddress(reinterpret_cast<const GLubyte*>("glGenFramebuffers"))); + pGlDeleteFramebuffers = reinterpret_cast<PFNGLDELETEFRAMEBUFFERSPROC>(glXGetProcAddress(reinterpret_cast<const GLubyte*>("glDeleteFramebuffers"))); + pGlFramebufferTexture2D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DPROC>(glXGetProcAddress(reinterpret_cast<const GLubyte*>("glFramebufferTexture2D"))); resolved = pGlBlitFramebuffer && pGlBindFramebuffer && pGlXBindTexImageEXT && pGlXReleaseTexImageEXT; return resolved; @@ -318,7 +362,7 @@ uint32_t GraphicsSurface::platformGetTextureID() return m_texture; } -void GraphicsSurface::platformCopyToGLTexture(uint32_t target, uint32_t id, const IntRect& targetRect, const IntPoint& offset) +void GraphicsSurface::platformCopyToGLTexture(uint32_t /*target*/, uint32_t /*id*/, const IntRect& /*targetRect*/, const IntPoint& /*offset*/) { // This is not supported by GLX/Xcomposite. } @@ -331,9 +375,10 @@ void GraphicsSurface::platformCopyFromTexture(uint32_t texture, const IntRect& s void GraphicsSurface::platformPaintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity, BitmapTexture* mask) { + TextureMapperGL* texMapGL = static_cast<TextureMapperGL*>(textureMapper); TransformationMatrix adjustedTransform = transform; adjustedTransform.multiply(TransformationMatrix::rectToRect(FloatRect(FloatPoint::zero(), m_size), targetRect)); - static_cast<TextureMapperGL*>(textureMapper)->drawTexture(platformGetTextureID(), 0, m_size, targetRect, adjustedTransform, opacity, mask); + texMapGL->drawTexture(platformGetTextureID(), TextureMapperGL::ShouldFlipTexture, m_size, targetRect, adjustedTransform, opacity, mask); } uint32_t GraphicsSurface::platformFrontBuffer() const @@ -388,7 +433,7 @@ PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, return surface; } -char* GraphicsSurface::platformLock(const IntRect& rect, int* outputStride, LockOptions lockOptions) +char* GraphicsSurface::platformLock(const IntRect&, int* /*outputStride*/, LockOptions) { // GraphicsSurface is currently only being used for WebGL, which does not require this locking mechanism. return 0; @@ -410,5 +455,18 @@ void GraphicsSurface::platformDestroy() m_private = 0; } +#if !PLATFORM(QT) +PassOwnPtr<GraphicsContext> GraphicsSurface::platformBeginPaint(const IntSize&, char*, int) +{ + notImplemented(); + return nullptr; +} + +PassRefPtr<Image> GraphicsSurface::createReadOnlyImage(const IntRect&) +{ + notImplemented(); + return 0; +} +#endif } #endif diff --git a/Source/WebCore/platform/graphics/surfaces/win/GraphicsSurfaceWin.cpp b/Source/WebCore/platform/graphics/surfaces/win/GraphicsSurfaceWin.cpp new file mode 100644 index 000000000..19bebd2ff --- /dev/null +++ b/Source/WebCore/platform/graphics/surfaces/win/GraphicsSurfaceWin.cpp @@ -0,0 +1,492 @@ +/* + + Copyright (C) 2012 Zeno Albisser <zeno@webkit.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "GraphicsSurface.h" + +#if USE(GRAPHICS_SURFACE) +#include "TextureMapperGL.h" + +#define EGL_EGLEXT_PROTOTYPES // This must be defined before including egl.h and eglext.h. +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#if PLATFORM(QT) +#include <QGuiApplication> +#include <QOpenGLContext> +#include <qpa/qplatformnativeinterface.h> +#endif + +namespace WebCore { + +#define STRINGIFY(...) #__VA_ARGS__ + +static GLuint loadShader(GLenum type, const GLchar *shaderSrc) +{ + GLuint shader; + GLint compiled; + + shader = glCreateShader(type); + if (!shader) + return 0; + + glShaderSource(shader, 1, &shaderSrc, 0); + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) { + glDeleteShader(shader); + return 0; + } + return shader; +} + +struct GraphicsSurfacePrivate { +public: + GraphicsSurfacePrivate(const IntSize& size, GraphicsSurfaceToken token) + : m_token(token) + , m_detachedContext(0) + , m_detachedReadSurface(0) + , m_detachedDrawSurface(0) + , m_size(size) + , m_eglDisplay(0) + , m_eglContext(0) + , m_eglConfig(0) + , m_eglFrontBufferSurface(0) + , m_eglBackBufferSurface(0) + , m_initialFrontBufferShareHandle(token.frontBufferHandle) + , m_frontBufferShareHandle(token.frontBufferHandle) + , m_backBufferShareHandle(token.backBufferHandle) + , m_frontBufferTexture(0) + , m_shaderProgram(0) + { + initializeShaderProgram(); + } + + + GraphicsSurfacePrivate(const PlatformGraphicsContext3D shareContext, const IntSize& size, GraphicsSurface::Flags flags) + : m_detachedContext(0) + , m_detachedReadSurface(0) + , m_detachedDrawSurface(0) + , m_size(size) + , m_eglDisplay(0) + , m_eglContext(0) + , m_eglConfig(0) + , m_eglFrontBufferSurface(0) + , m_eglBackBufferSurface(0) + , m_initialFrontBufferShareHandle(0) + , m_frontBufferShareHandle(0) + , m_backBufferShareHandle(0) + , m_frontBufferTexture(0) + , m_shaderProgram(0) + { + initializeShaderProgram(); + + static PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE = 0; + if (!eglQuerySurfacePointerANGLE) { + eglQuerySurfacePointerANGLE = reinterpret_cast<PFNEGLQUERYSURFACEPOINTERANGLEPROC>(eglGetProcAddress("eglQuerySurfacePointerANGLE")); + if (!eglQuerySurfacePointerANGLE) + return; + } + + if (!m_eglDisplay || !m_eglContext || !m_eglConfig) { + m_eglDisplay = eglGetCurrentDisplay(); + +#if PLATFORM(QT) + QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface(); + m_eglConfig = static_cast<EGLConfig>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("eglConfig"), shareContext)); + EGLContext eglShareContext = static_cast<EGLContext>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("eglContext"), shareContext)); +#endif + EGLint contextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, eglShareContext, contextAttributes); + } + + EGLint attributes[] = { + EGL_WIDTH, size.width(), + EGL_HEIGHT, size.height(), + EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB, + EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, + EGL_NONE + }; + + m_eglFrontBufferSurface = eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, attributes); + m_eglBackBufferSurface = eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, attributes); + if (m_eglFrontBufferSurface == EGL_NO_SURFACE || m_eglBackBufferSurface == EGL_NO_SURFACE) + return; + + eglQuerySurfacePointerANGLE(m_eglDisplay, m_eglFrontBufferSurface, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &m_frontBufferShareHandle); + eglQuerySurfacePointerANGLE(m_eglDisplay, m_eglBackBufferSurface, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &m_backBufferShareHandle); + + m_initialFrontBufferShareHandle = m_frontBufferShareHandle; + + m_token = GraphicsSurfaceToken(m_frontBufferShareHandle, m_backBufferShareHandle); + } + + ~GraphicsSurfacePrivate() + { + releaseFrontBufferTexture(); + + if (m_eglBackBufferSurface) + eglDestroySurface(m_eglDisplay, m_eglBackBufferSurface); + + if (m_shaderProgram) + glDeleteProgram(m_shaderProgram); + m_shaderProgram = 0; + + if (m_eglDisplay && m_eglContext) + eglDestroyContext(m_eglDisplay, m_eglContext); + } + + void copyFromTexture(uint32_t texture, const IntRect& sourceRect) + { + if (!makeCurrent()) + return; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + drawTexture(texture); + glFinish(); + doneCurrent(); + } + + bool makeCurrent() + { + m_detachedContext = eglGetCurrentContext(); + m_detachedReadSurface = eglGetCurrentSurface(EGL_READ); + m_detachedDrawSurface = eglGetCurrentSurface(EGL_DRAW); + + return eglMakeCurrent(m_eglDisplay, m_eglBackBufferSurface, m_eglBackBufferSurface, m_eglContext); + } + + bool doneCurrent() + { + if (!m_detachedContext || !m_detachedDrawSurface || !m_detachedReadSurface) + return false; + + bool success = eglMakeCurrent(m_eglDisplay, m_detachedDrawSurface, m_detachedReadSurface, m_detachedContext); + m_detachedContext = 0; + m_detachedReadSurface = 0; + m_detachedDrawSurface = 0; + return success; + } + + PlatformGraphicsSurface swapBuffers() + { + if (m_frontBufferTexture) + releaseFrontBufferTexture(); + std::swap(m_eglFrontBufferSurface, m_eglBackBufferSurface); + std::swap(m_frontBufferShareHandle, m_backBufferShareHandle); + + return m_frontBufferShareHandle; + } + + GraphicsSurfaceToken token() const + { + return m_token; + } + + uint32_t frontBufferTextureID() + { + if (!m_eglFrontBufferSurface) { + m_eglFrontBufferSurface = createSurfaceFromShareHandle(m_size, m_frontBufferShareHandle); + + glGenTextures(1, &m_frontBufferTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_frontBufferTexture); + eglBindTexImage(m_eglDisplay, m_eglFrontBufferSurface, EGL_BACK_BUFFER); + + 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); + } + + return m_frontBufferTexture; + } + + PlatformGraphicsSurface initialFrontBufferShareHandle() const + { + return m_initialFrontBufferShareHandle; + } + + PlatformGraphicsSurface frontBufferShareHandle() const + { + return m_frontBufferShareHandle; + } + + PlatformGraphicsSurface backBufferShareHandle() const + { + return m_backBufferShareHandle; + } + + void releaseFrontBufferTexture() + { + if (m_frontBufferTexture) { + eglReleaseTexImage(m_eglDisplay, m_eglFrontBufferSurface, EGL_BACK_BUFFER); + glDeleteTextures(1, &m_frontBufferTexture); + m_frontBufferTexture = 0; + } + + if (m_eglFrontBufferSurface) + eglDestroySurface(m_eglDisplay, m_eglFrontBufferSurface); + m_eglFrontBufferSurface = 0; + } + + +protected: + void initializeShaderProgram() + { + if (m_shaderProgram) + return; + + GLchar vShaderStr[] = + STRINGIFY( + attribute highp vec2 vertex; + attribute highp vec2 textureCoordinates; + varying highp vec2 textureCoords; + void main(void) + { + gl_Position = vec4(vertex, 0.0, 1.0); + textureCoords = textureCoordinates; + } + ); + + GLchar fShaderStr[] = + STRINGIFY( + varying highp vec2 textureCoords; + uniform sampler2D texture; + void main(void) + { + highp vec3 color = texture2D(texture, textureCoords).rgb; + gl_FragColor = vec4(clamp(color, 0.0, 1.0), 1.0); + } + ); + + GLuint vertexShader; + GLuint fragmentShader; + GLint linked; + + vertexShader = loadShader(GL_VERTEX_SHADER, vShaderStr); + fragmentShader = loadShader(GL_FRAGMENT_SHADER, fShaderStr); + if (!vertexShader || !fragmentShader) + return; + + m_shaderProgram = glCreateProgram(); + if (!m_shaderProgram) + return; + + glAttachShader(m_shaderProgram, vertexShader); + glAttachShader(m_shaderProgram, fragmentShader); + + glLinkProgram(m_shaderProgram); + glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &linked); + if (!linked) { + glDeleteProgram(m_shaderProgram); + m_shaderProgram = 0; + } + + m_vertexAttr = glGetAttribLocation(m_shaderProgram, "vertex"); + m_textureCoordinatesAttr = glGetAttribLocation(m_shaderProgram, "textureCoordinates"); + m_textureUniform = glGetAttribLocation(m_shaderProgram, "texture"); + + 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); + } + + EGLSurface createSurfaceFromShareHandle(const IntSize& size, HANDLE shareHandle) + { + if (!m_eglDisplay || !m_eglConfig) { + m_eglDisplay = eglGetCurrentDisplay(); + +#if PLATFORM(QT) + QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface(); + m_eglConfig = static_cast<EGLConfig>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("eglConfig"), QOpenGLContext::currentContext())); +#endif + } + + EGLint attributes[] = { + EGL_WIDTH, size.width(), + EGL_HEIGHT, size.height(), + EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB, + EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, + EGL_NONE + }; + + EGLSurface surface = eglCreatePbufferFromClientBuffer(m_eglDisplay, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, reinterpret_cast<EGLClientBuffer>(shareHandle), m_eglConfig, attributes); + ASSERT(surface); + + return surface; + } + + void drawTexture(uint32_t texture) + { + glUseProgram(m_shaderProgram); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, texture); + + 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); + + GLfloat afVertices[] = { + -1, -1, + 1, -1, + -1, 1, + 1, 1 + }; + glVertexAttribPointer(m_vertexAttr, 2, GL_FLOAT, GL_FALSE, 0, afVertices); + + GLfloat aftextureCoordinates[] = { + 0, 1, + 1, 1, + 0, 0, + 1, 0 + }; + glVertexAttribPointer(m_textureCoordinatesAttr, 2, GL_FLOAT, GL_FALSE, 0, aftextureCoordinates); + + glUniform1i(m_textureUniform, 0); + + glEnableVertexAttribArray(m_vertexAttr); + glEnableVertexAttribArray(m_textureCoordinatesAttr); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glDisableVertexAttribArray(m_vertexAttr); + glDisableVertexAttribArray(m_textureCoordinatesAttr); + + glBindTexture(GL_TEXTURE_2D, 0); + } + +private: + GraphicsSurfaceToken m_token; + EGLContext m_detachedContext; + EGLSurface m_detachedReadSurface; + EGLSurface m_detachedDrawSurface; + IntSize m_size; + EGLDisplay m_eglDisplay; + EGLContext m_eglContext; + EGLConfig m_eglConfig; + EGLSurface m_eglFrontBufferSurface; + EGLSurface m_eglBackBufferSurface; + PlatformGraphicsSurface m_initialFrontBufferShareHandle; + PlatformGraphicsSurface m_frontBufferShareHandle; + PlatformGraphicsSurface m_backBufferShareHandle; + GLuint m_frontBufferTexture; + GLint m_shaderProgram; + + GLuint m_vertexAttr; + GLuint m_textureCoordinatesAttr; + GLuint m_textureUniform; +}; + +GraphicsSurfaceToken GraphicsSurface::platformExport() +{ + return m_private->token(); +} + +uint32_t GraphicsSurface::platformGetTextureID() +{ + return m_private->frontBufferTextureID(); +} + +void GraphicsSurface::platformCopyToGLTexture(uint32_t target, uint32_t id, const IntRect& targetRect, const IntPoint& offset) +{ + // Currently not implemented. +} + +void GraphicsSurface::platformCopyFromTexture(uint32_t texture, const IntRect& sourceRect) +{ + m_private->copyFromTexture(texture, sourceRect); +} + +void GraphicsSurface::platformPaintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity, BitmapTexture* mask) +{ + GLuint frontBufferTexture = platformGetTextureID(); + + TransformationMatrix adjustedTransform = transform; + adjustedTransform.multiply(TransformationMatrix::rectToRect(FloatRect(FloatPoint::zero(), m_size), targetRect)); + static_cast<TextureMapperGL*>(textureMapper)->drawTexture(frontBufferTexture, 0, m_size, targetRect, adjustedTransform, opacity, mask); +} + +uint32_t GraphicsSurface::platformFrontBuffer() const +{ + if (m_private->initialFrontBufferShareHandle() == m_private->frontBufferShareHandle()) + return 0; + if (m_private->initialFrontBufferShareHandle() == m_private->backBufferShareHandle()) + return 1; + return 0xFFFF; +} + +uint32_t GraphicsSurface::platformSwapBuffers() +{ + m_private->swapBuffers(); + return platformFrontBuffer(); +} + +PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, Flags flags, const PlatformGraphicsContext3D shareContext) +{ + // Single buffered GraphicsSurface is currently not supported. + if (flags & SupportsCopyToTexture || flags & SupportsSingleBuffered) + return PassRefPtr<GraphicsSurface>(); + + RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(size, flags)); + surface->m_private = new GraphicsSurfacePrivate(shareContext, size, flags); + + if (!surface->m_private->frontBufferShareHandle() || !surface->m_private->backBufferShareHandle()) + return PassRefPtr<GraphicsSurface>(); + + return surface; +} + +PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, const GraphicsSurfaceToken& token) +{ + // Single buffered GraphicsSurface is currently not supported. + if (flags & SupportsCopyToTexture || flags & SupportsSingleBuffered) + return PassRefPtr<GraphicsSurface>(); + + RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(size, flags)); + surface->m_private = new GraphicsSurfacePrivate(size, token); + + if (!surface->m_private->frontBufferShareHandle() || !surface->m_private->backBufferShareHandle()) + return PassRefPtr<GraphicsSurface>(); + + return surface; +} + +char* GraphicsSurface::platformLock(const IntRect& rect, int* outputStride, LockOptions lockOptions) +{ + // GraphicsSurface is currently only being used for WebGL, which does not require this locking mechanism. + return 0; +} + +void GraphicsSurface::platformUnlock() +{ + // GraphicsSurface is currently only being used for WebGL, which does not require this locking mechanism. +} + +void GraphicsSurface::platformDestroy() +{ + delete m_private; + m_private = 0; +} + +} +#endif diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp index 42954a499..41897c63e 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "GraphicsLayerTextureMapper.h" +#include "GraphicsLayerAnimation.h" #include "GraphicsLayerFactory.h" #include "TextureMapperLayer.h" @@ -87,6 +88,7 @@ void GraphicsLayerTextureMapper::setNeedsDisplay() { m_needsDisplay = true; notifyChange(TextureMapperLayer::DisplayChange); + addRepaintRect(FloatRect(FloatPoint(), m_size)); } /* \reimp (GraphicsLayer.h) @@ -94,6 +96,7 @@ void GraphicsLayerTextureMapper::setNeedsDisplay() void GraphicsLayerTextureMapper::setContentsNeedsDisplay() { notifyChange(TextureMapperLayer::DisplayChange); + addRepaintRect(contentsRect()); } /* \reimp (GraphicsLayer.h) @@ -104,6 +107,7 @@ void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect) return; m_needsDisplayRect.unite(rect); notifyChange(TextureMapperLayer::DisplayChange); + addRepaintRect(rect); } /* \reimp (GraphicsLayer.h) @@ -392,12 +396,19 @@ bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList if (valueList.property() == AnimatedPropertyWebkitTransform) listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0; - m_animations.add(GraphicsLayerAnimation(keyframesName, valueList, boxSize, anim, timeOffset, listsMatch)); + m_animations.add(GraphicsLayerAnimation(keyframesName, valueList, boxSize, anim, WTF::currentTime() - timeOffset, listsMatch)); notifyChange(TextureMapperLayer::AnimationChange); m_animationStartedTimer.startOneShot(0); return true; } +void GraphicsLayerTextureMapper::setAnimations(const GraphicsLayerAnimations& animations) +{ + m_animations = animations; + notifyChange(TextureMapperLayer::AnimationChange); +} + + void GraphicsLayerTextureMapper::pauseAnimation(const String& animationName, double timeOffset) { m_animations.pause(animationName, timeOffset); diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h index 637abd9d4..510b23f5c 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h @@ -81,6 +81,7 @@ public: virtual bool addAnimation(const KeyframeValueList&, const IntSize&, const Animation*, const String&, double); virtual void pauseAnimation(const String&, double); virtual void removeAnimation(const String&); + void setAnimations(const GraphicsLayerAnimations&); TextureMapperLayer* layer() const { return m_layer.get(); } TextureMapperPlatformLayer* contentsLayer() const { return m_contentsLayer; } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp index cee45b969..7a980a9c5 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp @@ -21,33 +21,108 @@ #include "TextureMapper.h" #include "TextureMapperImageBuffer.h" +#include "Timer.h" +#include <wtf/CurrentTime.h> +#include <wtf/NonCopyingSort.h> #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) namespace WebCore { -PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& size) +struct BitmapTexturePoolEntry { + explicit BitmapTexturePoolEntry(PassRefPtr<BitmapTexture> texture) + : m_texture(texture) + { } + inline void markUsed() { m_timeLastUsed = monotonicallyIncreasingTime(); } + static bool compareTimeLastUsed(const BitmapTexturePoolEntry& a, const BitmapTexturePoolEntry& b) + { + return a.m_timeLastUsed - b.m_timeLastUsed > 0; + } + + RefPtr<BitmapTexture> m_texture; + double m_timeLastUsed; +}; + +class BitmapTexturePool { + WTF_MAKE_NONCOPYABLE(BitmapTexturePool); + WTF_MAKE_FAST_ALLOCATED; +public: + BitmapTexturePool(); + + PassRefPtr<BitmapTexture> acquireTexture(const IntSize&, TextureMapper*); + +private: + void scheduleReleaseUnusedTextures(); + void releaseUnusedTexturesTimerFired(Timer<BitmapTexturePool>*); + + Vector<BitmapTexturePoolEntry> m_textures; + Timer<BitmapTexturePool> m_releaseUnusedTexturesTimer; + + static const double s_releaseUnusedSecondsTolerance; + static const double s_releaseUnusedTexturesTimerInterval; +}; + +const double BitmapTexturePool::s_releaseUnusedSecondsTolerance = 3; +const double BitmapTexturePool::s_releaseUnusedTexturesTimerInterval = 0.5; + +BitmapTexturePool::BitmapTexturePool() + : m_releaseUnusedTexturesTimer(this, &BitmapTexturePool::releaseUnusedTexturesTimerFired) +{ } + +void BitmapTexturePool::scheduleReleaseUnusedTextures() +{ + if (m_releaseUnusedTexturesTimer.isActive()) + m_releaseUnusedTexturesTimer.stop(); + + m_releaseUnusedTexturesTimer.startOneShot(s_releaseUnusedTexturesTimerInterval); +} + +void BitmapTexturePool::releaseUnusedTexturesTimerFired(Timer<BitmapTexturePool>*) { - RefPtr<BitmapTexture> selectedTexture; + if (m_textures.isEmpty()) + return; + + // Delete entries, which have been unused in s_releaseUnusedSecondsTolerance. + nonCopyingSort(m_textures.begin(), m_textures.end(), BitmapTexturePoolEntry::compareTimeLastUsed); + + double minUsedTime = monotonicallyIncreasingTime() - s_releaseUnusedSecondsTolerance; + for (size_t i = 0; i < m_textures.size(); ++i) { + if (m_textures[i].m_timeLastUsed < minUsedTime) { + m_textures.remove(i, m_textures.size() - i); + break; + } + } +} - for (size_t i = 0; i < m_texturePool.size(); ++i) { - RefPtr<BitmapTexture>& texture = m_texturePool[i]; +PassRefPtr<BitmapTexture> BitmapTexturePool::acquireTexture(const IntSize& size, TextureMapper* textureMapper) +{ + BitmapTexturePoolEntry* selectedEntry = 0; + for (size_t i = 0; i < m_textures.size(); ++i) { + BitmapTexturePoolEntry* entry = &m_textures[i]; - // If the surface has only one reference (the one in m_texturePool), we can safely reuse it. - if (texture->refCount() > 1) + // If the surface has only one reference (the one in m_textures), we can safely reuse it. + if (entry->m_texture->refCount() > 1) continue; - if (texture->canReuseWith(size)) { - selectedTexture = texture; + if (entry->m_texture->canReuseWith(size)) { + selectedEntry = entry; break; } } - if (!selectedTexture) { - selectedTexture = createTexture(); - m_texturePool.append(selectedTexture); + if (!selectedEntry) { + m_textures.append(BitmapTexturePoolEntry(textureMapper->createTexture())); + selectedEntry = &m_textures.last(); } + scheduleReleaseUnusedTextures(); + selectedEntry->markUsed(); + return selectedEntry->m_texture; +} + +PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& size) +{ + RefPtr<BitmapTexture> selectedTexture = m_texturePool->acquireTexture(size, this); selectedTexture->reset(size, BitmapTexture::SupportsAlpha); return selectedTexture; } @@ -59,5 +134,15 @@ PassOwnPtr<TextureMapper> TextureMapper::create(AccelerationMode mode) return platformCreateAccelerated(); } +TextureMapper::TextureMapper(AccelerationMode accelerationMode) + : m_interpolationQuality(InterpolationDefault) + , m_textDrawingMode(TextModeFill) + , m_texturePool(adoptPtr(new BitmapTexturePool())) + , m_accelerationMode(accelerationMode) +{ } + +TextureMapper::~TextureMapper() +{ } + } #endif diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h index 282bf2ca4..2693d9ad9 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h @@ -47,6 +47,7 @@ namespace WebCore { +class BitmapTexturePool; class TextureMapper; // A 2D texture that can be the target of software or GL rendering. @@ -115,7 +116,7 @@ public: typedef unsigned PaintFlags; static PassOwnPtr<TextureMapper> create(AccelerationMode newMode = SoftwareMode); - virtual ~TextureMapper() { } + virtual ~TextureMapper(); enum ExposedEdges { NoEdges = 0, @@ -150,15 +151,10 @@ public: virtual IntSize maxTextureSize() const { return IntSize(INT_MAX, INT_MAX); } - // A surface is released implicitly when dereferenced. virtual PassRefPtr<BitmapTexture> acquireTextureFromPool(const IntSize&); protected: - TextureMapper(AccelerationMode accelerationMode) - : m_interpolationQuality(InterpolationDefault) - , m_textDrawingMode(TextModeFill) - , m_accelerationMode(accelerationMode) - {} + TextureMapper(AccelerationMode); private: #if USE(TEXTURE_MAPPER_GL) @@ -171,7 +167,7 @@ private: #endif InterpolationQuality m_interpolationQuality; TextDrawingModeFlags m_textDrawingMode; - Vector<RefPtr<BitmapTexture> > m_texturePool; + OwnPtr<BitmapTexturePool> m_texturePool; GraphicsContext* m_context; AccelerationMode m_accelerationMode; }; diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp index d4015a7c7..acfafb99b 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp @@ -33,10 +33,6 @@ #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#if USE(GRAPHICS_SURFACE) -#include "GraphicsSurface.h" -#endif - #if PLATFORM(QT) #include "NativeImageQt.h" #endif @@ -381,7 +377,7 @@ void TextureMapperGL::drawTextureRectangleARB(uint32_t texture, Flags flags, con m_context3D->uniform1i(program->samplerLocation(), 0); m_context3D->uniform1f(program->flipLocation(), !!(flags & ShouldFlipTexture)); - m_context3D->uniform2f(program->textureSizeLocation(), textureSize.width(), textureSize.height()); + m_context3D->uniform2f(program->samplerSizeLocation(), textureSize.width(), textureSize.height()); m_context3D->uniform1f(program->opacityLocation(), opacity); if (maskTexture && maskTexture->isValid()) { @@ -644,6 +640,7 @@ void BitmapTextureGL::updateContents(const void* srcData, const IntRect& targetR const unsigned bytesPerPixel = 4; char* data = reinterpret_cast<char*>(const_cast<void*>(srcData)); Vector<char> temporaryData; + IntPoint adjustedSourceOffset = sourceOffset; // prepare temporaryData if necessary if ((!driverSupportsBGRASwizzling() && updateContentsFlag == UpdateCannotModifyOriginalImageData) @@ -659,14 +656,17 @@ void BitmapTextureGL::updateContents(const void* srcData, const IntRect& targetR src += bytesPerLine; dst += targetBytesPerLine; } + + bytesPerLine = targetBytesPerLine; + adjustedSourceOffset = IntPoint(0, 0); } if (driverSupportsBGRASwizzling()) glFormat = GraphicsContext3D::BGRA; else - swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(data), IntRect(sourceOffset, targetRect.size()), bytesPerLine / bytesPerPixel); + swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(data), IntRect(adjustedSourceOffset, targetRect.size()), bytesPerLine / bytesPerPixel); - if (bytesPerLine == targetRect.width() * bytesPerPixel && sourceOffset == IntPoint::zero()) { + if (bytesPerLine == static_cast<int>(targetRect.width() * bytesPerPixel) && adjustedSourceOffset == IntPoint::zero()) { m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, data); return; } @@ -680,8 +680,8 @@ void BitmapTextureGL::updateContents(const void* srcData, const IntRect& targetR #if !defined(TEXMAP_OPENGL_ES_2) // Use the OpenGL sub-image extension, now that we know it's available. m_context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerLine / bytesPerPixel); - m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, sourceOffset.y()); - m_context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, sourceOffset.x()); + m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, adjustedSourceOffset.y()); + m_context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, adjustedSourceOffset.x()); m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, data); m_context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, 0); m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, 0); diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp index 21bd7b235..401af8c3e 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp @@ -129,7 +129,7 @@ void TextureMapperLayer::updateBackingStore(TextureMapper* textureMapper, Graphi context->translate(-dirtyRect.x(), -dirtyRect.y()); layer->paintGraphicsLayerContents(*context, dirtyRect); - if (layer->showRepaintCounter()) { + if (layer->isShowingRepaintCounter()) { layer->incrementRepaintCount(); drawRepaintCounter(context, layer); } @@ -138,7 +138,7 @@ void TextureMapperLayer::updateBackingStore(TextureMapper* textureMapper, Graphi TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get()); backingStore->updateContents(textureMapper, image.get(), m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData); - backingStore->setShowDebugBorders(layer->showDebugBorders()); + backingStore->setShowDebugBorders(layer->isShowingDebugBorder()); backingStore->setDebugBorder(m_debugBorderColor, m_debugBorderWidth); m_state.needsDisplay = false; @@ -223,12 +223,12 @@ IntRect TextureMapperLayer::intermediateSurfaceRect(const TransformationMatrix& } #if ENABLE(CSS_FILTERS) - if (m_state.filters.hasOutsets()) { + if (m_filters.hasOutsets()) { int leftOutset; int topOutset; int bottomOutset; int rightOutset; - m_state.filters.getOutsets(topOutset, rightOutset, bottomOutset, leftOutset); + m_filters.getOutsets(topOutset, rightOutset, bottomOutset, leftOutset); IntRect unfilteredTargetRect(rect); rect.move(std::max(0, -leftOutset), std::max(0, -topOutset)); rect.expand(leftOutset + rightOutset, topOutset + bottomOutset); @@ -262,7 +262,7 @@ TextureMapperLayer::ContentsLayerCount TextureMapperLayer::countPotentialLayersW bool TextureMapperLayer::shouldPaintToIntermediateSurface() const { #if ENABLE(CSS_FILTERS) - if (m_state.filters.size()) + if (m_filters.size()) return true; #endif bool hasOpacity = m_opacity < 0.99; @@ -381,7 +381,7 @@ void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options maskTexture = 0; #if ENABLE(CSS_FILTERS) - surface = applyFilters(m_state.filters, options.textureMapper, surface.get(), surfaceRect); + surface = applyFilters(m_filters, options.textureMapper, surface.get(), surfaceRect); #endif options.textureMapper->bindSurface(options.surface.get()); @@ -510,6 +510,13 @@ bool TextureMapperLayer::descendantsOrSelfHaveRunningAnimations() const return false; } +void TextureMapperLayer::applyAnimationsRecursively() +{ + syncAnimations(); + for (size_t i = 0; i < m_children.size(); ++i) + m_children[i]->applyAnimationsRecursively(); +} + void TextureMapperLayer::syncAnimations() { m_animations.apply(this); @@ -517,6 +524,10 @@ void TextureMapperLayer::syncAnimations() setTransform(m_state.transform); if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity)) setOpacity(m_state.opacity); +#if ENABLE(CSS_FILTERS) + if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitFilter)) + setFilters(m_state.filters); +#endif } void TextureMapperLayer::flushCompositingState(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper, int options) @@ -606,7 +617,7 @@ void TextureMapperLayer::drawRepaintCounter(GraphicsContext* context, GraphicsLa cairo_text_extents(cr, repaintCount.data(), &repaintTextExtents); static const int repaintCountBorderWidth = 10; - setSourceRGBAFromColor(cr, layer->showDebugBorders() ? m_debugBorderColor : Color(0, 255, 0, 127)); + setSourceRGBAFromColor(cr, layer->isShowingDebugBorder() ? m_debugBorderColor : Color(0, 255, 0, 127)); cairo_rectangle(cr, 0, 0, repaintTextExtents.width + (repaintCountBorderWidth * 2), repaintTextExtents.height + (repaintCountBorderWidth * 2)); diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h index 5740acf52..5cd959d61 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h @@ -119,6 +119,9 @@ public: IntSize size() const { return IntSize(m_size.width(), m_size.height()); } void setTransform(const TransformationMatrix&); void setOpacity(float value) { m_opacity = value; } +#if ENABLE(CSS_FILTERS) + void setFilters(const FilterOperations& filters) { m_filters = filters; } +#endif void setTextureMapper(TextureMapper* texmap) { m_textureMapper = texmap; } bool descendantsOrSelfHaveRunningAnimations() const; @@ -132,6 +135,7 @@ public: void setScrollPositionDeltaIfNeeded(const FloatSize&); void setDebugBorder(const Color&, float width); + void applyAnimationsRecursively(); private: TextureMapperLayer* rootLayer(); @@ -164,6 +168,9 @@ private: // GraphicsLayerAnimation::Client void setAnimatedTransform(const TransformationMatrix& matrix) { setTransform(matrix); } void setAnimatedOpacity(float opacity) { setOpacity(opacity); } +#if ENABLE(CSS_FILTERS) + virtual void setAnimatedFilters(const FilterOperations& filters) { setFilters(filters); } +#endif void syncAnimations(); bool isVisible() const; @@ -190,6 +197,9 @@ private: TextureMapperPlatformLayer* m_contentsLayer; FloatSize m_size; float m_opacity; +#if ENABLE(CSS_FILTERS) + FilterOperations m_filters; +#endif float m_centerZ; String m_name; bool m_shouldUpdateBackingStoreFromLayer; diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp index 27e786713..c8e1ae461 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp @@ -224,12 +224,12 @@ static void getShaderSpec(TextureMapperShaderManager::ShaderKey key, String& ver STRINGIFY( precision mediump float; uniform sampler2DRect s_sampler; - uniform lowp vec2 s_samplerSize; + uniform lowp vec2 u_samplerSize; uniform lowp float u_opacity; varying highp vec2 v_sourceTexCoord; void main(void) { - lowp vec4 color = texture2DRect(s_sampler, s_samplerSize * v_sourceTexCoord); + lowp vec4 color = texture2DRect(s_sampler, u_samplerSize * v_sourceTexCoord); gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity); } ); diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h index b1f8d6107..380142945 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h @@ -51,7 +51,7 @@ public: TEXMAP_DECLARE_UNIFORM(matrix) TEXMAP_DECLARE_UNIFORM(flip) - TEXMAP_DECLARE_UNIFORM(textureSize) + TEXMAP_DECLARE_UNIFORM(samplerSize) TEXMAP_DECLARE_UNIFORM(opacity) TEXMAP_DECLARE_UNIFORM(color) TEXMAP_DECLARE_UNIFORM(expandedQuadEdgesInScreenSpace) diff --git a/Source/WebCore/platform/graphics/transforms/TransformState.cpp b/Source/WebCore/platform/graphics/transforms/TransformState.cpp index a8fb8f32d..e0a9cec82 100644 --- a/Source/WebCore/platform/graphics/transforms/TransformState.cpp +++ b/Source/WebCore/platform/graphics/transforms/TransformState.cpp @@ -76,13 +76,16 @@ void TransformState::move(LayoutUnit x, LayoutUnit y, TransformAccumulation accu } // FIXME: We transform AffineTransform to TransformationMatrix. This is rather inefficient. -void TransformState::applyTransform(const AffineTransform& transformFromContainer, TransformAccumulation accumulate) +void TransformState::applyTransform(const AffineTransform& transformFromContainer, TransformAccumulation accumulate, bool* wasClamped) { - applyTransform(transformFromContainer.toTransformationMatrix(), accumulate); + applyTransform(transformFromContainer.toTransformationMatrix(), accumulate, wasClamped); } -void TransformState::applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation accumulate) +void TransformState::applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation accumulate, bool* wasClamped) { + if (wasClamped) + *wasClamped = false; + // If we have an accumulated transform from last time, multiply in this transform if (m_accumulatedTransform) { if (m_direction == ApplyTransformDirection) @@ -96,44 +99,53 @@ void TransformState::applyTransform(const TransformationMatrix& transformFromCon if (accumulate == FlattenTransform) { const TransformationMatrix* finalTransform = m_accumulatedTransform ? m_accumulatedTransform.get() : &transformFromContainer; - flattenWithTransform(*finalTransform); + flattenWithTransform(*finalTransform, wasClamped); } m_accumulatingTransform = accumulate == AccumulateTransform; } -void TransformState::flatten() +void TransformState::flatten(bool* wasClamped) { + if (wasClamped) + *wasClamped = false; + if (!m_accumulatedTransform) { m_accumulatingTransform = false; return; } - flattenWithTransform(*m_accumulatedTransform); + flattenWithTransform(*m_accumulatedTransform, wasClamped); } -FloatPoint TransformState::mappedPoint() const +FloatPoint TransformState::mappedPoint(bool* wasClamped) const { + if (wasClamped) + *wasClamped = false; + if (!m_accumulatedTransform) return m_lastPlanarPoint; if (m_direction == ApplyTransformDirection) return m_accumulatedTransform->mapPoint(m_lastPlanarPoint); - return m_accumulatedTransform->inverse().projectPoint(m_lastPlanarPoint); + return m_accumulatedTransform->inverse().projectPoint(m_lastPlanarPoint, wasClamped); } -FloatQuad TransformState::mappedQuad() const +FloatQuad TransformState::mappedQuad(bool* wasClamped) const { + if (wasClamped) + *wasClamped = false; + if (!m_accumulatedTransform) return m_lastPlanarQuad; if (m_direction == ApplyTransformDirection) return m_accumulatedTransform->mapQuad(m_lastPlanarQuad); - return m_accumulatedTransform->inverse().projectQuad(m_lastPlanarQuad); + return m_accumulatedTransform->inverse().projectQuad(m_lastPlanarQuad, wasClamped); } -void TransformState::flattenWithTransform(const TransformationMatrix& t) +void TransformState::flattenWithTransform(const TransformationMatrix& t, bool* wasClamped) { if (m_direction == ApplyTransformDirection) { if (m_mapPoint) @@ -145,7 +157,7 @@ void TransformState::flattenWithTransform(const TransformationMatrix& t) if (m_mapPoint) m_lastPlanarPoint = inverseTransform.projectPoint(m_lastPlanarPoint); if (m_mapQuad) - m_lastPlanarQuad = inverseTransform.projectQuad(m_lastPlanarQuad); + m_lastPlanarQuad = inverseTransform.projectQuad(m_lastPlanarQuad, wasClamped); } // We could throw away m_accumulatedTransform if we wanted to here, but that diff --git a/Source/WebCore/platform/graphics/transforms/TransformState.h b/Source/WebCore/platform/graphics/transforms/TransformState.h index 33eb7e0db..f34295f39 100644 --- a/Source/WebCore/platform/graphics/transforms/TransformState.h +++ b/Source/WebCore/platform/graphics/transforms/TransformState.h @@ -81,20 +81,20 @@ public: } void move(LayoutUnit x, LayoutUnit y, TransformAccumulation = FlattenTransform); - void applyTransform(const AffineTransform& transformFromContainer, TransformAccumulation = FlattenTransform); - void applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation = FlattenTransform); - void flatten(); + void applyTransform(const AffineTransform& transformFromContainer, TransformAccumulation = FlattenTransform, bool* wasClamped = 0); + void applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation = FlattenTransform, bool* wasClamped = 0); + void flatten(bool* wasClamped = 0); // Return the coords of the point or quad in the last flattened layer FloatPoint lastPlanarPoint() const { return m_lastPlanarPoint; } FloatQuad lastPlanarQuad() const { return m_lastPlanarQuad; } // Return the point or quad mapped through the current transform - FloatPoint mappedPoint() const; - FloatQuad mappedQuad() const; + FloatPoint mappedPoint(bool* wasClamped = 0) const; + FloatQuad mappedQuad(bool* wasClamped = 0) const; private: - void flattenWithTransform(const TransformationMatrix&); + void flattenWithTransform(const TransformationMatrix&, bool* wasClamped); FloatPoint m_lastPlanarPoint; FloatQuad m_lastPlanarQuad; diff --git a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp index 495b15f8b..a2fb7b687 100644 --- a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp +++ b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp @@ -589,7 +589,7 @@ FloatPoint TransformationMatrix::projectPoint(const FloatPoint& p, bool* clamped return FloatPoint(static_cast<float>(outX), static_cast<float>(outY)); } -FloatQuad TransformationMatrix::projectQuad(const FloatQuad& q) const +FloatQuad TransformationMatrix::projectQuad(const FloatQuad& q, bool* clamped) const { FloatQuad projectedQuad; @@ -603,6 +603,9 @@ FloatQuad TransformationMatrix::projectQuad(const FloatQuad& q) const projectedQuad.setP3(projectPoint(q.p3(), &clamped3)); projectedQuad.setP4(projectPoint(q.p4(), &clamped4)); + if (clamped) + *clamped = clamped1 || clamped2 || clamped3 || clamped4; + // If all points on the quad had w < 0, then the entire quad would not be visible to the projected surface. bool everythingWasClipped = clamped1 && clamped2 && clamped3 && clamped4; if (everythingWasClipped) @@ -727,24 +730,22 @@ TransformationMatrix& TransformationMatrix::scale3d(double sx, double sy, double TransformationMatrix& TransformationMatrix::rotate3d(double x, double y, double z, double angle) { - // Angles are in degrees. Switch to radians. - angle = deg2rad(angle); - - double sinTheta = sin(angle); - double cosTheta = cos(angle); - // Normalize the axis of rotation double length = sqrt(x * x + y * y + z * z); if (length == 0) { - // bad vector, just use something reasonable - x = 0; - y = 0; - z = 1; + // A direction vector that cannot be normalized, such as [0, 0, 0], will cause the rotation to not be applied. + return *this; } else if (length != 1) { x /= length; y /= length; z /= length; } + + // Angles are in degrees. Switch to radians. + angle = deg2rad(angle); + + double sinTheta = sin(angle); + double cosTheta = cos(angle); TransformationMatrix mat; @@ -970,6 +971,149 @@ TransformationMatrix TransformationMatrix::rectToRect(const FloatRect& from, con // TransformationMatrix& TransformationMatrix::multiply(const TransformationMatrix& mat) { +#if CPU(APPLE_ARMV7S) + double* leftMatrix = &(m_matrix[0][0]); + const double* rightMatrix = &(mat.m_matrix[0][0]); + asm volatile (// First row of leftMatrix. + "mov r3, %[leftMatrix]\n\t" + "vld1.64 { d16-d19 }, [%[leftMatrix], :128]!\n\t" + "vld1.64 { d0-d3}, [%[rightMatrix], :128]!\n\t" + "vmul.f64 d4, d0, d16\n\t" + "vld1.64 { d20-d23 }, [%[leftMatrix], :128]!\n\t" + "vmla.f64 d4, d1, d20\n\t" + "vld1.64 { d24-d27 }, [%[leftMatrix], :128]!\n\t" + "vmla.f64 d4, d2, d24\n\t" + "vld1.64 { d28-d31 }, [%[leftMatrix], :128]!\n\t" + "vmla.f64 d4, d3, d28\n\t" + + "vmul.f64 d5, d0, d17\n\t" + "vmla.f64 d5, d1, d21\n\t" + "vmla.f64 d5, d2, d25\n\t" + "vmla.f64 d5, d3, d29\n\t" + + "vmul.f64 d6, d0, d18\n\t" + "vmla.f64 d6, d1, d22\n\t" + "vmla.f64 d6, d2, d26\n\t" + "vmla.f64 d6, d3, d30\n\t" + + "vmul.f64 d7, d0, d19\n\t" + "vmla.f64 d7, d1, d23\n\t" + "vmla.f64 d7, d2, d27\n\t" + "vmla.f64 d7, d3, d31\n\t" + "vld1.64 { d0-d3}, [%[rightMatrix], :128]!\n\t" + "vst1.64 { d4-d7 }, [r3, :128]!\n\t" + + // Second row of leftMatrix. + "vmul.f64 d4, d0, d16\n\t" + "vmla.f64 d4, d1, d20\n\t" + "vmla.f64 d4, d2, d24\n\t" + "vmla.f64 d4, d3, d28\n\t" + + "vmul.f64 d5, d0, d17\n\t" + "vmla.f64 d5, d1, d21\n\t" + "vmla.f64 d5, d2, d25\n\t" + "vmla.f64 d5, d3, d29\n\t" + + "vmul.f64 d6, d0, d18\n\t" + "vmla.f64 d6, d1, d22\n\t" + "vmla.f64 d6, d2, d26\n\t" + "vmla.f64 d6, d3, d30\n\t" + + "vmul.f64 d7, d0, d19\n\t" + "vmla.f64 d7, d1, d23\n\t" + "vmla.f64 d7, d2, d27\n\t" + "vmla.f64 d7, d3, d31\n\t" + "vld1.64 { d0-d3}, [%[rightMatrix], :128]!\n\t" + "vst1.64 { d4-d7 }, [r3, :128]!\n\t" + + // Third row of leftMatrix. + "vmul.f64 d4, d0, d16\n\t" + "vmla.f64 d4, d1, d20\n\t" + "vmla.f64 d4, d2, d24\n\t" + "vmla.f64 d4, d3, d28\n\t" + + "vmul.f64 d5, d0, d17\n\t" + "vmla.f64 d5, d1, d21\n\t" + "vmla.f64 d5, d2, d25\n\t" + "vmla.f64 d5, d3, d29\n\t" + + "vmul.f64 d6, d0, d18\n\t" + "vmla.f64 d6, d1, d22\n\t" + "vmla.f64 d6, d2, d26\n\t" + "vmla.f64 d6, d3, d30\n\t" + + "vmul.f64 d7, d0, d19\n\t" + "vmla.f64 d7, d1, d23\n\t" + "vmla.f64 d7, d2, d27\n\t" + "vmla.f64 d7, d3, d31\n\t" + "vld1.64 { d0-d3}, [%[rightMatrix], :128]\n\t" + "vst1.64 { d4-d7 }, [r3, :128]!\n\t" + + // Fourth and last row of leftMatrix. + "vmul.f64 d4, d0, d16\n\t" + "vmla.f64 d4, d1, d20\n\t" + "vmla.f64 d4, d2, d24\n\t" + "vmla.f64 d4, d3, d28\n\t" + + "vmul.f64 d5, d0, d17\n\t" + "vmla.f64 d5, d1, d21\n\t" + "vmla.f64 d5, d2, d25\n\t" + "vmla.f64 d5, d3, d29\n\t" + + "vmul.f64 d6, d0, d18\n\t" + "vmla.f64 d6, d1, d22\n\t" + "vmla.f64 d6, d2, d26\n\t" + "vmla.f64 d6, d3, d30\n\t" + + "vmul.f64 d7, d0, d19\n\t" + "vmla.f64 d7, d1, d23\n\t" + "vmla.f64 d7, d2, d27\n\t" + "vmla.f64 d7, d3, d31\n\t" + "vst1.64 { d4-d7 }, [r3, :128]\n\t" + : [leftMatrix]"+r"(leftMatrix), [rightMatrix]"+r"(rightMatrix) + : + : "memory", "r3", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"); +#elif CPU(ARM_VFP) && PLATFORM(IOS) + +#define MATRIX_MULTIPLY_ONE_LINE \ + "vldmia.64 %[rightMatrix]!, { d0-d3}\n\t" \ + "vmul.f64 d4, d0, d16\n\t" \ + "vmla.f64 d4, d1, d20\n\t" \ + "vmla.f64 d4, d2, d24\n\t" \ + "vmla.f64 d4, d3, d28\n\t" \ + \ + "vmul.f64 d5, d0, d17\n\t" \ + "vmla.f64 d5, d1, d21\n\t" \ + "vmla.f64 d5, d2, d25\n\t" \ + "vmla.f64 d5, d3, d29\n\t" \ + \ + "vmul.f64 d6, d0, d18\n\t" \ + "vmla.f64 d6, d1, d22\n\t" \ + "vmla.f64 d6, d2, d26\n\t" \ + "vmla.f64 d6, d3, d30\n\t" \ + \ + "vmul.f64 d7, d0, d19\n\t" \ + "vmla.f64 d7, d1, d23\n\t" \ + "vmla.f64 d7, d2, d27\n\t" \ + "vmla.f64 d7, d3, d31\n\t" \ + "vstmia.64 %[leftMatrix]!, { d4-d7 }\n\t" + + double* leftMatrix = &(m_matrix[0][0]); + const double* rightMatrix = &(mat.m_matrix[0][0]); + // We load the full m_matrix at once in d16-d31. + asm volatile("vldmia.64 %[leftMatrix], { d16-d31 }\n\t" + : + : [leftMatrix]"r"(leftMatrix) + : "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"); + for (unsigned i = 0; i < 4; ++i) { + asm volatile(MATRIX_MULTIPLY_ONE_LINE + : [leftMatrix]"+r"(leftMatrix), [rightMatrix]"+r"(rightMatrix) + : + : "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7"); + } +#undef MATRIX_MULTIPLY_ONE_LINE + +#else Matrix4 tmp; tmp[0][0] = (mat.m_matrix[0][0] * m_matrix[0][0] + mat.m_matrix[0][1] * m_matrix[1][0] @@ -1009,6 +1153,7 @@ TransformationMatrix& TransformationMatrix::multiply(const TransformationMatrix& + mat.m_matrix[3][2] * m_matrix[2][3] + mat.m_matrix[3][3] * m_matrix[3][3]); setMatrix(tmp); +#endif return *this; } diff --git a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h index 9eda74608..49e4b0796 100644 --- a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h +++ b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h @@ -72,7 +72,11 @@ class FloatQuad; class TransformationMatrix { WTF_MAKE_FAST_ALLOCATED; public: +#if CPU(APPLE_ARMV7S) + typedef double Matrix4[4][4] __attribute__((aligned (16))); +#else typedef double Matrix4[4][4]; +#endif TransformationMatrix() { makeIdentity(); } TransformationMatrix(const AffineTransform& t); @@ -166,7 +170,7 @@ public: // with the destination plane. FloatPoint projectPoint(const FloatPoint&, bool* clamped = 0) const; // Projects the four corners of the quad - FloatQuad projectQuad(const FloatQuad&) const; + FloatQuad projectQuad(const FloatQuad&, bool* clamped = 0) const; // Projects the four corners of the quad and takes a bounding box, // while sanitizing values created when the w component is negative. FractionalLayoutRect clampedBoundsOfProjectedQuad(const FloatQuad&) const; diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp index 72323518f..f2125c78f 100644 --- a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp +++ b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp @@ -148,26 +148,6 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri return SimpleFontData::create(FontPlatformData(hfont, scaledSize, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()), isCustomFont(), false); } -PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->smallCaps) - m_derivedFontData->smallCaps = createScaledFontData(fontDescription, cSmallCapsFontSizeMultiplier); - - return m_derivedFontData->smallCaps; -} - -PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->emphasisMark) - m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - - return m_derivedFontData->emphasisMark; -} - bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { // FIXME: Support custom fonts. diff --git a/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp b/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp index 5925c7aa9..842fad5f3 100644 --- a/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp @@ -75,26 +75,6 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri return SimpleFontData::create(*result); } -PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->smallCaps) - m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - - return m_derivedFontData->smallCaps; -} - -PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->emphasisMark) - m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - - return m_derivedFontData->emphasisMark; -} - DWORD getKnownFontCodePages(const wchar_t* family); bool SimpleFontData::containsCharacters(const UChar* characters, int length) const diff --git a/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp index e08a1540c..a58d3e512 100644 --- a/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp +++ b/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp @@ -98,26 +98,6 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri return SimpleFontData::create(platformData, isCustomFont(), false); } -PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->smallCaps) - m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - - return m_derivedFontData->smallCaps; -} - -PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->emphasisMark) - m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - - return m_derivedFontData->emphasisMark; -} - bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { // FIXME: We will need to implement this to load non-ASCII encoding sites |