diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-07-11 13:45:28 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-07-11 13:45:28 +0200 |
commit | d6a599dbc9d824a462b2b206316e102bf8136446 (patch) | |
tree | ecb257a5e55b2239d74b90fdad62fccd661cf286 /Source/WebCore/platform | |
parent | 3ccc3a85f09a83557b391aae380d3bf5f81a2911 (diff) |
Imported WebKit commit 8ff1f22783a32de82fee915abd55bd1b298f2644 (http://svn.webkit.org/repository/webkit/trunk@122325)
New snapshot that should work with the latest Qt build system changes
Diffstat (limited to 'Source/WebCore/platform')
279 files changed, 6908 insertions, 4340 deletions
diff --git a/Source/WebCore/platform/ContextMenuItem.h b/Source/WebCore/platform/ContextMenuItem.h index 697379875..9d367446e 100644 --- a/Source/WebCore/platform/ContextMenuItem.h +++ b/Source/WebCore/platform/ContextMenuItem.h @@ -134,7 +134,6 @@ namespace WebCore { ContextMenuItemTagRightToLeft, ContextMenuItemTagPDFSinglePageScrolling, ContextMenuItemTagPDFFacingPagesScrolling, - ContextMenuItemTagDictationAlternative, #if ENABLE(INSPECTOR) ContextMenuItemTagInspectElement, #endif @@ -164,6 +163,7 @@ namespace WebCore { ContextMenuItemTagEnterVideoFullscreen, ContextMenuItemTagMediaPlayPause, ContextMenuItemTagMediaMute, + ContextMenuItemTagDictationAlternative, ContextMenuItemBaseCustomTag = 5000, ContextMenuItemCustomTagNoAction = 5998, ContextMenuItemLastCustomTag = 5999, diff --git a/Source/WebCore/platform/FileSystem.h b/Source/WebCore/platform/FileSystem.h index b3c259a97..a6b3a675f 100644 --- a/Source/WebCore/platform/FileSystem.h +++ b/Source/WebCore/platform/FileSystem.h @@ -71,6 +71,10 @@ typedef struct _GFileIOStream GFileIOStream; typedef struct _GModule GModule; #endif +#if PLATFORM(EFL) +typedef struct _Eina_Module Eina_Module; +#endif + namespace WebCore { // PlatformModule @@ -78,6 +82,8 @@ namespace WebCore { typedef HMODULE PlatformModule; #elif PLATFORM(GTK) typedef GModule* PlatformModule; +#elif PLATFORM(EFL) +typedef Eina_Module* PlatformModule; #elif PLATFORM(QT) #if defined(Q_WS_MAC) typedef CFBundleRef PlatformModule; diff --git a/Source/WebCore/platform/FractionalLayoutUnit.h b/Source/WebCore/platform/FractionalLayoutUnit.h index d201e122b..21c526410 100644 --- a/Source/WebCore/platform/FractionalLayoutUnit.h +++ b/Source/WebCore/platform/FractionalLayoutUnit.h @@ -86,6 +86,14 @@ public: #endif FractionalLayoutUnit(const FractionalLayoutUnit& value) { m_value = value.rawValue(); } + static FractionalLayoutUnit fromFloatCeil(float value) + { + REPORT_OVERFLOW(isInBounds(value)); + FractionalLayoutUnit v; + v.m_value = ceilf(value * kFixedPointDenominator); + return v; + } + #if ENABLE(SUBPIXEL_LAYOUT) int toInt() const { return m_value / kFixedPointDenominator; } float toFloat() const { return static_cast<float>(m_value) / kFixedPointDenominator; } @@ -153,7 +161,7 @@ public: return toInt(); } - static float epsilon() { return 1 / kFixedPointDenominator; } + static float epsilon() { return 1.0f / kFixedPointDenominator; } static const FractionalLayoutUnit max() { FractionalLayoutUnit m; @@ -168,15 +176,15 @@ public: } private: - bool isInBounds(int value) + static bool isInBounds(int value) { return ::abs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator; } - bool isInBounds(unsigned value) + static bool isInBounds(unsigned value) { return value <= static_cast<unsigned>(std::numeric_limits<int>::max()) / kFixedPointDenominator; } - bool isInBounds(double value) + static bool isInBounds(double value) { return ::fabs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator; } diff --git a/Source/WebCore/platform/Length.cpp b/Source/WebCore/platform/Length.cpp index 086f2218d..9d93cc69f 100644 --- a/Source/WebCore/platform/Length.cpp +++ b/Source/WebCore/platform/Length.cpp @@ -201,7 +201,29 @@ Length::Length(PassRefPtr<CalculationValue> calc) { m_intValue = calcHandles().insert(calc); } + +Length Length::blendCalculation(const Length& from, double progress) const +{ + if (progress <= 0.0) + return from; + + if (progress >= 1.0) + return *this; + + // FIXME: https://webkit.org/b/90037 - some of these allocations can be eliminated + OwnPtr<CalcExpressionNode> startScale = adoptPtr(new CalcExpressionNumber(1.0 - progress)); + OwnPtr<CalcExpressionNode> startLength = adoptPtr(new CalcExpressionLength(from)); + OwnPtr<CalcExpressionNode> startNode = adoptPtr(new CalcExpressionBinaryOperation(startScale.release(), startLength.release(), CalcMultiply)); + OwnPtr<CalcExpressionNode> endScale = adoptPtr(new CalcExpressionNumber(progress)); + OwnPtr<CalcExpressionNode> endLength = adoptPtr(new CalcExpressionLength(*this)); + OwnPtr<CalcExpressionNode> endNode = adoptPtr(new CalcExpressionBinaryOperation(endScale.release(), endLength.release(), CalcMultiply)); + + OwnPtr<CalcExpressionNode> blend = adoptPtr(new CalcExpressionBinaryOperation(startNode.release(), endNode.release(), CalcAdd)); + + return Length(CalculationValue::create(blend.release(), CalculationRangeAll)); +} + PassRefPtr<CalculationValue> Length::calculationValue() const { ASSERT(isCalculated()); diff --git a/Source/WebCore/platform/Length.h b/Source/WebCore/platform/Length.h index 1815130a9..7171e3494 100644 --- a/Source/WebCore/platform/Length.h +++ b/Source/WebCore/platform/Length.h @@ -230,15 +230,14 @@ public: Length blend(const Length& from, double progress) const { // Blend two lengths to produce a new length that is in between them. Used for animation. + if (from.type() == Calculated || type() == Calculated) + return blendCalculation(from, progress); + if (!from.isZero() && !isZero() && from.type() != type()) return *this; if (from.isZero() && isZero()) return *this; - - // FIXME http://webkit.org/b/86160 - Blending doesn't work with calculated expressions - if (from.type() == Calculated || type() == Calculated) - return *this; LengthType resultType = type(); if (isZero()) @@ -293,6 +292,8 @@ private: incrementCalculatedRef(); } + Length blendCalculation(const Length& from, double progress) const; + int calculationHandle() const { ASSERT(isCalculated()); diff --git a/Source/WebCore/platform/LocalizedStrings.cpp b/Source/WebCore/platform/LocalizedStrings.cpp index b140f9c07..9c4bdf3f9 100644 --- a/Source/WebCore/platform/LocalizedStrings.cpp +++ b/Source/WebCore/platform/LocalizedStrings.cpp @@ -244,7 +244,7 @@ String contextMenuItemTagSearchInSpotlight() String contextMenuItemTagSearchWeb() { -#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) RetainPtr<CFStringRef> searchProviderName(AdoptCF, wkCopyDefaultSearchProviderDisplayName()); return formatLocalizedString(WEB_UI_STRING("Search with %@", "Search with search provider context menu item with provider name inserted"), searchProviderName.get()); #else diff --git a/Source/WebCore/platform/Logging.cpp b/Source/WebCore/platform/Logging.cpp index 34637a7cc..d97e1045a 100644 --- a/Source/WebCore/platform/Logging.cpp +++ b/Source/WebCore/platform/Logging.cpp @@ -27,6 +27,8 @@ #include "Logging.h" #include "PlatformString.h" +#if !LOG_DISABLED + namespace WebCore { WTFLogChannel LogNotYetImplemented = { 0x00000001, "WebCoreLogLevel", WTFLogChannelOff }; @@ -63,6 +65,7 @@ WTFLogChannel LogFileAPI = { 0x10000000, "WebCoreLogLevel", WTFLogChan WTFLogChannel LogWebAudio = { 0x20000000, "WebCoreLogLevel", WTFLogChannelOff }; WTFLogChannel LogCompositing = { 0x40000000, "WebCoreLogLevel", WTFLogChannelOff }; +WTFLogChannel LogGamepad = { 0x80000000, "WebCoreLogLevel", WTFLogChannelOff }; WTFLogChannel* getChannelFromName(const String& channelName) @@ -145,7 +148,12 @@ WTFLogChannel* getChannelFromName(const String& channelName) if (equalIgnoringCase(channelName, String("Compositing"))) return &LogCompositing; + if (equalIgnoringCase(channelName, String("Gamepad"))) + return &LogGamepad; + return 0; } } + +#endif // !LOG_DISABLED diff --git a/Source/WebCore/platform/Logging.h b/Source/WebCore/platform/Logging.h index 1af1c04ab..cde0ce851 100644 --- a/Source/WebCore/platform/Logging.h +++ b/Source/WebCore/platform/Logging.h @@ -29,6 +29,8 @@ #include <wtf/Assertions.h> #include <wtf/Forward.h> +#if !LOG_DISABLED + #ifndef LOG_CHANNEL_PREFIX #define LOG_CHANNEL_PREFIX Log #endif @@ -61,9 +63,12 @@ namespace WebCore { extern WTFLogChannel LogFileAPI; extern WTFLogChannel LogWebAudio; extern WTFLogChannel LogCompositing; + extern WTFLogChannel LogGamepad; void initializeLoggingChannelsIfNecessary(); WTFLogChannel* getChannelFromName(const String& channelName); } +#endif // !LOG_DISABLED + #endif // Logging_h diff --git a/Source/WebCore/platform/MemoryPressureHandler.cpp b/Source/WebCore/platform/MemoryPressureHandler.cpp index 982876d05..15e680862 100644 --- a/Source/WebCore/platform/MemoryPressureHandler.cpp +++ b/Source/WebCore/platform/MemoryPressureHandler.cpp @@ -42,7 +42,7 @@ MemoryPressureHandler::MemoryPressureHandler() { } -#if !PLATFORM(MAC) || defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) || PLATFORM(IOS) +#if !PLATFORM(MAC) || defined(BUILDING_ON_SNOW_LEOPARD) || PLATFORM(IOS) void MemoryPressureHandler::install() { } void MemoryPressureHandler::uninstall() { } diff --git a/Source/WebCore/platform/PlatformScreen.h b/Source/WebCore/platform/PlatformScreen.h index e723308d3..df989a10b 100644 --- a/Source/WebCore/platform/PlatformScreen.h +++ b/Source/WebCore/platform/PlatformScreen.h @@ -53,7 +53,7 @@ namespace WebCore { FloatRect screenRect(Widget*); FloatRect screenAvailableRect(Widget*); // type can be "monitor" or the name of a profile such as "sRGB" or "Adobe RGB". - void screenColorProfile(Widget*, const String& type, ColorProfile&); + void screenColorProfile(Widget*, ColorProfile&); #if PLATFORM(MAC) NSScreen *screenForWindow(NSWindow *); diff --git a/Source/WebCore/platform/SuddenTermination.h b/Source/WebCore/platform/SuddenTermination.h index 810fea731..b66ae1abc 100644 --- a/Source/WebCore/platform/SuddenTermination.h +++ b/Source/WebCore/platform/SuddenTermination.h @@ -34,7 +34,7 @@ namespace WebCore { void disableSuddenTermination(); void enableSuddenTermination(); -#if (!PLATFORM(MAC) || defined(BUILDING_ON_LEOPARD)) && !PLATFORM(CHROMIUM) +#if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) inline void disableSuddenTermination() { } inline void enableSuddenTermination() { } #endif diff --git a/Source/WebCore/platform/audio/AudioFIFO.cpp b/Source/WebCore/platform/audio/AudioFIFO.cpp new file mode 100644 index 000000000..961814189 --- /dev/null +++ b/Source/WebCore/platform/audio/AudioFIFO.cpp @@ -0,0 +1,144 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY 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" + +#if ENABLE(WEB_AUDIO) + +#include "AudioFIFO.h" + +namespace WebCore { + +AudioFIFO::AudioFIFO(unsigned numberOfChannels, size_t fifoLength) + : m_fifoAudioBus(numberOfChannels, fifoLength) + , m_fifoLength(fifoLength) + , m_framesInFifo(0) + , m_readIndex(0) + , m_writeIndex(0) +{ +} + +void AudioFIFO::consume(AudioBus* destination, size_t framesToConsume) +{ + bool isGood = destination && (framesToConsume <= m_fifoLength) && (framesToConsume <= m_framesInFifo) && (destination->length() >= framesToConsume); + ASSERT(isGood); + if (!isGood) + return; + + // Copy the requested number of samples to the destination. + + size_t part1Length; + size_t part2Length; + findWrapLengths(m_readIndex, framesToConsume, part1Length, part2Length); + + size_t numberOfChannels = m_fifoAudioBus.numberOfChannels(); + + for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { + float* destinationData = destination->channel(channelIndex)->mutableData(); + const float* sourceData = m_fifoAudioBus.channel(channelIndex)->data(); + + bool isCopyGood = ((m_readIndex < m_fifoLength) + && (m_readIndex + part1Length) <= m_fifoLength + && (part1Length <= destination->length()) + && (part1Length + part2Length) <= destination->length()); + ASSERT(isCopyGood); + if (!isCopyGood) + return; + + memcpy(destinationData, sourceData + m_readIndex, part1Length * sizeof(*sourceData)); + // Handle wrap around of the FIFO, if needed. + if (part2Length) + memcpy(destinationData + part1Length, sourceData, part2Length * sizeof(*sourceData)); + } + m_readIndex = updateIndex(m_readIndex, framesToConsume); + ASSERT(m_framesInFifo >= framesToConsume); + m_framesInFifo -= framesToConsume; +} + +void AudioFIFO::push(const AudioBus* sourceBus) +{ + // Copy the sourceBus into the FIFO buffer. + + bool isGood = sourceBus && (m_framesInFifo + sourceBus->length() <= m_fifoLength); + if (!isGood) + return; + + size_t sourceLength = sourceBus->length(); + size_t part1Length; + size_t part2Length; + findWrapLengths(m_writeIndex, sourceLength, part1Length, part2Length); + + size_t numberOfChannels = m_fifoAudioBus.numberOfChannels(); + + for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { + float* destination = m_fifoAudioBus.channel(channelIndex)->mutableData(); + const float* source = sourceBus->channel(channelIndex)->data(); + + bool isCopyGood = ((m_writeIndex < m_fifoLength) + && (m_writeIndex + part1Length) <= m_fifoLength + && part2Length < m_fifoLength + && part1Length + part2Length <= sourceLength); + ASSERT(isCopyGood); + if (!isCopyGood) + return; + + memcpy(destination + m_writeIndex, source, part1Length * sizeof(*destination)); + + // Handle wrap around of the FIFO, if needed. + if (part2Length) + memcpy(destination, source + part1Length, part2Length * sizeof(*destination)); + } + + m_framesInFifo += sourceLength; + ASSERT(m_framesInFifo <= m_fifoLength); + m_writeIndex = updateIndex(m_writeIndex, sourceLength); +} + +void AudioFIFO::findWrapLengths(size_t index, size_t size, size_t& part1Length, size_t& part2Length) +{ + ASSERT(index < m_fifoLength && size <= m_fifoLength); + if (index < m_fifoLength && size <= m_fifoLength) { + if (index + size > m_fifoLength) { + // Need to wrap. Figure out the length of each piece. + part1Length = m_fifoLength - index; + part2Length = size - part1Length; + } else { + // No wrap needed. + part1Length = size; + part2Length = 0; + } + } else { + // Invalid values for index or size. Set the part lengths to zero so nothing is copied. + part1Length = 0; + part2Length = 0; + } +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/Source/WebCore/platform/audio/AudioFIFO.h b/Source/WebCore/platform/audio/AudioFIFO.h new file mode 100644 index 000000000..f526f22e6 --- /dev/null +++ b/Source/WebCore/platform/audio/AudioFIFO.h @@ -0,0 +1,75 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY 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 AudioFIFO_h +#define AudioFIFO_h + +#include "AudioBus.h" + +namespace WebCore { + +class AudioFIFO { +public: + // Create a FIFO large enough to hold |fifoLength| frames of data of |numberOfChannels| channels. + AudioFIFO(unsigned numberOfChannels, size_t fifoLength); + + // Push the data from the bus into the FIFO. + void push(const AudioBus*); + + // Consume |framesToConsume| frames of data from the FIFO and put them in |destination|. The + // corresponding frames are removed from the FIFO. + void consume(AudioBus* destination, size_t framesToConsume); + + // Number of frames of data that are currently in the FIFO. + size_t framesInFifo() const { return m_framesInFifo; } + +private: + // Update the FIFO index by the step, with appropriate wrapping around the endpoint. + int updateIndex(int index, int step) { return (index + step) % m_fifoLength; } + + void findWrapLengths(size_t index, size_t providerSize, size_t& part1Length, size_t& part2Length); + + // The FIFO itself. In reality, the FIFO is a circular buffer. + AudioBus m_fifoAudioBus; + + // The total available space in the FIFO. + size_t m_fifoLength; + + // The number of actual elements in the FIFO + size_t m_framesInFifo; + + // Where to start reading from the FIFO. + size_t m_readIndex; + + // Where to start writing to the FIFO. + size_t m_writeIndex; +}; + +} // namespace WebCore + +#endif // AudioFIFO.h diff --git a/Source/WebCore/platform/audio/AudioPullFIFO.cpp b/Source/WebCore/platform/audio/AudioPullFIFO.cpp index 03e89deba..261156709 100644 --- a/Source/WebCore/platform/audio/AudioPullFIFO.cpp +++ b/Source/WebCore/platform/audio/AudioPullFIFO.cpp @@ -36,11 +36,7 @@ namespace WebCore { AudioPullFIFO::AudioPullFIFO(AudioSourceProvider& audioProvider, unsigned numberOfChannels, size_t fifoLength, size_t providerSize) : m_provider(audioProvider) - , m_fifoAudioBus(numberOfChannels, fifoLength) - , m_fifoLength(fifoLength) - , m_framesInFifo(0) - , m_readIndex(0) - , m_writeIndex(0) + , m_fifo(numberOfChannels, fifoLength) , m_providerSize(providerSize) , m_tempBus(numberOfChannels, providerSize) { @@ -48,64 +44,15 @@ AudioPullFIFO::AudioPullFIFO(AudioSourceProvider& audioProvider, unsigned number void AudioPullFIFO::consume(AudioBus* destination, size_t framesToConsume) { - bool isGood = destination && (framesToConsume <= m_fifoLength); - ASSERT(isGood); - if (!isGood) + if (!destination) return; - if (framesToConsume > m_framesInFifo) { + if (framesToConsume > m_fifo.framesInFifo()) { // We don't have enough data in the FIFO to fulfill the request. Ask for more data. - fillBuffer(framesToConsume - m_framesInFifo); + fillBuffer(framesToConsume - m_fifo.framesInFifo()); } - // We have enough data now. Copy the requested number of samples to the destination. - - size_t part1Length; - size_t part2Length; - findWrapLengths(m_readIndex, framesToConsume, part1Length, part2Length); - - size_t numberOfChannels = m_fifoAudioBus.numberOfChannels(); - - for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { - float* destinationData = destination->channel(channelIndex)->mutableData(); - const float* sourceData = m_fifoAudioBus.channel(channelIndex)->data(); - - bool isCopyGood = ((m_readIndex < m_fifoLength) - && (m_readIndex + part1Length) <= m_fifoLength - && (part1Length <= destination->length()) - && (part1Length + part2Length) <= destination->length()); - ASSERT(isCopyGood); - if (!isCopyGood) - return; - - memcpy(destinationData, sourceData + m_readIndex, part1Length * sizeof(*sourceData)); - // Handle wrap around of the FIFO, if needed. - if (part2Length > 0) - memcpy(destinationData + part1Length, sourceData, part2Length * sizeof(*sourceData)); - } - m_readIndex = updateIndex(m_readIndex, framesToConsume); - m_framesInFifo -= framesToConsume; - ASSERT(m_framesInFifo >= 0); -} - -void AudioPullFIFO::findWrapLengths(size_t index, size_t size, size_t& part1Length, size_t& part2Length) -{ - ASSERT(index < m_fifoLength && size <= m_fifoLength); - if (index < m_fifoLength && size <= m_fifoLength) { - if (index + size > m_fifoLength) { - // Need to wrap. Figure out the length of each piece. - part1Length = m_fifoLength - index; - part2Length = size - part1Length; - } else { - // No wrap needed. - part1Length = size; - part2Length = 0; - } - } else { - // Invalid values for index or size. Set the part lengths to zero so nothing is copied. - part1Length = 0; - part2Length = 0; - } + m_fifo.consume(destination, framesToConsume); } void AudioPullFIFO::fillBuffer(size_t numberOfFrames) @@ -117,34 +64,8 @@ void AudioPullFIFO::fillBuffer(size_t numberOfFrames) while (framesProvided < numberOfFrames) { m_provider.provideInput(&m_tempBus, m_providerSize); - size_t part1Length; - size_t part2Length; - findWrapLengths(m_writeIndex, m_providerSize, part1Length, part2Length); - - size_t numberOfChannels = m_fifoAudioBus.numberOfChannels(); - - for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { - float* destination = m_fifoAudioBus.channel(channelIndex)->mutableData(); - const float* source = m_tempBus.channel(channelIndex)->data(); - - bool isCopyGood = (part1Length <= m_providerSize - && (part1Length + part2Length) <= m_providerSize - && (m_writeIndex < m_fifoLength) - && (m_writeIndex + part1Length) <= m_fifoLength - && part2Length < m_fifoLength); - ASSERT(isCopyGood); - if (!isCopyGood) - return; - - memcpy(destination + m_writeIndex, source, part1Length * sizeof(*destination)); - // Handle wrap around of the FIFO, if needed. - if (part2Length > 0) - memcpy(destination, source + part1Length, part2Length * sizeof(*destination)); - } + m_fifo.push(&m_tempBus); - m_framesInFifo += m_providerSize; - ASSERT(m_framesInFifo <= m_fifoLength); - m_writeIndex = updateIndex(m_writeIndex, m_providerSize); framesProvided += m_providerSize; } } diff --git a/Source/WebCore/platform/audio/AudioPullFIFO.h b/Source/WebCore/platform/audio/AudioPullFIFO.h index fac19b9d1..33269ae28 100644 --- a/Source/WebCore/platform/audio/AudioPullFIFO.h +++ b/Source/WebCore/platform/audio/AudioPullFIFO.h @@ -30,6 +30,7 @@ #define AudioPullFIFO_h #include "AudioBus.h" +#include "AudioFIFO.h" #include "AudioSourceProvider.h" namespace WebCore { @@ -52,31 +53,14 @@ public: void consume(AudioBus* destination, size_t framesToConsume); private: - // Update the FIFO index by the step, with appropriate wrapping around the endpoint. - int updateIndex(int index, int step) { return (index + step) % m_fifoLength; } - - void findWrapLengths(size_t index, size_t providerSize, size_t& part1Length, size_t& part2Length); - // Fill the FIFO buffer with at least |numberOfFrames| more data. void fillBuffer(size_t numberOfFrames); // The provider of the data in our FIFO. AudioSourceProvider& m_provider; - // The FIFO itself. In reality, the FIFO is a circular buffer. - AudioBus m_fifoAudioBus; - - // The total available space in the FIFO. - size_t m_fifoLength; - - // The number of actual elements in the FIFO - size_t m_framesInFifo; - - // Where to start reading from the FIFO. - size_t m_readIndex; - - // Where to start writing to the FIFO. - size_t m_writeIndex; + // The actual FIFO + AudioFIFO m_fifo; // Number of frames of data that the provider will produce per call. unsigned int m_providerSize; diff --git a/Source/WebCore/platform/blackberry/LoggingBlackBerry.cpp b/Source/WebCore/platform/blackberry/LoggingBlackBerry.cpp index 994d78ec9..1d665bc92 100644 --- a/Source/WebCore/platform/blackberry/LoggingBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/LoggingBlackBerry.cpp @@ -19,6 +19,8 @@ #include "config.h" #include "Logging.h" +#if !LOG_DISABLED + #include <wtf/text/WTFString.h> namespace WebCore { @@ -53,3 +55,5 @@ void initializeLoggingChannelsIfNecessary() } } // namespace WebCore + +#endif // !LOG_DISABLED diff --git a/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp b/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp index ba8e16bf8..44c6d8ec0 100644 --- a/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp @@ -30,107 +30,19 @@ #include "MIMETypeRegistry.h" #include "NotImplemented.h" +#include <BlackBerryPlatformCommonFunctions.h> +#include <wtf/text/CString.h> namespace WebCore { -struct ExtensionMap { - const char* extension; - const char* mimeType; -}; - -static const ExtensionMap extensionMap[] = { - { "bmp", "image/bmp" }, - { "css", "text/css" }, - { "gif", "image/gif" }, - { "html", "text/html" }, - { "htm", "text/html" }, - { "ico", "image/x-icon" }, - { "jpg", "image/jpeg" }, - { "jpeg", "image/jpeg" }, - { "js", "application/x-javascript" }, - { "mng", "video/x-mng" }, - { "pbm", "image/x-portable-bitmap" }, - { "pgm", "image/x-portable-graymap" }, - { "pdf", "application/pdf" }, - { "png", "image/png" }, - { "ppm", "image/x-portable-pixmap" }, - { "rss", "application/rss+xml" }, - { "svg", "image/svg+xml" }, - { "svgz", "image/svg+xml" }, - { "txt", "text/plain" }, - { "text", "text/plain" }, - { "tiff", "image/tiff" }, - { "tif", "image/tiff" }, - { "xbm", "image/x-xbitmap" }, - { "xml", "text/xml" }, - { "xpm", "image/x-xpm" }, - { "xsl", "text/xsl" }, - { "xhtml", "application/xhtml+xml" }, - { "m4a", "audio/m4a" }, - { "midi", "audio/midi" }, - { "mid", "audio/mid" }, - { "mp3", "audio/mp3" }, - { "wma", "audio/x-ms-wma" }, - { "3gp", "video/3gpp" }, - { "3gpp", "video/3gpp" }, - { "3gpp2", "video/3gpp2" }, - { "3g2", "video/3gpp2" }, - { "3gp2", "video/3gpp2" }, - { "mp4", "video/mp4" }, - { "m4v", "video/m4v" }, - { "avi", "video/x-msvideo" }, - { "mov", "video/quicktime" }, - { "divx", "video/divx" }, - { "mpeg", "video/mpeg" }, - { "sbv", "video/sbv" }, - { "asf", "video/x-ms-asf" }, - { "wm", "video/x-ms-wm" }, - { "wmv", "video/x-ms-wmv" }, - { "wmx", "video/x-ms-wmx" }, - { "wav", "audio/x-wav" }, - { "amr", "audio/amr" }, - { "aac", "audio/aac" }, - { "x-gsm", "audio/x-gsm" }, - { "swf", "application/x-shockwave-flash" }, - { "m3u8", "application/vnd.apple.mpegurl" }, - { "m3url", "audio/mpegurl" }, - { "m3u", "audio/mpegurl" }, - { "flac", "audio/x-flac" }, - { "ogg", "audio/ogg" }, - { "oga", "audio/ogg" }, - // FIXME: wince also maps ttf and otf to text/plain. Should we do that too? - { 0, 0 } -}; - String MIMETypeRegistry::getMIMETypeForExtension(const String& extension) { - String lowerExtension = extension.lower(); - - const ExtensionMap* entry = extensionMap; - while (entry->extension) { - if (lowerExtension == entry->extension) - return entry->mimeType; - ++entry; - } - - return String(); + return String(BlackBerry::Platform::getMIMETypeForExtension(extension.lower().utf8().data()).c_str()); } String MIMETypeRegistry::getPreferredExtensionForMIMEType(const String& type) { - if (type.isEmpty()) - return String(); - - String lowerType = type.lower(); - - const ExtensionMap* entry = extensionMap; - while (entry->mimeType) { - if (lowerType == entry->mimeType) - return entry->extension; - ++entry; - } - - return String(); + return String(BlackBerry::Platform::getPreferredExtensionForMIMEType(type.lower().utf8().data()).c_str()); } bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) diff --git a/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp b/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp index 00244acc7..592539cd4 100644 --- a/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp @@ -64,7 +64,7 @@ FloatRect screenRect(Widget* widget) return FloatRect(FloatPoint(), FloatSize(IntSize(BlackBerry::Platform::Graphics::Screen::primaryScreen()->size()))); } -void screenColorProfile(Widget*, const String&, ColorProfile&) +void screenColorProfile(Widget*, ColorProfile&) { notImplemented(); } diff --git a/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp b/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp index a85c08973..46f33dafd 100644 --- a/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp +++ b/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp @@ -73,11 +73,11 @@ FloatRect screenAvailableRect(Widget* widget) return PlatformSupport::screenAvailableRect(widget); } -void screenColorProfile(Widget*, const String& type, ColorProfile& toProfile) +void screenColorProfile(Widget*, ColorProfile& toProfile) { // FIXME: Add support for multiple monitors. WebKit::WebVector<char> profile; - WebKit::Platform::current()->screenColorProfile(WebKit::WebString(type), &profile); + WebKit::Platform::current()->screenColorProfile(&profile); toProfile.append(profile.data(), profile.size()); } diff --git a/Source/WebCore/platform/chromium/support/WebTransformationMatrix.cpp b/Source/WebCore/platform/chromium/support/WebTransformationMatrix.cpp index eefd154e8..cb259f051 100644 --- a/Source/WebCore/platform/chromium/support/WebTransformationMatrix.cpp +++ b/Source/WebCore/platform/chromium/support/WebTransformationMatrix.cpp @@ -422,16 +422,6 @@ TransformationMatrix WebTransformationMatrix::toWebCoreTransform() const return m_private; } -FloatRect WebTransformationMatrix::mapRect(const FloatRect& rect) const -{ - return m_private.mapRect(rect); -} - -IntRect WebTransformationMatrix::mapRect(const IntRect& rect) const -{ - return m_private.mapRect(rect); -} - FloatPoint3D WebTransformationMatrix::mapPoint(const FloatPoint3D& p) const { return m_private.mapPoint(p); @@ -447,14 +437,4 @@ IntPoint WebTransformationMatrix::mapPoint(const IntPoint& p) const return m_private.mapPoint(p); } -FloatQuad WebTransformationMatrix::mapQuad(const FloatQuad& quad) const -{ - return m_private.mapQuad(quad); -} - -FloatPoint WebTransformationMatrix::projectPoint(const FloatPoint& p, bool* clamped) const -{ - return m_private.projectPoint(p, clamped); -} - } // namespace WebKit diff --git a/Source/WebCore/platform/efl/BatteryProviderEfl.cpp b/Source/WebCore/platform/efl/BatteryProviderEfl.cpp new file mode 100644 index 000000000..c5d030a3d --- /dev/null +++ b/Source/WebCore/platform/efl/BatteryProviderEfl.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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 "BatteryProviderEfl.h" + +#if ENABLE(BATTERY_STATUS) + +#include "BatteryProviderEflClient.h" +#include "EventNames.h" +#include <E_Ukit.h> +#include <limits> + +namespace WebCore { + +BatteryProviderEfl::BatteryProviderEfl(BatteryProviderEflClient* client) + : m_client(client) + , m_timer(this, &BatteryProviderEfl::timerFired) + , m_batteryStatusRefreshInterval(1.0) +{ +} + +BatteryStatus* BatteryProviderEfl::batteryStatus() const +{ + return m_batteryStatus.get(); +} + +void BatteryProviderEfl::startUpdating() +{ + if (m_timer.isActive()) + return; + + if (!e_dbus_init()) + return; + + if (!e_ukit_init()) { + e_dbus_shutdown(); + return; + } + + m_timer.startRepeating(m_batteryStatusRefreshInterval); +} + +void BatteryProviderEfl::stopUpdating() +{ + m_timer.stop(); + e_ukit_shutdown(); + e_dbus_shutdown(); +} + +void BatteryProviderEfl::setBatteryStatus(const AtomicString& eventType, PassRefPtr<BatteryStatus> batteryStatus) +{ + m_batteryStatus = batteryStatus; + m_client->didChangeBatteryStatus(eventType, m_batteryStatus); +} + +void BatteryProviderEfl::timerFired(Timer<BatteryProviderEfl>* timer) +{ + ASSERT_UNUSED(timer, timer == &m_timer); + E_DBus_Connection* edbusConnection = e_dbus_bus_get(DBUS_BUS_SYSTEM); + if (edbusConnection) + e_upower_get_all_devices(edbusConnection, getBatteryStatus, static_cast<void*>(this)); +} + +void BatteryProviderEfl::getBatteryStatus(void* data, void* replyData, DBusError* dBusError) +{ + E_Ukit_Get_All_Devices_Return* eukitDeviceNames = static_cast<E_Ukit_Get_All_Devices_Return*>(replyData); + if (!eukitDeviceNames || !eukitDeviceNames->strings || dbus_error_is_set(dBusError)) { + dbus_error_free(dBusError); + return; + } + + E_DBus_Connection* edbusConnection = e_dbus_bus_get(DBUS_BUS_SYSTEM); + Eina_List* list; + void* deviceName; + EINA_LIST_FOREACH(eukitDeviceNames->strings, list, deviceName) + e_upower_get_all_properties(edbusConnection, static_cast<char*>(deviceName), setBatteryClient, data); +} + +void BatteryProviderEfl::setBatteryClient(void* data, void* replyData, DBusError* dBusError) +{ + E_Ukit_Get_All_Properties_Return* eukitPropertyNames = static_cast<E_Ukit_Get_All_Properties_Return*>(replyData); + + if (!eukitPropertyNames || dbus_error_is_set(dBusError)) { + dbus_error_free(dBusError); + return; + } + + if (!eukitPropertyNames->properties) + return; + + E_Ukit_Property* property = static_cast<E_Ukit_Property*>(eina_hash_find(eukitPropertyNames->properties, "Type")); + if (!property || property->val.u != E_UPOWER_SOURCE_BATTERY) + return; + + BatteryProviderEfl* client = static_cast<BatteryProviderEfl*>(data); + BatteryStatus* clientBatteryStatus = client->batteryStatus(); + bool charging = false; + bool chargingChanged = false; + static unsigned chargingState = 0; + + property = static_cast<E_Ukit_Property*>(eina_hash_find(eukitPropertyNames->properties, "State")); + if (!property) + return; + if (!clientBatteryStatus || chargingState != property->val.u) { + chargingChanged = true; + chargingState = property->val.u; + (chargingState == E_UPOWER_STATE_FULL || chargingState == E_UPOWER_STATE_CHARGING) ? charging = true : charging = false; + } else + charging = clientBatteryStatus->charging(); + + bool chargingTimeChanged = false; + bool dischargingTimeChanged = false; + double chargingTime = std::numeric_limits<double>::infinity(); + double dischargingTime = std::numeric_limits<double>::infinity(); + + if (charging) { + if (!clientBatteryStatus || clientBatteryStatus->dischargingTime() != std::numeric_limits<double>::infinity()) + dischargingTimeChanged = true; + dischargingTime = std::numeric_limits<double>::infinity(); + property = static_cast<E_Ukit_Property*>(eina_hash_find(eukitPropertyNames->properties, "TimeToFull")); + if (!property) + return; + if (!clientBatteryStatus || clientBatteryStatus->chargingTime() != property->val.x) + chargingTimeChanged = true; + chargingTime = property->val.x; + } else { + if (!clientBatteryStatus || clientBatteryStatus->chargingTime() != std::numeric_limits<double>::infinity()) + chargingTimeChanged = true; + chargingTime = std::numeric_limits<double>::infinity(); + property = static_cast<E_Ukit_Property*>(eina_hash_find(eukitPropertyNames->properties, "TimeToEmpty")); + if (!property) + return; + if (!clientBatteryStatus || clientBatteryStatus->dischargingTime() != property->val.x) + dischargingTimeChanged = true; + dischargingTime = property->val.x; + } + + double level = 0; + bool levelChanged = false; + + property = static_cast<E_Ukit_Property*>(eina_hash_find(eukitPropertyNames->properties, "Percentage")); + if (!property) + return; + if (!clientBatteryStatus || clientBatteryStatus->level() != property->val.d) + levelChanged = true; + level = property->val.d; + + WTF::RefPtr<BatteryStatus> batteryStatus = BatteryStatus::create(charging, chargingTime, dischargingTime, level); + if (chargingChanged) + client->setBatteryStatus(eventNames().chargingchangeEvent, batteryStatus); + if (chargingTimeChanged) + client->setBatteryStatus(eventNames().chargingtimechangeEvent, batteryStatus); + if (dischargingTimeChanged) + client->setBatteryStatus(eventNames().dischargingtimechangeEvent, batteryStatus); + if (levelChanged) + client->setBatteryStatus(eventNames().levelchangeEvent, batteryStatus); +} + +} + +#endif // BATTERY_STATUS + diff --git a/Source/WebCore/platform/efl/BatteryProviderEfl.h b/Source/WebCore/platform/efl/BatteryProviderEfl.h new file mode 100644 index 000000000..bb4bb7f04 --- /dev/null +++ b/Source/WebCore/platform/efl/BatteryProviderEfl.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef BatteryProviderEfl_h +#define BatteryProviderEfl_h + +#if ENABLE(BATTERY_STATUS) + +#include "BatteryClient.h" +#include "BatteryStatus.h" +#include "Timer.h" +#include <wtf/text/AtomicString.h> + +typedef struct DBusError DBusError; + +namespace WebCore { + +class BatteryProviderEflClient; + +class BatteryProviderEfl { +public: + BatteryProviderEfl(BatteryProviderEflClient*); + ~BatteryProviderEfl() { } + + virtual void startUpdating(); + virtual void stopUpdating(); + + void setBatteryStatus(const AtomicString& eventType, PassRefPtr<BatteryStatus>); + BatteryStatus* batteryStatus() const; + +private: + void timerFired(Timer<BatteryProviderEfl>*); + static void getBatteryStatus(void* data, void* replyData, DBusError*); + static void setBatteryClient(void* data, void* replyData, DBusError*); + + BatteryProviderEflClient* m_client; + Timer<BatteryProviderEfl> m_timer; + RefPtr<BatteryStatus> m_batteryStatus; + const double m_batteryStatusRefreshInterval; +}; + +} + +#endif // ENABLE(BATTERY_STATUS) +#endif // BatteryProviderEfl_h + diff --git a/Source/WebCore/platform/efl/BatteryProviderEflClient.h b/Source/WebCore/platform/efl/BatteryProviderEflClient.h new file mode 100644 index 000000000..c3ed8d02c --- /dev/null +++ b/Source/WebCore/platform/efl/BatteryProviderEflClient.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2012 Samsung Electronics. All rights reserved. + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef BatteryProviderEflClient_h +#define BatteryProviderEflClient_h + +#if ENABLE(BATTERY_STATUS) + +#include "BatteryStatus.h" +#include <wtf/text/AtomicString.h> + +namespace WebCore { + +class BatteryProviderEflClient { +public: + virtual void didChangeBatteryStatus(const AtomicString& eventType, PassRefPtr<BatteryStatus>) = 0; +}; + +} // namespace WebCore + +#endif // ENABLE(BATTERY_STATUS) + +#endif // BatteryProviderEflClient_h diff --git a/Source/WebCore/platform/efl/FileSystemEfl.cpp b/Source/WebCore/platform/efl/FileSystemEfl.cpp index c6bff150a..407882279 100644 --- a/Source/WebCore/platform/efl/FileSystemEfl.cpp +++ b/Source/WebCore/platform/efl/FileSystemEfl.cpp @@ -70,7 +70,7 @@ bool unloadModule(PlatformModule module) // caution, closing handle will make memory vanish and any remaining // timer, idler, threads or any other left-over will crash, // maybe just ignore this is a safer solution? - return !dlclose(module); + return eina_module_free(module); } String homeDirectoryPath() @@ -91,6 +91,12 @@ Vector<String> listDirectory(const String& path, const String& filter) const char *f_name; Eina_Iterator* it = eina_file_ls(path.utf8().data()); + // FIXME: Early return if the iterator is null to avoid error messages from eina_iterator_free(). + // This check can be removed once the magic check on _free() removed in Eina. + // http://www.mail-archive.com/enlightenment-devel@lists.sourceforge.net/msg42944.html + if (!it) + return matchingEntries; + EINA_ITERATOR_FOREACH(it, f_name) { if (!fnmatch(cfilter.data(), f_name, 0)) matchingEntries.append(String::fromUTF8(f_name)); diff --git a/Source/WebCore/platform/efl/GamepadsEfl.cpp b/Source/WebCore/platform/efl/GamepadsEfl.cpp new file mode 100644 index 000000000..f67ba42e9 --- /dev/null +++ b/Source/WebCore/platform/efl/GamepadsEfl.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Gamepads.h" + +#if ENABLE(GAMEPAD) + +#include "GamepadDeviceLinux.h" +#include "GamepadList.h" +#include "Logging.h" +#include <Ecore.h> +#include <Eeze.h> +#include <Eina.h> +#include <unistd.h> +#include <wtf/HashMap.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/text/CString.h> +#include <wtf/text/StringHash.h> + +namespace WebCore { + +static const char joystickPrefix[] = "/dev/input/js"; + +class GamepadDeviceEfl : public GamepadDeviceLinux { +public: + static PassOwnPtr<GamepadDeviceEfl> create(const String& deviceFile) + { + return adoptPtr(new GamepadDeviceEfl(deviceFile)); + } + ~GamepadDeviceEfl(); + void resetFdHandler() { m_fdHandler = 0; } + const String& deviceFile() const { return m_deviceFile; } + +private: + GamepadDeviceEfl(const String& deviceFile); + static Eina_Bool readCallback(void* userData, Ecore_Fd_Handler*); + + Ecore_Fd_Handler* m_fdHandler; + String m_deviceFile; +}; + +GamepadDeviceEfl::GamepadDeviceEfl(const String& deviceFile) + : GamepadDeviceLinux(deviceFile) + , m_fdHandler(0) + , m_deviceFile(deviceFile) +{ + if (m_fileDescriptor < 0) + return; + + m_fdHandler = ecore_main_fd_handler_add(m_fileDescriptor, ECORE_FD_READ, readCallback, this, 0, 0); + if (!m_fdHandler) + LOG_ERROR("Failed to create the Ecore_Fd_Handler."); +} + +GamepadDeviceEfl::~GamepadDeviceEfl() +{ + if (m_fdHandler) + ecore_main_fd_handler_del(m_fdHandler); +} + +Eina_Bool GamepadDeviceEfl::readCallback(void* userData, Ecore_Fd_Handler* fdHandler) +{ + GamepadDeviceEfl* gamepadDevice = static_cast<GamepadDeviceEfl*>(userData); + + if (ecore_main_fd_handler_active_get(fdHandler, ECORE_FD_ERROR)) { + LOG_ERROR("An error occurred while watching the joystick file descriptor at %s, aborting.", gamepadDevice->deviceFile().utf8().data()); + gamepadDevice->resetFdHandler(); + return ECORE_CALLBACK_CANCEL; + } + + int fdDevice = ecore_main_fd_handler_fd_get(fdHandler); + struct js_event event; + const ssize_t len = read(fdDevice, &event, sizeof(event)); + + if (len <= 0) { + LOG_ERROR("Failed to read joystick file descriptor at %s, aborting.", gamepadDevice->deviceFile().utf8().data()); + gamepadDevice->resetFdHandler(); + return ECORE_CALLBACK_CANCEL; + } + if (len != sizeof(event)) { + LOG_ERROR("Wrong js_event size read on file descriptor at %s, ignoring.", gamepadDevice->deviceFile().utf8().data()); + return ECORE_CALLBACK_RENEW; + } + + gamepadDevice->updateForEvent(event); + return ECORE_CALLBACK_RENEW; +} + +class GamepadsEfl { +public: + GamepadsEfl(size_t length); + + void registerDevice(const String& syspath); + void unregisterDevice(const String& syspath); + + void updateGamepadList(GamepadList*); + +private: + ~GamepadsEfl(); + static void onGamePadChange(const char* syspath, Eeze_Udev_Event, void* userData, Eeze_Udev_Watch* watcher); + + Vector<OwnPtr<GamepadDeviceEfl> > m_slots; + HashMap<String, GamepadDeviceEfl*> m_deviceMap; + + Eeze_Udev_Watch* m_gamepadsWatcher; +}; + +void GamepadsEfl::onGamePadChange(const char* syspath, Eeze_Udev_Event event, void* userData, Eeze_Udev_Watch* watcher) +{ + GamepadsEfl* gamepadsEfl = static_cast<GamepadsEfl*>(userData); + + switch (event) { + case EEZE_UDEV_EVENT_ADD: + gamepadsEfl->registerDevice(String::fromUTF8(syspath)); + break; + case EEZE_UDEV_EVENT_REMOVE: + gamepadsEfl->unregisterDevice(String::fromUTF8(syspath)); + break; + default: + break; + } +} + +GamepadsEfl::GamepadsEfl(size_t length) + : m_slots(length) + , m_gamepadsWatcher(0) +{ + if (eeze_init() < 0) { + LOG_ERROR("Failed to initialize eeze library."); + return; + } + + // Watch for gamepads additions / removals. + m_gamepadsWatcher = eeze_udev_watch_add(EEZE_UDEV_TYPE_JOYSTICK, (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE), onGamePadChange, this); + + // List available gamepads. + Eina_List* gamepads = eeze_udev_find_by_type(EEZE_UDEV_TYPE_JOYSTICK, 0); + void* data; + EINA_LIST_FREE(gamepads, data) { + char* syspath = static_cast<char*>(data); + registerDevice(String::fromUTF8(syspath)); + eina_stringshare_del(syspath); + } +} + +GamepadsEfl::~GamepadsEfl() +{ + if (m_gamepadsWatcher) + eeze_udev_watch_del(m_gamepadsWatcher); + eeze_shutdown(); +} + +void GamepadsEfl::registerDevice(const String& syspath) +{ + if (m_deviceMap.contains(syspath)) + return; + + // Make sure it is a valid joystick. + const char* deviceFile = eeze_udev_syspath_get_devpath(syspath.utf8().data()); + if (!deviceFile || !eina_str_has_prefix(deviceFile, joystickPrefix)) + return; + + LOG(Gamepad, "Registering gamepad at %s", deviceFile); + + const size_t slotCount = m_slots.size(); + for (size_t index = 0; index < slotCount; ++index) { + if (!m_slots[index]) { + m_slots[index] = GamepadDeviceEfl::create(String::fromUTF8(deviceFile)); + LOG(Gamepad, "Gamepad device name is %s", m_slots[index]->id().utf8().data()); + m_deviceMap.add(syspath, m_slots[index].get()); + break; + } + } +} + +void GamepadsEfl::unregisterDevice(const String& syspath) +{ + if (!m_deviceMap.contains(syspath)) + return; + + GamepadDeviceEfl* gamepadDevice = m_deviceMap.take(syspath); + LOG(Gamepad, "Unregistering gamepad at %s", gamepadDevice->deviceFile().utf8().data()); + const size_t index = m_slots.find(gamepadDevice); + ASSERT(index != notFound); + + m_slots[index].clear(); +} + +void GamepadsEfl::updateGamepadList(GamepadList* into) +{ + ASSERT(m_slots.size() == into->length()); + + const size_t slotCount = m_slots.size(); + for (size_t i = 0; i < slotCount; ++i) { + if (m_slots[i].get() && m_slots[i]->connected()) { + GamepadDeviceEfl* gamepadDevice = m_slots[i].get(); + RefPtr<Gamepad> gamepad = into->item(i); + if (!gamepad) + gamepad = Gamepad::create(); + + gamepad->index(i); + gamepad->id(gamepadDevice->id()); + gamepad->timestamp(gamepadDevice->timestamp()); + gamepad->axes(gamepadDevice->axesCount(), gamepadDevice->axesData()); + gamepad->buttons(gamepadDevice->buttonsCount(), gamepadDevice->buttonsData()); + + into->set(i, gamepad); + } else + into->set(i, 0); + } +} + +void sampleGamepads(GamepadList* into) +{ + DEFINE_STATIC_LOCAL(GamepadsEfl, gamepadsEfl, (into->length())); + gamepadsEfl.updateGamepadList(into); +} + +} // namespace WebCore + +#endif // ENABLE(GAMEPAD) diff --git a/Source/WebCore/platform/efl/LanguageEfl.cpp b/Source/WebCore/platform/efl/LanguageEfl.cpp index 2b0a13dd8..6aeadb4b9 100644 --- a/Source/WebCore/platform/efl/LanguageEfl.cpp +++ b/Source/WebCore/platform/efl/LanguageEfl.cpp @@ -43,7 +43,13 @@ static String platformLanguage() if (!localeDefault) return String("c"); - return String(localeDefault).replace('_', '-'); + String locale = String(localeDefault); + locale.replace('_', '-'); + size_t position = locale.find('.'); + if (position != notFound) + locale = locale.left(position); + + return locale; } Vector<String> platformUserPreferredLanguages() diff --git a/Source/WebCore/platform/efl/LoggingEfl.cpp b/Source/WebCore/platform/efl/LoggingEfl.cpp index bd711484a..79cf004f5 100644 --- a/Source/WebCore/platform/efl/LoggingEfl.cpp +++ b/Source/WebCore/platform/efl/LoggingEfl.cpp @@ -23,6 +23,8 @@ #include "config.h" #include "Logging.h" +#if !LOG_DISABLED + #include "PlatformString.h" #include <Eina.h> @@ -62,3 +64,5 @@ void initializeLoggingChannelsIfNecessary() } } + +#endif // !LOG_DISABLED diff --git a/Source/WebCore/platform/efl/PlatformScreenEfl.cpp b/Source/WebCore/platform/efl/PlatformScreenEfl.cpp index 5010f1851..5332c2fbf 100644 --- a/Source/WebCore/platform/efl/PlatformScreenEfl.cpp +++ b/Source/WebCore/platform/efl/PlatformScreenEfl.cpp @@ -86,6 +86,8 @@ FloatRect screenRect(Widget* widget) int x, y, w, h; Evas* e = widget->evas(); + if (!e) + return FloatRect(); ecore_evas_screen_geometry_get(ecore_evas_ecore_evas_get(e), &x, &y, &w, &h); @@ -98,7 +100,7 @@ FloatRect screenAvailableRect(Widget* widget) return screenRect(widget); } -void screenColorProfile(Widget*, const String&, ColorProfile&) +void screenColorProfile(Widget*, ColorProfile&) { notImplemented(); } diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.cpp b/Source/WebCore/platform/efl/RenderThemeEfl.cpp index 7d27b96d0..462ee946e 100644 --- a/Source/WebCore/platform/efl/RenderThemeEfl.cpp +++ b/Source/WebCore/platform/efl/RenderThemeEfl.cpp @@ -82,9 +82,9 @@ void RenderThemeEfl::adjustSizeConstraints(RenderStyle* style, FormType type) co { const struct ThemePartDesc* desc = m_partDescs + (size_t)type; - if (style->minWidth().isIntrinsicOrAuto()) + if (style->minWidth().isIntrinsic()) style->setMinWidth(desc->min.width()); - if (style->minHeight().isIntrinsicOrAuto()) + if (style->minHeight().isIntrinsic()) style->setMinHeight(desc->min.height()); if (desc->max.width().value() > 0 && style->maxWidth().isIntrinsicOrAuto()) diff --git a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp index c93166659..595d16a4f 100644 --- a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp +++ b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp @@ -25,7 +25,7 @@ #include "config.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "ANGLEWebKitBridge.h" #include <wtf/OwnArrayPtr.h> @@ -117,4 +117,4 @@ bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShad } -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/BitmapImage.cpp b/Source/WebCore/platform/graphics/BitmapImage.cpp index 8bc97227f..04528591a 100644 --- a/Source/WebCore/platform/graphics/BitmapImage.cpp +++ b/Source/WebCore/platform/graphics/BitmapImage.cpp @@ -263,9 +263,12 @@ String BitmapImage::filenameExtension() const size_t BitmapImage::frameCount() { if (!m_haveFrameCount) { - m_haveFrameCount = true; m_frameCount = m_source.frameCount(); - didDecodeProperties(); + // If decoder is not initialized yet, m_source.frameCount() returns 0. + if (m_frameCount) { + didDecodeProperties(); + m_haveFrameCount = true; + } } return m_frameCount; } @@ -319,8 +322,10 @@ NativeImagePtr BitmapImage::nativeImageForCurrentFrame() bool BitmapImage::frameHasAlphaAtIndex(size_t index) { + // When a frame has not finished decoding, always mark it as having alpha. + // See ImageSource::framehasAlphaAtIndex for explanation of why incomplete images claim to have alpha. if (!ensureFrameIsCached(index)) - return true; // Why does an invalid index mean alpha? + return true; return m_frames[index].m_hasAlpha; } diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h index 64c81c791..21885cdd4 100644 --- a/Source/WebCore/platform/graphics/BitmapImage.h +++ b/Source/WebCore/platform/graphics/BitmapImage.h @@ -112,7 +112,7 @@ public: { return adoptRef(new BitmapImage(observer)); } - ~BitmapImage(); + virtual ~BitmapImage(); virtual bool isBitmapImage() const; diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.cpp b/Source/WebCore/platform/graphics/GraphicsContext3D.cpp index b765f4046..38b089268 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/Source/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -26,7 +26,7 @@ #include "config.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "GraphicsContext3D.h" @@ -1833,4 +1833,4 @@ unsigned GraphicsContext3D::getChannelBitsByFormat(GC3Denum format) } // namespace WebCore -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h index dbd9dfede..51eef09c5 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext3D.h +++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h @@ -20,7 +20,7 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GraphicsContext3D_h @@ -91,14 +91,12 @@ const Platform3DObject NullPlatform3DObject = 0; #include <CoreGraphics/CGContext.h> #endif -#if PLATFORM(BLACKBERRY) -#include <GLES2/gl2.h> -#endif - namespace WebCore { class DrawingBuffer; class Extensions3D; -#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL) +#if USE(OPENGL_ES_2) +class Extensions3DOpenGLES; +#else class Extensions3DOpenGL; #endif #if PLATFORM(QT) @@ -924,6 +922,7 @@ public: // in particular stencil and antialias, and determine which could or // could not be honored based on the capabilities of the OpenGL // implementation. + void validateDepthStencil(const char* packedDepthStencilExtension); void validateAttributes(); // Read rendering results into a pixel array with the same format as the @@ -955,16 +954,30 @@ public: HashMap<Platform3DObject, ShaderSourceEntry> m_shaderSourceMap; ANGLEWebKitBridge m_compiler; +#endif +#if PLATFORM(QT) && defined(QT_OPENGL_ES_2) + friend class Extensions3DQt; + OwnPtr<Extensions3DQt> m_extensions; +#elif PLATFORM(BLACKBERRY) + friend class Extensions3DOpenGLES; + OwnPtr<Extensions3DOpenGLES> m_extensions; +#elif !PLATFORM(CHROMIUM) friend class Extensions3DOpenGL; OwnPtr<Extensions3DOpenGL> m_extensions; +#endif + friend class Extensions3DOpenGLCommon; Attributes m_attrs; Vector<Vector<float> > m_vertexArray; - GC3Duint m_texture, m_compositorTexture; + GC3Duint m_texture; +#if !PLATFORM(BLACKBERRY) + GC3Duint m_compositorTexture; +#endif GC3Duint m_fbo; -#if USE(OPENGL_ES_2) + +#if !PLATFORM(BLACKBERRY) GC3Duint m_depthBuffer; GC3Duint m_stencilBuffer; #endif @@ -985,10 +998,11 @@ public: // Errors raised by synthesizeGLError(). ListHashSet<GC3Denum> m_syntheticErrors; -#endif friend class GraphicsContext3DPrivate; OwnPtr<GraphicsContext3DPrivate> m_private; + + bool systemAllowsMultisamplingOnATICards() const; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.cpp b/Source/WebCore/platform/graphics/GraphicsLayer.cpp index 10d7b7fc8..9a52fb67b 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayer.cpp +++ b/Source/WebCore/platform/graphics/GraphicsLayer.cpp @@ -509,13 +509,13 @@ int GraphicsLayer::validateTransformOperations(const KeyframeValueList& valueLis return firstIndex; } -double GraphicsLayer::backingStoreArea() const +double GraphicsLayer::backingStoreMemoryEstimate() const { if (!drawsContent()) return 0; // Effects of page and device scale are ignored; subclasses should override to take these into account. - return static_cast<double>(size().width()) * size().height(); + return static_cast<double>(4 * size().width()) * size().height(); } static void writeIndent(TextStream& ts, int indent) diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.h b/Source/WebCore/platform/graphics/GraphicsLayer.h index 16c73a483..7939717fa 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayer.h +++ b/Source/WebCore/platform/graphics/GraphicsLayer.h @@ -38,51 +38,12 @@ #include "FloatSize.h" #include "GraphicsLayerClient.h" #include "IntRect.h" +#include "PlatformLayer.h" #include "TransformationMatrix.h" #include "TransformOperations.h" #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> -#if PLATFORM(MAC) -OBJC_CLASS CALayer; -typedef CALayer PlatformLayer; -#elif PLATFORM(WIN) -typedef struct _CACFLayer PlatformLayer; -#elif PLATFORM(QT) -#if USE(TEXTURE_MAPPER) -namespace WebCore { -class TextureMapperPlatformLayer; -typedef TextureMapperPlatformLayer PlatformLayer; -}; -#else -QT_BEGIN_NAMESPACE -class QGraphicsObject; -QT_END_NAMESPACE -namespace WebCore { -typedef QGraphicsObject PlatformLayer; -} -#endif -#elif PLATFORM(CHROMIUM) -namespace WebCore { -class LayerChromium; -typedef LayerChromium PlatformLayer; -} -#elif PLATFORM(GTK) -#if USE(TEXTURE_MAPPER_CAIRO) || USE(TEXTURE_MAPPER_GL) -namespace WebCore { -class TextureMapperPlatformLayer; -typedef TextureMapperPlatformLayer PlatformLayer; -}; -#elif USE(CLUTTER) -typedef struct _ClutterActor ClutterActor; -namespace WebCore { -typedef ClutterActor PlatformLayer; -}; -#endif -#else -typedef void* PlatformLayer; -#endif - enum LayerTreeAsTextBehaviorFlags { LayerTreeAsTextBehaviorNormal = 0, LayerTreeAsTextDebug = 1 << 0, // Dump extra debugging info like layer addresses. @@ -426,8 +387,8 @@ public: // pointers for the layers and timing data will be included in the returned string. String layerTreeAsText(LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const; - // Return an estimate of the backing store area (in pixels). May be incorrect for tiled layers. - virtual double backingStoreArea() const; + // Return an estimate of the backing store memory cost (in bytes). May be incorrect for tiled layers. + virtual double backingStoreMemoryEstimate() const; bool usingTiledLayer() const { return m_usingTiledLayer; } diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h index 24831ed0a..06ac56757 100644 --- a/Source/WebCore/platform/graphics/ImageBuffer.h +++ b/Source/WebCore/platform/graphics/ImageBuffer.h @@ -33,7 +33,7 @@ #include "FloatRect.h" #include "GraphicsContext.h" #if USE(ACCELERATED_COMPOSITING) -#include "GraphicsLayer.h" +#include "PlatformLayer.h" #endif #include "GraphicsTypes.h" #include "GraphicsTypes3D.h" diff --git a/Source/WebCore/platform/graphics/OpenGLESShims.h b/Source/WebCore/platform/graphics/OpenGLESShims.h new file mode 100644 index 000000000..052af5e45 --- /dev/null +++ b/Source/WebCore/platform/graphics/OpenGLESShims.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OpenGLESShims_h +#define OpenGLESShims_h + +#if PLATFORM(BLACKBERRY) +#define glBindFramebufferEXT glBindFramebuffer +#define glFramebufferTexture2DEXT glFramebufferTexture2D +#define glBindRenderbufferEXT glBindRenderbuffer +#define glRenderbufferStorageEXT glRenderbufferStorage +#define glFramebufferRenderbufferEXT glFramebufferRenderbuffer +#define GL_RENDERBUFFER_EXT GL_RENDERBUFFER +#define GL_STENCIL_ATTACHMENT_EXT GL_STENCIL_ATTACHMENT +#define glCheckFramebufferStatusEXT glCheckFramebufferStatus +#define glDeleteFramebuffersEXT glDeleteFramebuffers +#define glDeleteRenderbuffersEXT glDeleteRenderbuffers +#define glGenRenderbuffersEXT glGenRenderbuffers +#define glGenFramebuffersEXT glGenFramebuffers +#define glGetFramebufferAttachmentParameterivEXT glGetFramebufferAttachmentParameteriv +#define glGetRenderbufferParameterivEXT glGetRenderbufferParameteriv +#define glIsRenderbufferEXT glIsRenderbuffer +#define glIsFramebufferEXT glIsFramebuffer +#define glGenerateMipmapEXT glGenerateMipmap +#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0 +#define GL_DEPTH_ATTACHMENT_EXT GL_DEPTH_ATTACHMENT +#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE +#define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER +#define GL_DEPTH24_STENCIL8_EXT GL_DEPTH24_STENCIL8_OES +#define GL_RGBA8 GL_RGBA8_OES +#define GL_RGB8 GL_RGB8_OES +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x9134 +#define GL_MAX_SAMPLES_EXT 0x8D57 +#endif // PLATFORM(BLACKBERRY) + +#endif // OpenGLESShims_h + diff --git a/Source/WebCore/platform/graphics/OpenGLShims.cpp b/Source/WebCore/platform/graphics/OpenGLShims.cpp index a23dc6895..82cc21c6d 100644 --- a/Source/WebCore/platform/graphics/OpenGLShims.cpp +++ b/Source/WebCore/platform/graphics/OpenGLShims.cpp @@ -17,7 +17,7 @@ */ #include "config.h" -#if ENABLE(WEBGL) || defined(QT_OPENGL_SHIMS) +#if USE(3D_GRAPHICS) || defined(QT_OPENGL_SHIMS) #define DISABLE_SHIMS #include "OpenGLShims.h" @@ -227,4 +227,4 @@ bool initializeOpenGLShims() } // namespace WebCore -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/Pattern.h b/Source/WebCore/platform/graphics/Pattern.h index 5a3c87966..3d5300555 100644 --- a/Source/WebCore/platform/graphics/Pattern.h +++ b/Source/WebCore/platform/graphics/Pattern.h @@ -78,6 +78,9 @@ public: // Pattern space is an abstract space that maps to the default user space by the transformation 'userSpaceTransformation' #if USE(SKIA) PlatformPatternPtr platformPattern(const AffineTransform& userSpaceTransformation); +#elif PLATFORM(QT) + // Qt ignores user space transformation and uses pattern's instead + PlatformPatternPtr createPlatformPattern() const; #else PlatformPatternPtr createPlatformPattern(const AffineTransform& userSpaceTransformation) const; #endif diff --git a/Source/WebCore/platform/graphics/PlatformLayer.h b/Source/WebCore/platform/graphics/PlatformLayer.h new file mode 100644 index 000000000..6dc0fe5c3 --- /dev/null +++ b/Source/WebCore/platform/graphics/PlatformLayer.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PlatformLayer_h +#define PlatformLayer_h + +#if USE(ACCELERATED_COMPOSITING) + +#if PLATFORM(MAC) +OBJC_CLASS CALayer; +typedef CALayer PlatformLayer; +#elif PLATFORM(WIN) +typedef struct _CACFLayer PlatformLayer; +#elif PLATFORM(QT) +namespace WebCore { +class TextureMapperPlatformLayer; +typedef TextureMapperPlatformLayer PlatformLayer; +}; +#elif PLATFORM(CHROMIUM) +namespace WebCore { +class LayerChromium; +typedef LayerChromium PlatformLayer; +} +#elif PLATFORM(GTK) +#if USE(TEXTURE_MAPPER_CAIRO) || USE(TEXTURE_MAPPER_GL) +namespace WebCore { +class TextureMapperPlatformLayer; +typedef TextureMapperPlatformLayer PlatformLayer; +}; +#elif USE(CLUTTER) +typedef struct _ClutterActor ClutterActor; +namespace WebCore { +typedef ClutterActor PlatformLayer; +}; +#endif +#else +typedef void* PlatformLayer; +#endif + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // PlatformLayer_h diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp index 73f0bdfc5..a1f625696 100644 --- a/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp @@ -26,7 +26,7 @@ #include "config.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "GraphicsContext3D.h" @@ -209,5 +209,5 @@ void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback> } // namespace WebCore -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp index 083fb7a26..55d479b8a 100644 --- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp +++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp @@ -1517,9 +1517,7 @@ void GraphicsLayerCA::updateContentsImage() // FIXME: maybe only do trilinear if the image is being scaled down, // but then what if the layer size changes? -#ifndef BUILDING_ON_LEOPARD m_contentsLayer->setMinificationFilter(PlatformCALayer::Trilinear); -#endif m_contentsLayer->setContents(m_pendingContentsImage.get()); m_pendingContentsImage = 0; @@ -2392,7 +2390,7 @@ void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) FloatSize GraphicsLayerCA::constrainedSize() const { FloatSize constrainedSize = m_size; -#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) +#if defined(BUILDING_ON_SNOW_LEOPARD) float tileColumns = ceilf(m_size.width() / kTiledLayerTileSize); float tileRows = ceilf(m_size.height() / kTiledLayerTileSize); double numTiles = tileColumns * tileRows; @@ -2835,13 +2833,13 @@ void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags) m_uncommittedChanges |= flags; } -double GraphicsLayerCA::backingStoreArea() const +double GraphicsLayerCA::backingStoreMemoryEstimate() const { if (!drawsContent()) return 0; // contentsLayer is given to us, so we don't really know anything about its contents. - return static_cast<double>(size().width()) * size().height() * m_layer->contentsScale(); + return static_cast<double>(4 * size().width()) * size().height() * m_layer->contentsScale(); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h index 4d5f01b9d..d5b4c2c61 100644 --- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h +++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h @@ -162,7 +162,7 @@ private: virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects) OVERRIDE; virtual float platformCALayerDeviceScaleFactor() OVERRIDE; - virtual double backingStoreArea() const; + virtual double backingStoreMemoryEstimate() const; void updateOpacityOnLayer(); diff --git a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h index f7f2d52b3..002b7a07a 100644 --- a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h +++ b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h @@ -213,7 +213,7 @@ public: void printTree() const; #endif -#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) void synchronouslyDisplayTilesInRect(const FloatRect&); #endif diff --git a/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm b/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm index cd856692b..c3679d726 100644 --- a/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm +++ b/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm @@ -36,8 +36,6 @@ #import <QuartzCore/QuartzCore.h> #import <wtf/UnusedParam.h> -#define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_LEOPARD)) - using namespace WebCore; // This value must be the same as in PlatformCALayerMac.mm @@ -75,7 +73,6 @@ static PlatformCAAnimation::FillModeType fromCAFillModeType(NSString* string) return PlatformCAAnimation::Forwards; } -#if HAVE_MODERN_QUARTZCORE static NSString* toCAValueFunctionType(PlatformCAAnimation::ValueFunctionType type) { switch (type) { @@ -132,7 +129,6 @@ static PlatformCAAnimation::ValueFunctionType fromCAValueFunctionType(NSString* return PlatformCAAnimation::NoValueFunction; } -#endif static CAMediaTimingFunction* toCAMediaTimingFunction(const TimingFunction* timingFunction, bool reverse) { @@ -344,21 +340,13 @@ void PlatformCAAnimation::setAdditive(bool value) PlatformCAAnimation::ValueFunctionType PlatformCAAnimation::valueFunction() const { -#if HAVE_MODERN_QUARTZCORE CAValueFunction* vf = [m_animation.get() valueFunction]; return fromCAValueFunctionType([vf name]); -#else - return NoValueFunction; -#endif } void PlatformCAAnimation::setValueFunction(ValueFunctionType value) { -#if HAVE_MODERN_QUARTZCORE [m_animation.get() setValueFunction:[CAValueFunction functionWithName:toCAValueFunctionType(value)]]; -#else - UNUSED_PARAM(value); -#endif } void PlatformCAAnimation::setFromValue(float value) diff --git a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm index 4c3623a63..3a7ac781f 100644 --- a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm +++ b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm @@ -44,8 +44,6 @@ #import <wtf/CurrentTime.h> #import <wtf/UnusedParam.h> -#define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_LEOPARD)) - using std::min; using std::max; @@ -95,7 +93,7 @@ static double mediaTimeToCurrentTime(CFTimeInterval t) @end -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) @interface CATiledLayer(GraphicsLayerCAPrivate) - (void)displayInRect:(CGRect)r levelOfDetail:(int)lod options:(NSDictionary *)dict; - (BOOL)canDrawConcurrently; @@ -105,7 +103,7 @@ static double mediaTimeToCurrentTime(CFTimeInterval t) @interface CALayer(Private) - (void)setContentsChanged; -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) - (void)setAcceleratesDrawing:(BOOL)flag; - (BOOL)acceleratesDrawing; #endif @@ -148,7 +146,6 @@ static NSDictionary* nullActionsDictionary() return actions; } -#if HAVE_MODERN_QUARTZCORE static NSString* toCAFilterType(PlatformCALayer::FilterType type) { switch (type) { @@ -158,7 +155,6 @@ static NSString* toCAFilterType(PlatformCALayer::FilterType type) default: return 0; } } -#endif PassRefPtr<PlatformCALayer> PlatformCALayer::create(LayerType layerType, PlatformCALayerClient* owner) { @@ -460,9 +456,7 @@ FloatPoint3D PlatformCALayer::anchorPoint() const { CGPoint point = [m_layer.get() anchorPoint]; float z = 0; -#if HAVE_MODERN_QUARTZCORE z = [m_layer.get() anchorPointZ]; -#endif return FloatPoint3D(point.x, point.y, z); } @@ -470,9 +464,7 @@ void PlatformCALayer::setAnchorPoint(const FloatPoint3D& value) { BEGIN_BLOCK_OBJC_EXCEPTIONS [m_layer.get() setAnchorPoint:CGPointMake(value.x(), value.y())]; -#if HAVE_MODERN_QUARTZCORE [m_layer.get() setAnchorPointZ:value.z()]; -#endif END_BLOCK_OBJC_EXCEPTIONS } @@ -502,28 +494,14 @@ void PlatformCALayer::setSublayerTransform(const TransformationMatrix& value) TransformationMatrix PlatformCALayer::contentsTransform() const { -#if !HAVE_MODERN_QUARTZCORE - if (m_layerType != LayerTypeWebLayer) - return TransformationMatrix(); - - return [static_cast<WebLayer*>(m_layer.get()) contentsTransform]; -#else + // FIXME: This function can be removed. return TransformationMatrix(); -#endif } void PlatformCALayer::setContentsTransform(const TransformationMatrix& value) { -#if !HAVE_MODERN_QUARTZCORE - if (m_layerType != LayerTypeWebLayer) - return; - - BEGIN_BLOCK_OBJC_EXCEPTIONS - [m_layer.get() setContentsTransform:value]; - END_BLOCK_OBJC_EXCEPTIONS -#else + // FIXME: This function can be removed. UNUSED_PARAM(value); -#endif } bool PlatformCALayer::isHidden() const @@ -540,22 +518,14 @@ void PlatformCALayer::setHidden(bool value) bool PlatformCALayer::isGeometryFlipped() const { -#if HAVE_MODERN_QUARTZCORE return [m_layer.get() isGeometryFlipped]; -#else - return false; -#endif } void PlatformCALayer::setGeometryFlipped(bool value) { -#if HAVE_MODERN_QUARTZCORE BEGIN_BLOCK_OBJC_EXCEPTIONS [m_layer.get() setGeometryFlipped:value]; END_BLOCK_OBJC_EXCEPTIONS -#else - UNUSED_PARAM(value); -#endif } bool PlatformCALayer::isDoubleSided() const @@ -584,7 +554,7 @@ void PlatformCALayer::setMasksToBounds(bool value) bool PlatformCALayer::acceleratesDrawing() const { -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) return [m_layer.get() acceleratesDrawing]; #else return false; @@ -593,7 +563,7 @@ bool PlatformCALayer::acceleratesDrawing() const void PlatformCALayer::setAcceleratesDrawing(bool acceleratesDrawing) { -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) BEGIN_BLOCK_OBJC_EXCEPTIONS [m_layer.get() setAcceleratesDrawing:acceleratesDrawing]; END_BLOCK_OBJC_EXCEPTIONS @@ -628,24 +598,16 @@ void PlatformCALayer::setContentsRect(const FloatRect& value) void PlatformCALayer::setMinificationFilter(FilterType value) { -#if HAVE_MODERN_QUARTZCORE BEGIN_BLOCK_OBJC_EXCEPTIONS [m_layer.get() setMinificationFilter:toCAFilterType(value)]; END_BLOCK_OBJC_EXCEPTIONS -#else - UNUSED_PARAM(value); -#endif } void PlatformCALayer::setMagnificationFilter(FilterType value) { -#if HAVE_MODERN_QUARTZCORE BEGIN_BLOCK_OBJC_EXCEPTIONS [m_layer.get() setMagnificationFilter:toCAFilterType(value)]; END_BLOCK_OBJC_EXCEPTIONS -#else - UNUSED_PARAM(value); -#endif } Color PlatformCALayer::backgroundColor() const @@ -948,7 +910,7 @@ void PlatformCALayer::setTimeOffset(CFTimeInterval value) float PlatformCALayer::contentsScale() const { -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) return [m_layer.get() contentsScale]; #else return 1; @@ -957,7 +919,7 @@ float PlatformCALayer::contentsScale() const void PlatformCALayer::setContentsScale(float value) { -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) BEGIN_BLOCK_OBJC_EXCEPTIONS [m_layer.get() setContentsScale:value]; END_BLOCK_OBJC_EXCEPTIONS @@ -975,7 +937,7 @@ TiledBacking* PlatformCALayer::tiledBacking() return [tileCacheLayer tiledBacking]; } -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) void PlatformCALayer::synchronouslyDisplayTilesInRect(const FloatRect& rect) { if (m_layerType != LayerTypeWebTiledLayer) diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm index 666ea3946..59d8b1f9b 100644 --- a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm +++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm @@ -36,7 +36,7 @@ using namespace std; -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) @interface CALayer (WebCALayerDetails) - (void)setAcceleratesDrawing:(BOOL)flag; @end @@ -64,6 +64,9 @@ TileCache::TileCache(WebTileCacheLayer* tileCacheLayer, const IntSize& tileSize) [CATransaction begin]; [CATransaction setDisableActions:YES]; [m_tileCacheLayer addSublayer:m_tileContainerLayer.get()]; +#ifndef NDEBUG + [m_tileContainerLayer.get() setName:@"TileCache Container Layer"]; +#endif [CATransaction commit]; } @@ -154,7 +157,7 @@ void TileCache::setScale(CGFloat scale) if (m_scale == scale && m_deviceScaleFactor == deviceScaleFactor) return; -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) Vector<FloatRect> dirtyRects; m_deviceScaleFactor = deviceScaleFactor; @@ -179,7 +182,7 @@ void TileCache::setScale(CGFloat scale) void TileCache::setAcceleratesDrawing(bool acceleratesDrawing) { -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) if (m_acceleratesDrawing == acceleratesDrawing) return; @@ -394,8 +397,11 @@ RetainPtr<WebTileLayer> TileCache::createTileLayer(const IntRect& tileRect) [layer.get() setBorderWidth:m_tileDebugBorderWidth]; [layer.get() setEdgeAntialiasingMask:0]; [layer.get() setOpaque:YES]; +#ifndef NDEBUG + [layer.get() setName:@"Tile"]; +#endif -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if !defined(BUILDING_ON_SNOW_LEOPARD) [layer.get() setContentsScale:m_deviceScaleFactor]; [layer.get() setAcceleratesDrawing:m_acceleratesDrawing]; #endif diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm index d3e27274b..72ae6fbd4 100644 --- a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm +++ b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm @@ -42,7 +42,9 @@ using namespace WebCore; // FIXME: The tile size should be configurable. _tileCache = TileCache::create(self, IntSize(512, 512)); - +#ifndef NDEBUG + [self setName:@"WebTileCacheLayer"]; +#endif return self; } diff --git a/Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp index 4c590a63b..a4eabe8ab 100644 --- a/Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/DrawingBufferCairo.cpp @@ -25,7 +25,7 @@ #include "config.h" -#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(WEBGL) +#if ENABLE(ACCELERATED_2D_CANVAS) || USE(3D_GRAPHICS) #include "DrawingBuffer.h" diff --git a/Source/WebCore/platform/graphics/cairo/GLContext.h b/Source/WebCore/platform/graphics/cairo/GLContext.h index ab82c9a45..c23a46cf1 100644 --- a/Source/WebCore/platform/graphics/cairo/GLContext.h +++ b/Source/WebCore/platform/graphics/cairo/GLContext.h @@ -42,7 +42,7 @@ public: virtual bool canRenderToDefaultFramebuffer() = 0; virtual IntSize defaultFrameBufferSize() = 0; -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) virtual PlatformGraphicsContext3D platformContext() = 0; #endif }; diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp index ac292d375..62da1a16c 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp @@ -28,11 +28,12 @@ #include "config.h" #include "GraphicsContext3D.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "Extensions3DOpenGL.h" #include "GraphicsContext3DPrivate.h" #include "Image.h" +#include "NotImplemented.h" #include "OpenGLShims.h" #include "PlatformContextCairo.h" #include "RefPtrCairo.h" @@ -146,6 +147,11 @@ GraphicsContext3D::~GraphicsContext3D() ::glDeleteFramebuffersEXT(1, &m_fbo); } +void GraphicsContext3D::releaseShaderCompiler() +{ + notImplemented(); +} + bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) { if (!image) @@ -258,4 +264,4 @@ PlatformLayer* GraphicsContext3D::platformLayer() const } // namespace WebCore -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp index 86b3abb68..7d6629f69 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp @@ -20,7 +20,7 @@ #include "config.h" #include "GraphicsContext3DPrivate.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "HostWindow.h" #include "NotImplemented.h" @@ -129,4 +129,4 @@ void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper* textureMapper } // namespace WebCore -#endif // ENABLE_WEBGL +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp index e044b8d9a..50de51f47 100644 --- a/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp +++ b/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -26,7 +26,7 @@ #include "config.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "GraphicsContext3D.h" @@ -283,4 +283,4 @@ void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imag } // namespace WebCore -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/cg/ImageCG.cpp b/Source/WebCore/platform/graphics/cg/ImageCG.cpp index 9dd454120..fed911aeb 100644 --- a/Source/WebCore/platform/graphics/cg/ImageCG.cpp +++ b/Source/WebCore/platform/graphics/cg/ImageCG.cpp @@ -229,9 +229,7 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const if (!nativeImageForCurrentFrame()) return; - ASSERT(patternTransform.isInvertible()); if (!patternTransform.isInvertible()) - // Avoid a hang under CGContextDrawTiledImage on release builds. return; CGContextRef context = ctxt->platformContext(); diff --git a/Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp b/Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp index 42c952f07..69e632b71 100644 --- a/Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp +++ b/Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp @@ -122,15 +122,54 @@ WebTransformOperations toWebTransformOperations(const TransformOperations& trans } template <class Value, class Keyframe, class Curve> -bool appendKeyframe(Curve& curve, double keyTime, const Value* value, PassOwnPtr<CCTimingFunction> timingFunction, const FloatSize&) +bool appendKeyframe(Curve& curve, double keyTime, const Value* value, const Value* lastValue, PassOwnPtr<CCTimingFunction> timingFunction, const FloatSize&) { curve.addKeyframe(Keyframe::create(keyTime, value->value(), timingFunction)); return true; } +bool isRotationType(TransformOperation::OperationType transformType) +{ + return transformType == TransformOperation::ROTATE + || transformType == TransformOperation::ROTATE_X + || transformType == TransformOperation::ROTATE_Y + || transformType == TransformOperation::ROTATE_Z + || transformType == TransformOperation::ROTATE_3D; +} + +bool causesRotationOfAtLeast180Degrees(const TransformAnimationValue* value, const TransformAnimationValue* lastValue) +{ + if (!lastValue) + return false; + + const TransformOperations& operations = *value->value(); + const TransformOperations& lastOperations = *lastValue->value(); + + // We'll be doing matrix interpolation in this case. No risk of incorrect + // rotations here. + if (!operations.operationsMatch(lastOperations)) + return false; + + for (size_t i = 0; i < operations.size(); ++i) { + if (!isRotationType(operations.operations()[i]->getOperationType())) + continue; + + RotateTransformOperation* rotation = static_cast<RotateTransformOperation*>(operations.operations()[i].get()); + RotateTransformOperation* lastRotation = static_cast<RotateTransformOperation*>(lastOperations.operations()[i].get()); + + if (fabs(rotation->angle() - lastRotation->angle()) >= 180) + return true; + } + + return false; +} + template <> -bool appendKeyframe<TransformAnimationValue, CCTransformKeyframe, CCKeyframedTransformAnimationCurve>(CCKeyframedTransformAnimationCurve& curve, double keyTime, const TransformAnimationValue* value, PassOwnPtr<CCTimingFunction> timingFunction, const FloatSize& boxSize) +bool appendKeyframe<TransformAnimationValue, CCTransformKeyframe, CCKeyframedTransformAnimationCurve>(CCKeyframedTransformAnimationCurve& curve, double keyTime, const TransformAnimationValue* value, const TransformAnimationValue* lastValue, PassOwnPtr<CCTimingFunction> timingFunction, const FloatSize& boxSize) { + if (causesRotationOfAtLeast180Degrees(value, lastValue)) + return false; + WebTransformOperations operations = toWebTransformOperations(*value->value(), boxSize); if (operations.apply().isInvertible()) { curve.addKeyframe(CCTransformKeyframe::create(keyTime, operations, timingFunction)); @@ -159,6 +198,9 @@ PassOwnPtr<CCActiveAnimation> createActiveAnimation(const KeyframeValueList& val size_t index = reverse ? valueList.size() - i - 1 : i; const Value* originalValue = static_cast<const Value*>(valueList.at(index)); + const Value* lastOriginalValue = 0; + if (valueList.size() > 1 && ((reverse && index + 1 < valueList.size()) || (!reverse && index > 0))) + lastOriginalValue = static_cast<const Value*>(valueList.at(reverse ? index + 1 : index - 1)); OwnPtr<CCTimingFunction> timingFunction; const TimingFunction* originalTimingFunction = originalValue->timingFunction(); @@ -190,7 +232,7 @@ PassOwnPtr<CCActiveAnimation> createActiveAnimation(const KeyframeValueList& val if (reverse) keyTime = duration - keyTime; - bool addedKeyframe = appendKeyframe<Value, Keyframe, Curve>(*curve, keyTime, originalValue, timingFunction.release(), boxSize); + bool addedKeyframe = appendKeyframe<Value, Keyframe, Curve>(*curve, keyTime, originalValue, lastOriginalValue, timingFunction.release(), boxSize); if (!addedKeyframe) return nullptr; } diff --git a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp index f85285f3b..f869c58a2 100644 --- a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp @@ -33,11 +33,12 @@ #include "LayerPainterChromium.h" #include "PlatformColor.h" #include "PlatformContextSkia.h" +#include "cc/CCGraphicsContext.h" #include "skia/ext/platform_canvas.h" namespace WebCore { -BitmapCanvasLayerTextureUpdater::Texture::Texture(BitmapCanvasLayerTextureUpdater* textureUpdater, PassOwnPtr<ManagedTexture> texture) +BitmapCanvasLayerTextureUpdater::Texture::Texture(BitmapCanvasLayerTextureUpdater* textureUpdater, PassOwnPtr<CCPrioritizedTexture> texture) : LayerTextureUpdater::Texture(texture) , m_textureUpdater(textureUpdater) { @@ -68,9 +69,9 @@ BitmapCanvasLayerTextureUpdater::~BitmapCanvasLayerTextureUpdater() { } -PassOwnPtr<LayerTextureUpdater::Texture> BitmapCanvasLayerTextureUpdater::createTexture(TextureManager* manager) +PassOwnPtr<LayerTextureUpdater::Texture> BitmapCanvasLayerTextureUpdater::createTexture(CCPrioritizedTextureManager* manager) { - return adoptPtr(new Texture(this, ManagedTexture::create(manager))); + return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); } LayerTextureUpdater::SampledTexelFormat BitmapCanvasLayerTextureUpdater::sampledTexelFormat(GC3Denum textureFormat) @@ -80,7 +81,7 @@ LayerTextureUpdater::SampledTexelFormat BitmapCanvasLayerTextureUpdater::sampled LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA; } -void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect) +void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) { m_texSubImage.setSubImageSize(tileSize); @@ -89,10 +90,10 @@ void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect m_canvas = adoptPtr(skia::CreateBitmapCanvas(m_canvasSize.width(), m_canvasSize.height(), m_opaque)); } - paintContents(m_canvas.get(), contentRect, contentsScale, resultingOpaqueRect); + paintContents(m_canvas.get(), contentRect, contentsWidthScale, contentsHeightScale, resultingOpaqueRect); } -void BitmapCanvasLayerTextureUpdater::updateTextureRect(CCGraphicsContext* context, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect) +void BitmapCanvasLayerTextureUpdater::updateTextureRect(CCGraphicsContext* context, TextureAllocator* allocator, CCPrioritizedTexture* texture, const IntRect& sourceRect, const IntRect& destRect) { const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(false); bitmap.lockPixels(); diff --git a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h index 3c95380ce..d97968c03 100644 --- a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h +++ b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h @@ -37,6 +37,7 @@ class SkCanvas; namespace WebCore { class LayerPainterChromium; +class CCGraphicsContext; // This class rasterizes the contentRect into a skia bitmap canvas. It then updates // textures by copying from the canvas into the texture, using MapSubImage if @@ -45,7 +46,7 @@ class BitmapCanvasLayerTextureUpdater : public CanvasLayerTextureUpdater { public: class Texture : public LayerTextureUpdater::Texture { public: - Texture(BitmapCanvasLayerTextureUpdater*, PassOwnPtr<ManagedTexture>); + Texture(BitmapCanvasLayerTextureUpdater*, PassOwnPtr<CCPrioritizedTexture>); virtual ~Texture(); virtual void updateRect(CCGraphicsContext*, TextureAllocator*, const IntRect& sourceRect, const IntRect& destRect) OVERRIDE; @@ -59,10 +60,10 @@ public: static PassRefPtr<BitmapCanvasLayerTextureUpdater> create(PassOwnPtr<LayerPainterChromium>, bool useMapTexSubImage); virtual ~BitmapCanvasLayerTextureUpdater(); - virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager*); + virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(CCPrioritizedTextureManager*); virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat); - virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect) OVERRIDE; - void updateTextureRect(CCGraphicsContext*, TextureAllocator*, ManagedTexture*, const IntRect& sourceRect, const IntRect& destRect); + virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) OVERRIDE; + void updateTextureRect(CCGraphicsContext*, TextureAllocator*, CCPrioritizedTexture*, const IntRect& sourceRect, const IntRect& destRect); virtual void setOpaque(bool) OVERRIDE; diff --git a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp index 71b390f5b..23cffea94 100644 --- a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp @@ -34,10 +34,11 @@ #include "PlatformColor.h" #include "SkCanvas.h" #include "SkDevice.h" +#include "cc/CCGraphicsContext.h" namespace WebCore { -BitmapSkPictureCanvasLayerTextureUpdater::Texture::Texture(BitmapSkPictureCanvasLayerTextureUpdater* textureUpdater, PassOwnPtr<ManagedTexture> texture) +BitmapSkPictureCanvasLayerTextureUpdater::Texture::Texture(BitmapSkPictureCanvasLayerTextureUpdater* textureUpdater, PassOwnPtr<CCPrioritizedTexture> texture) : CanvasLayerTextureUpdater::Texture(texture) , m_textureUpdater(textureUpdater) { @@ -78,9 +79,9 @@ BitmapSkPictureCanvasLayerTextureUpdater::~BitmapSkPictureCanvasLayerTextureUpda { } -PassOwnPtr<LayerTextureUpdater::Texture> BitmapSkPictureCanvasLayerTextureUpdater::createTexture(TextureManager* manager) +PassOwnPtr<LayerTextureUpdater::Texture> BitmapSkPictureCanvasLayerTextureUpdater::createTexture(CCPrioritizedTextureManager* manager) { - return adoptPtr(new Texture(this, ManagedTexture::create(manager))); + return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); } LayerTextureUpdater::SampledTexelFormat BitmapSkPictureCanvasLayerTextureUpdater::sampledTexelFormat(GC3Denum textureFormat) @@ -90,10 +91,10 @@ LayerTextureUpdater::SampledTexelFormat BitmapSkPictureCanvasLayerTextureUpdater LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA; } -void BitmapSkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect) +void BitmapSkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) { m_texSubImage.setSubImageSize(tileSize); - SkPictureCanvasLayerTextureUpdater::prepareToUpdate(contentRect, tileSize, contentsScale, resultingOpaqueRect); + SkPictureCanvasLayerTextureUpdater::prepareToUpdate(contentRect, tileSize, contentsWidthScale, contentsHeightScale, resultingOpaqueRect); } void BitmapSkPictureCanvasLayerTextureUpdater::paintContentsRect(SkCanvas* canvas, const IntRect& sourceRect) diff --git a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h index 09481d284..787b39937 100644 --- a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h +++ b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h @@ -40,7 +40,7 @@ class BitmapSkPictureCanvasLayerTextureUpdater : public SkPictureCanvasLayerText public: class Texture : public CanvasLayerTextureUpdater::Texture { public: - Texture(BitmapSkPictureCanvasLayerTextureUpdater*, PassOwnPtr<ManagedTexture>); + Texture(BitmapSkPictureCanvasLayerTextureUpdater*, PassOwnPtr<CCPrioritizedTexture>); virtual void prepareRect(const IntRect& sourceRect) OVERRIDE; virtual void updateRect(CCGraphicsContext*, TextureAllocator*, const IntRect& sourceRect, const IntRect& destRect) OVERRIDE; @@ -55,9 +55,9 @@ public: static PassRefPtr<BitmapSkPictureCanvasLayerTextureUpdater> create(PassOwnPtr<LayerPainterChromium>, bool useMapTexSubImage); virtual ~BitmapSkPictureCanvasLayerTextureUpdater(); - virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager*) OVERRIDE; + virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(CCPrioritizedTextureManager*) OVERRIDE; virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE; - virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect) OVERRIDE; + virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) OVERRIDE; void paintContentsRect(SkCanvas*, const IntRect& sourceRect); void updateTextureRect(CCGraphicsContext*, GC3Denum format, const IntRect& destRect, const uint8_t* pixels); diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp index 530bb2f71..be8484b75 100644 --- a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp @@ -30,9 +30,8 @@ #include "CanvasLayerTextureUpdater.h" -#include "GraphicsContext.h" +#include "FloatRect.h" #include "LayerPainterChromium.h" -#include "PlatformContextSkia.h" #include "SkCanvas.h" #include "SkPaint.h" #include "SkRect.h" @@ -50,31 +49,35 @@ CanvasLayerTextureUpdater::~CanvasLayerTextureUpdater() { } -void CanvasLayerTextureUpdater::paintContents(SkCanvas* canvas, const IntRect& contentRect, float contentsScale, IntRect& resultingOpaqueRect) +void CanvasLayerTextureUpdater::paintContents(SkCanvas* canvas, const IntRect& contentRect, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) { TRACE_EVENT0("cc", "CanvasLayerTextureUpdater::paintContents"); canvas->save(); canvas->translate(WebCoreFloatToSkScalar(-contentRect.x()), WebCoreFloatToSkScalar(-contentRect.y())); - IntRect scaledContentRect = contentRect; + IntRect layerRect = contentRect; - if (contentsScale != 1.0) { - canvas->scale(WebCoreFloatToSkScalar(contentsScale), WebCoreFloatToSkScalar(contentsScale)); + if (contentsWidthScale != 1 || contentsHeightScale != 1) { + canvas->scale(WebCoreFloatToSkScalar(contentsWidthScale), WebCoreFloatToSkScalar(contentsHeightScale)); FloatRect rect = contentRect; - rect.scale(1 / contentsScale); - scaledContentRect = enclosingIntRect(rect); + rect.scale(1 / contentsWidthScale, 1 / contentsHeightScale); + layerRect = enclosingIntRect(rect); } SkPaint paint; paint.setAntiAlias(false); paint.setXfermodeMode(SkXfermode::kClear_Mode); - canvas->drawRect(scaledContentRect, paint); - canvas->clipRect(scaledContentRect); + canvas->drawRect(layerRect, paint); + canvas->clipRect(layerRect); - m_painter->paint(canvas, scaledContentRect, resultingOpaqueRect); + FloatRect opaqueLayerRect; + m_painter->paint(canvas, layerRect, opaqueLayerRect); canvas->restore(); + opaqueLayerRect.scale(contentsWidthScale, contentsHeightScale); + resultingOpaqueRect = enclosedIntRect(opaqueLayerRect); + m_contentRect = contentRect; } diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h index c951e93fe..b441e4e74 100644 --- a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h +++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h @@ -47,7 +47,7 @@ public: protected: explicit CanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium>); - void paintContents(SkCanvas*, const IntRect& contentRect, float contentsScale, IntRect& resultingOpaqueRect); + void paintContents(SkCanvas*, const IntRect& contentRect, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect); const IntRect& contentRect() const { return m_contentRect; } private: diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp index 05ee55225..078d377d0 100644 --- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp @@ -38,7 +38,6 @@ #include "BitmapSkPictureCanvasLayerTextureUpdater.h" #include "FrameBufferSkPictureCanvasLayerTextureUpdater.h" #include "LayerPainterChromium.h" -#include "PlatformSupport.h" #include "cc/CCLayerTreeHost.h" #include "cc/CCSettings.h" #include <public/Platform.h> @@ -46,31 +45,25 @@ namespace WebCore { -class ContentLayerPainter : public LayerPainterChromium { - WTF_MAKE_NONCOPYABLE(ContentLayerPainter); -public: - static PassOwnPtr<ContentLayerPainter> create(ContentLayerDelegate* delegate) - { - return adoptPtr(new ContentLayerPainter(delegate)); - } - - virtual void paint(SkCanvas* canvas, const IntRect& contentRect, IntRect& opaque) - { - double paintStart = currentTime(); - m_delegate->paintContents(canvas, contentRect, opaque); - double paintEnd = currentTime(); - double pixelsPerSec = (contentRect.width() * contentRect.height()) / (paintEnd - paintStart); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelContentPaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelContentPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30); - } -private: - explicit ContentLayerPainter(ContentLayerDelegate* delegate) - : m_delegate(delegate) - { - } - - ContentLayerDelegate* m_delegate; -}; +ContentLayerPainter::ContentLayerPainter(ContentLayerDelegate* delegate) + : m_delegate(delegate) +{ +} + +PassOwnPtr<ContentLayerPainter> ContentLayerPainter::create(ContentLayerDelegate* delegate) +{ + return adoptPtr(new ContentLayerPainter(delegate)); +} + +void ContentLayerPainter::paint(SkCanvas* canvas, const IntRect& contentRect, FloatRect& opaque) +{ + double paintStart = currentTime(); + m_delegate->paintContents(canvas, contentRect, opaque); + double paintEnd = currentTime(); + double pixelsPerSec = (contentRect.width() * contentRect.height()) / (paintEnd - paintStart); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelContentPaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelContentPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30); +} PassRefPtr<ContentLayerChromium> ContentLayerChromium::create(ContentLayerDelegate* delegate) { @@ -92,9 +85,16 @@ bool ContentLayerChromium::drawsContent() const return TiledLayerChromium::drawsContent() && m_delegate; } -void ContentLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion) +void ContentLayerChromium::setTexturePriorities(const CCPriorityCalculator& priorityCalc) { + // Update the tile data before creating all the layer's tiles. updateTileSizeAndTilingOption(); + + TiledLayerChromium::setTexturePriorities(priorityCalc); +} + +void ContentLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion) +{ createTextureUpdaterIfNeeded(); IntRect layerRect; @@ -108,15 +108,11 @@ void ContentLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTr m_needsDisplay = false; } -void ContentLayerChromium::idleUpdate(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion) +bool ContentLayerChromium::needMoreUpdates() { if (!drawsContent()) - return; - - const IntRect layerRect = visibleLayerRect(); - idleUpdateLayerRect(updater, layerRect, occlusion); - if (needsIdlePaint(layerRect)) - setNeedsCommit(); + return false; + return needsIdlePaint(visibleLayerRect()); } void ContentLayerChromium::createTextureUpdaterIfNeeded() diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h index d72818599..d8ea48565 100644 --- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h @@ -34,24 +34,38 @@ #if USE(ACCELERATED_COMPOSITING) +#include "LayerPainterChromium.h" #include "TiledLayerChromium.h" class SkCanvas; namespace WebCore { -class GraphicsContext; +class FloatRect; class IntRect; class LayerTextureUpdater; class ContentLayerDelegate { public: - virtual void paintContents(SkCanvas*, const IntRect& clip, IntRect& opaque) = 0; + virtual void paintContents(SkCanvas*, const IntRect& clip, FloatRect& opaque) = 0; protected: virtual ~ContentLayerDelegate() { } }; +class ContentLayerPainter : public LayerPainterChromium { + WTF_MAKE_NONCOPYABLE(ContentLayerPainter); +public: + static PassOwnPtr<ContentLayerPainter> create(ContentLayerDelegate*); + + virtual void paint(SkCanvas*, const IntRect& contentRect, FloatRect& opaque) OVERRIDE; + +private: + explicit ContentLayerPainter(ContentLayerDelegate*); + + ContentLayerDelegate* m_delegate; +}; + // A layer that renders its contents into an SkCanvas. class ContentLayerChromium : public TiledLayerChromium { public: @@ -62,8 +76,9 @@ public: void clearDelegate() { m_delegate = 0; } virtual bool drawsContent() const OVERRIDE; + virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; virtual void update(CCTextureUpdater&, const CCOcclusionTracker*) OVERRIDE; - virtual void idleUpdate(CCTextureUpdater&, const CCOcclusionTracker*) OVERRIDE; + virtual bool needMoreUpdates() OVERRIDE; virtual void setOpaque(bool) OVERRIDE; diff --git a/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp index 743bcc1f7..7e9ac0a6c 100644 --- a/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp @@ -40,10 +40,10 @@ namespace WebCore { static PassOwnPtr<SkCanvas> createAcceleratedCanvas(GraphicsContext3D* context, TextureAllocator* allocator, - ManagedTexture* texture) + CCPrioritizedTexture* texture) { // Allocate so that we have a valid texture id. - texture->allocate(allocator); + texture->acquireBackingTexture(allocator); GrContext* grContext = context->grContext(); IntSize canvasSize = texture->size(); @@ -58,7 +58,7 @@ static PassOwnPtr<SkCanvas> createAcceleratedCanvas(GraphicsContext3D* context, return adoptPtr(new SkCanvas(device.get())); } -FrameBufferSkPictureCanvasLayerTextureUpdater::Texture::Texture(FrameBufferSkPictureCanvasLayerTextureUpdater* textureUpdater, PassOwnPtr<ManagedTexture> texture) +FrameBufferSkPictureCanvasLayerTextureUpdater::Texture::Texture(FrameBufferSkPictureCanvasLayerTextureUpdater* textureUpdater, PassOwnPtr<CCPrioritizedTexture> texture) : LayerTextureUpdater::Texture(texture) , m_textureUpdater(textureUpdater) { @@ -90,9 +90,9 @@ FrameBufferSkPictureCanvasLayerTextureUpdater::~FrameBufferSkPictureCanvasLayerT { } -PassOwnPtr<LayerTextureUpdater::Texture> FrameBufferSkPictureCanvasLayerTextureUpdater::createTexture(TextureManager* manager) +PassOwnPtr<LayerTextureUpdater::Texture> FrameBufferSkPictureCanvasLayerTextureUpdater::createTexture(CCPrioritizedTextureManager* manager) { - return adoptPtr(new Texture(this, ManagedTexture::create(manager))); + return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); } LayerTextureUpdater::SampledTexelFormat FrameBufferSkPictureCanvasLayerTextureUpdater::sampledTexelFormat(GC3Denum textureFormat) @@ -101,7 +101,7 @@ LayerTextureUpdater::SampledTexelFormat FrameBufferSkPictureCanvasLayerTextureUp return LayerTextureUpdater::SampledTexelFormatRGBA; } -void FrameBufferSkPictureCanvasLayerTextureUpdater::updateTextureRect(PassRefPtr<GraphicsContext3D> prpContext, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect) +void FrameBufferSkPictureCanvasLayerTextureUpdater::updateTextureRect(PassRefPtr<GraphicsContext3D> prpContext, TextureAllocator* allocator, CCPrioritizedTexture* texture, const IntRect& sourceRect, const IntRect& destRect) { RefPtr<GraphicsContext3D> context(prpContext); diff --git a/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.h index 1f2f20cce..8f630a922 100644 --- a/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.h +++ b/Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.h @@ -40,7 +40,7 @@ class FrameBufferSkPictureCanvasLayerTextureUpdater : public SkPictureCanvasLaye public: class Texture : public LayerTextureUpdater::Texture { public: - Texture(FrameBufferSkPictureCanvasLayerTextureUpdater*, PassOwnPtr<ManagedTexture>); + Texture(FrameBufferSkPictureCanvasLayerTextureUpdater*, PassOwnPtr<CCPrioritizedTexture>); virtual ~Texture(); virtual void updateRect(CCGraphicsContext*, TextureAllocator*, const IntRect& sourceRect, const IntRect& destRect) OVERRIDE; @@ -54,9 +54,9 @@ public: static PassRefPtr<FrameBufferSkPictureCanvasLayerTextureUpdater> create(PassOwnPtr<LayerPainterChromium>); virtual ~FrameBufferSkPictureCanvasLayerTextureUpdater(); - virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager*) OVERRIDE; + virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(CCPrioritizedTextureManager*) OVERRIDE; virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE; - void updateTextureRect(PassRefPtr<GraphicsContext3D>, TextureAllocator*, ManagedTexture*, const IntRect& sourceRect, const IntRect& destRect); + void updateTextureRect(PassRefPtr<GraphicsContext3D>, TextureAllocator*, CCPrioritizedTexture*, const IntRect& sourceRect, const IntRect& destRect); private: explicit FrameBufferSkPictureCanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium>); diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index d37572d93..c21726e9f 100644 --- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -509,14 +509,6 @@ void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* platformLayer) bool GraphicsLayerChromium::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& animationName, double timeOffset) { - // Bail early if we have a large rotation. - if (values.property() == AnimatedPropertyWebkitTransform) { - bool hasRotationOfMoreThan180Degrees = false; - validateTransformOperations(values, hasRotationOfMoreThan180Degrees); - if (hasRotationOfMoreThan180Degrees) - return false; - } - primaryLayer().unwrap<LayerChromium>()->setLayerAnimationDelegate(this); int animationId = mapAnimationNameToId(animationName); diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp index 1fb3e4305..14164133d 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp @@ -34,7 +34,6 @@ #include "ImageLayerChromium.h" -#include "Image.h" #include "LayerTextureSubImage.h" #include "LayerTextureUpdater.h" #include "ManagedTexture.h" @@ -47,7 +46,7 @@ class ImageLayerTextureUpdater : public LayerTextureUpdater { public: class Texture : public LayerTextureUpdater::Texture { public: - Texture(ImageLayerTextureUpdater* textureUpdater, PassOwnPtr<ManagedTexture> texture) + Texture(ImageLayerTextureUpdater* textureUpdater, PassOwnPtr<CCPrioritizedTexture> texture) : LayerTextureUpdater::Texture(texture) , m_textureUpdater(textureUpdater) { @@ -71,9 +70,9 @@ public: virtual ~ImageLayerTextureUpdater() { } - virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager* manager) + virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(CCPrioritizedTextureManager* manager) { - return adoptPtr(new Texture(this, ManagedTexture::create(manager))); + return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); } virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE @@ -82,7 +81,7 @@ public: LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA; } - void updateTextureRect(CCGraphicsContext* context, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect) + void updateTextureRect(CCGraphicsContext* context, TextureAllocator* allocator, CCPrioritizedTexture* texture, const IntRect& sourceRect, const IntRect& destRect) { texture->bindTexture(context, allocator); @@ -142,6 +141,14 @@ void ImageLayerChromium::setBitmap(const SkBitmap& bitmap) setNeedsDisplay(); } +void ImageLayerChromium::setTexturePriorities(const CCPriorityCalculator& priorityCalc) +{ + // Update the tile data before creating all the layer's tiles. + updateTileSizeAndTilingOption(); + + TiledLayerChromium::setTexturePriorities(priorityCalc); +} + void ImageLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion) { createTextureUpdaterIfNeeded(); diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h index 988e71eac..adccce620 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h @@ -48,6 +48,7 @@ public: virtual ~ImageLayerChromium(); virtual bool drawsContent() const OVERRIDE; + virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; virtual void update(CCTextureUpdater&, const CCOcclusionTracker*) OVERRIDE; virtual bool needsContentsScale() const OVERRIDE; diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp index 1a4038a4f..38b856e63 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -33,9 +33,6 @@ #if USE(ACCELERATED_COMPOSITING) #include "LayerChromium.h" -#include "NativeImageSkia.h" -#include "PlatformContextSkia.h" -#include "RenderLayerBacking.h" #include "TextStream.h" #include "cc/CCActiveAnimation.h" #include "cc/CCAnimationEvents.h" @@ -44,7 +41,6 @@ #include "cc/CCLayerImpl.h" #include "cc/CCLayerTreeHost.h" #include "cc/CCSettings.h" -#include "skia/ext/platform_canvas.h" using namespace std; using WebKit::WebTransformationMatrix; @@ -70,7 +66,8 @@ LayerChromium::LayerChromium() , m_haveWheelEventHandlers(false) , m_nonFastScrollableRegionChanged(false) , m_anchorPoint(0.5, 0.5) - , m_backgroundColor(0, 0, 0, 0) + , m_backgroundColor(0) + , m_debugBorderColor(0) , m_debugBorderWidth(0) , m_opacity(1.0) , m_anchorPointZ(0) @@ -281,7 +278,7 @@ void LayerChromium::setAnchorPointZ(float anchorPointZ) setNeedsCommit(); } -void LayerChromium::setBackgroundColor(const Color& backgroundColor) +void LayerChromium::setBackgroundColor(SkColor backgroundColor) { if (m_backgroundColor == backgroundColor) return; @@ -601,7 +598,7 @@ PassOwnPtr<CCLayerImpl> LayerChromium::createCCLayerImpl() return CCLayerImpl::create(m_layerId); } -void LayerChromium::setDebugBorderColor(const Color& color) +void LayerChromium::setDebugBorderColor(SkColor color) { m_debugBorderColor = color; setNeedsCommit(); diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h index 68c2e317b..e3ceb94d0 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h @@ -35,12 +35,12 @@ #if USE(ACCELERATED_COMPOSITING) #include "FloatPoint.h" -#include "GraphicsContext.h" -#include "PlatformString.h" #include "Region.h" #include "RenderSurfaceChromium.h" +#include "SkColor.h" #include "cc/CCLayerAnimationController.h" #include "cc/CCOcclusionTracker.h" +#include "cc/CCPrioritizedTexture.h" #include <public/WebFilterOperations.h> #include <public/WebTransformationMatrix.h> @@ -106,8 +106,8 @@ public: void setAnchorPointZ(float); float anchorPointZ() const { return m_anchorPointZ; } - void setBackgroundColor(const Color&); - Color backgroundColor() const { return m_backgroundColor; } + void setBackgroundColor(SkColor); + SkColor backgroundColor() const { return m_backgroundColor; } // A layer's bounds are in logical, non-page-scaled pixels (however, the // root layer's bounds are in physical pixels). @@ -211,12 +211,12 @@ public: // These methods typically need to be overwritten by derived classes. virtual bool drawsContent() const { return m_isDrawable; } virtual void update(CCTextureUpdater&, const CCOcclusionTracker*) { } - virtual void idleUpdate(CCTextureUpdater&, const CCOcclusionTracker*) { } + virtual bool needMoreUpdates() { return false; } virtual void setIsMask(bool) { } virtual void bindContentsTexture() { } virtual bool needsContentsScale() const { return false; } - void setDebugBorderColor(const Color&); + void setDebugBorderColor(SkColor); void setDebugBorderWidth(float); void setDebugName(const String&); @@ -263,8 +263,8 @@ public: CCLayerTreeHost* layerTreeHost() const { return m_layerTreeHost; } - // Reserve any textures needed for this layer. - virtual void reserveTextures() { } + // Set the priority of all desired textures in this layer. + virtual void setTexturePriorities(const CCPriorityCalculator&) { } void setAlwaysReserveTextures(bool alwaysReserveTextures) { m_alwaysReserveTextures = alwaysReserveTextures; } bool alwaysReserveTextures() const { return m_alwaysReserveTextures; } @@ -360,8 +360,8 @@ private: bool m_nonFastScrollableRegionChanged; FloatPoint m_position; FloatPoint m_anchorPoint; - Color m_backgroundColor; - Color m_debugBorderColor; + SkColor m_backgroundColor; + SkColor m_debugBorderColor; float m_debugBorderWidth; String m_debugName; float m_opacity; diff --git a/Source/WebCore/platform/graphics/chromium/LayerPainterChromium.h b/Source/WebCore/platform/graphics/chromium/LayerPainterChromium.h index db6a884c1..bc0352e7c 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerPainterChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerPainterChromium.h @@ -33,12 +33,13 @@ class SkCanvas; namespace WebCore { +class FloatRect; class IntRect; class LayerPainterChromium { public: virtual ~LayerPainterChromium() { } - virtual void paint(SkCanvas*, const IntRect& contentRect, IntRect& opaque) = 0; + virtual void paint(SkCanvas*, const IntRect& contentRect, FloatRect& opaque) = 0; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index ca2d1902a..55b5929a3 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -38,13 +38,11 @@ #include "FloatQuad.h" #include "GeometryBinding.h" #include "GrTexture.h" -#include "ManagedTexture.h" -#include "NativeImageSkia.h" #include "NotImplemented.h" #include "PlatformColor.h" -#include "PlatformContextSkia.h" #include "SharedGraphicsContext3D.h" #include "SkBitmap.h" +#include "SkColor.h" #include "TextureManager.h" #include "ThrottledTextureUploader.h" #include "TraceEvent.h" @@ -58,6 +56,7 @@ #include "cc/CCRenderPass.h" #include "cc/CCRenderPassDrawQuad.h" #include "cc/CCRenderSurfaceFilters.h" +#include "cc/CCScopedTexture.h" #include "cc/CCSettings.h" #include "cc/CCSingleThreadProxy.h" #include "cc/CCSolidColorDrawQuad.h" @@ -133,10 +132,10 @@ public: } virtual ~UnthrottledTextureUploader() { } - virtual bool isBusy() { return false; } - virtual void beginUploads() { } - virtual void endUploads() { } - virtual void uploadTexture(CCGraphicsContext* context, LayerTextureUpdater::Texture* texture, TextureAllocator* allocator, const IntRect sourceRect, const IntRect destRect) { texture->updateRect(context, allocator, sourceRect, destRect); } + virtual bool isBusy() OVERRIDE { return false; } + virtual void beginUploads() OVERRIDE { } + virtual void endUploads() OVERRIDE { } + virtual void uploadTexture(CCGraphicsContext* context, LayerTextureUpdater::Texture* texture, TextureAllocator* allocator, const IntRect sourceRect, const IntRect destRect) OVERRIDE { texture->updateRect(context, allocator, sourceRect, destRect); } protected: UnthrottledTextureUploader() { } @@ -158,13 +157,14 @@ LayerRendererChromium::LayerRendererChromium(CCRendererClient* client, TextureUploaderOption textureUploaderSetting) : CCRenderer(client) , m_currentRenderPass(0) - , m_currentManagedTexture(0) + , m_currentTexture(0) , m_offscreenFramebufferId(0) , m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f)) , m_context(context) , m_defaultRenderPass(0) , m_isViewportChanged(false) , m_isFramebufferDiscarded(false) + , m_isUsingBindUniform(false) , m_visible(true) , m_textureUploaderSetting(textureUploaderSetting) { @@ -228,6 +228,8 @@ bool LayerRendererChromium::initialize() GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize)); m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context, extensions.contains("GL_EXT_texture_format_BGRA8888")); + m_isUsingBindUniform = extensions.contains("GL_CHROMIUM_bind_uniform_location"); + if (!initializeSharedObjects()) return false; @@ -272,8 +274,7 @@ void LayerRendererChromium::setVisible(bool visible) void LayerRendererChromium::releaseRenderPassTextures() { - if (m_implTextureManager) - m_implTextureManager->evictAndDeleteAllTextures(m_implTextureAllocator.get()); + m_renderPassTextures.clear(); } void LayerRendererChromium::viewportChanged() @@ -310,15 +311,58 @@ void LayerRendererChromium::clearRenderPass(const CCRenderPass* renderPass, cons GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST)); } +// static +IntSize LayerRendererChromium::renderPassTextureSize(const CCRenderPass* pass) +{ + return pass->framebufferOutputRect().size(); +} + +// static +GC3Denum LayerRendererChromium::renderPassTextureFormat(const CCRenderPass*) +{ + return GraphicsContext3D::RGBA; +} void LayerRendererChromium::decideRenderPassAllocationsForFrame(const CCRenderPassList& renderPassesInDrawOrder) { - // FIXME: Get this memory limit from GPU Memory Manager - size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes(); - size_t maxLimitBytes = TextureManager::highLimitBytes(viewportSize()); - size_t memoryLimitBytes = maxLimitBytes - contentsMemoryUseBytes > 0u ? maxLimitBytes - contentsMemoryUseBytes : 0u; + HashMap<int, const CCRenderPass*> passesInFrame; + for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) + passesInFrame.set(renderPassesInDrawOrder[i]->id(), renderPassesInDrawOrder[i].get()); + + Vector<int> passesToDelete; + HashMap<int, OwnPtr<CCScopedTexture> >::const_iterator passIterator; + for (passIterator = m_renderPassTextures.begin(); passIterator != m_renderPassTextures.end(); ++passIterator) { + const CCRenderPass* renderPassInFrame = passesInFrame.get(passIterator->first); + if (!renderPassInFrame) { + passesToDelete.append(passIterator->first); + continue; + } - m_implTextureManager->setMaxMemoryLimitBytes(memoryLimitBytes); + const IntSize& requiredSize = renderPassTextureSize(renderPassInFrame); + GC3Denum requiredFormat = renderPassTextureFormat(renderPassInFrame); + CCScopedTexture* texture = passIterator->second.get(); + ASSERT(texture); + + if (texture->id() && (texture->size() != requiredSize || texture->format() != requiredFormat)) + texture->free(); + } + + // Delete RenderPass textures from the previous frame that will not be used again. + for (size_t i = 0; i < passesToDelete.size(); ++i) + m_renderPassTextures.remove(passesToDelete[i]); + + for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) { + if (!m_renderPassTextures.contains(renderPassesInDrawOrder[i]->id())) { + OwnPtr<CCScopedTexture> texture = CCScopedTexture::create(m_implTextureAllocator.get()); + m_renderPassTextures.set(renderPassesInDrawOrder[i]->id(), texture.release()); + } + } +} + +bool LayerRendererChromium::haveCachedResourcesForRenderPassId(int id) const +{ + CCScopedTexture* texture = m_renderPassTextures.get(id); + return texture && texture->id(); } void LayerRendererChromium::beginDrawingFrame(const CCRenderPass* rootRenderPass) @@ -332,7 +376,7 @@ void LayerRendererChromium::beginDrawingFrame(const CCRenderPass* rootRenderPass if (viewportSize().isEmpty()) return; - TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0); + TRACE_EVENT0("cc", "LayerRendererChromium::drawLayers"); if (m_isViewportChanged) { // Only reshape when we know we are going to draw. Otherwise, the reshape // can leave the window at the wrong size if we never draw and the proper @@ -461,10 +505,10 @@ void LayerRendererChromium::drawDebugBorderQuad(const CCDebugBorderDrawQuad* qua LayerRendererChromium::toGLMatrix(&glMatrix[0], projectionMatrix() * renderMatrix); GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLocation(), 1, false, &glMatrix[0])); - const Color& color = quad->color(); - float alpha = color.alpha() / 255.0; + SkColor color = quad->color(); + float alpha = SkColorGetA(color) / 255.0; - GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (color.red() / 255.0) * alpha, (color.green() / 255.0) * alpha, (color.blue() / 255.0) * alpha, alpha)); + GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha)); GLC(context(), context()->lineWidth(quad->width())); @@ -472,7 +516,7 @@ void LayerRendererChromium::drawDebugBorderQuad(const CCDebugBorderDrawQuad* qua GLC(context(), context()->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short))); } -static inline SkBitmap applyFilters(LayerRendererChromium* layerRenderer, const WebKit::WebFilterOperations& filters, ManagedTexture* sourceTexture) +static inline SkBitmap applyFilters(LayerRendererChromium* layerRenderer, const WebKit::WebFilterOperations& filters, CCScopedTexture* sourceTexture) { if (filters.isEmpty()) return SkBitmap(); @@ -483,10 +527,10 @@ static inline SkBitmap applyFilters(LayerRendererChromium* layerRenderer, const layerRenderer->context()->flush(); - return CCRenderSurfaceFilters::apply(filters, sourceTexture->textureId(), sourceTexture->size(), filterContext.get()); + return CCRenderSurfaceFilters::apply(filters, sourceTexture->id(), sourceTexture->size(), filterContext.get()); } -void LayerRendererChromium::drawBackgroundFilters(const CCRenderPassDrawQuad* quad, const WebTransformationMatrix& contentsDeviceTransform) +PassOwnPtr<CCScopedTexture> LayerRendererChromium::drawBackgroundFilters(const CCRenderPassDrawQuad* quad, const WebTransformationMatrix& contentsDeviceTransform) { // This method draws a background filter, which applies a filter to any pixels behind the quad and seen through its background. // The algorithm works as follows: @@ -502,15 +546,16 @@ void LayerRendererChromium::drawBackgroundFilters(const CCRenderPassDrawQuad* qu // // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. - CCRenderSurface* drawingSurface = quad->renderPass()->targetSurface(); + // FIXME: When this algorithm changes, update CCLayerTreeHost::prioritizeTextures() accordingly. + if (quad->backgroundFilters().isEmpty()) - return; + return nullptr; // FIXME: We only allow background filters on an opaque render surface because other surfaces may contain // translucent pixels, and the contents behind those translucent pixels wouldn't have the filter applied. if (m_currentRenderPass->hasTransparentBackground()) - return; - ASSERT(!m_currentManagedTexture); + return nullptr; + ASSERT(!m_currentTexture); // FIXME: Do a single readback for both the surface and replica and cache the filtered results (once filter textures are not reused). IntRect deviceRect = enclosingIntRect(CCMathUtil::mapClippedRect(contentsDeviceTransform, sharedGeometryQuad().boundingBox())); @@ -522,22 +567,25 @@ void LayerRendererChromium::drawBackgroundFilters(const CCRenderPassDrawQuad* qu deviceRect.intersect(m_currentRenderPass->framebufferOutputRect()); - OwnPtr<ManagedTexture> deviceBackgroundTexture = ManagedTexture::create(m_implTextureManager.get()); + OwnPtr<CCScopedTexture> deviceBackgroundTexture = CCScopedTexture::create(m_implTextureAllocator.get()); if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect)) - return; + return nullptr; SkBitmap filteredDeviceBackground = applyFilters(this, quad->backgroundFilters(), deviceBackgroundTexture.get()); if (!filteredDeviceBackground.getTexture()) - return; + return nullptr; GrTexture* texture = reinterpret_cast<GrTexture*>(filteredDeviceBackground.getTexture()); int filteredDeviceBackgroundTextureId = texture->getTextureHandle(); - if (!drawingSurface->prepareBackgroundTexture(this)) - return; + OwnPtr<CCScopedTexture> backgroundTexture = CCScopedTexture::create(m_implTextureAllocator.get()); + if (!backgroundTexture->allocate(quad->quadRect().size(), GraphicsContext3D::RGBA)) + return nullptr; const CCRenderPass* targetRenderPass = m_currentRenderPass; - if (useManagedTexture(drawingSurface->backgroundTexture(), quad->quadRect())) { + bool usingBackgroundTexture = useScopedTexture(backgroundTexture.get(), quad->quadRect()); + + if (usingBackgroundTexture) { // Copy the readback pixels from device to the background texture for the surface. WebTransformationMatrix deviceToFramebufferTransform; deviceToFramebufferTransform.translate(quad->quadRect().width() / 2.0, quad->quadRect().height() / 2.0); @@ -547,17 +595,20 @@ void LayerRendererChromium::drawBackgroundFilters(const CCRenderPassDrawQuad* qu deviceToFramebufferTransform.translate(deviceRect.x(), deviceRect.y()); copyTextureToFramebuffer(filteredDeviceBackgroundTextureId, deviceRect.size(), deviceToFramebufferTransform); - - useRenderPass(targetRenderPass); } + + useRenderPass(targetRenderPass); + + if (!usingBackgroundTexture) + return nullptr; + return backgroundTexture.release(); } void LayerRendererChromium::drawRenderPassQuad(const CCRenderPassDrawQuad* quad) { - // The replica is always drawn first, so free after drawing the contents. - bool shouldReleaseTextures = !quad->isReplica(); - - CCRenderSurface* drawingSurface = quad->renderPass()->targetSurface(); + CCScopedTexture* contentsTexture = m_renderPassTextures.get(quad->renderPassId()); + if (!contentsTexture || !contentsTexture->id()) + return; WebTransformationMatrix renderTransform = quad->layerTransform(); // Apply a scaling factor to size the quad from 1x1 to its intended size. @@ -565,30 +616,29 @@ void LayerRendererChromium::drawRenderPassQuad(const CCRenderPassDrawQuad* quad) WebTransformationMatrix contentsDeviceTransform = WebTransformationMatrix(windowMatrix() * projectionMatrix() * renderTransform).to2dTransform(); // Can only draw surface if device matrix is invertible. - if (!contentsDeviceTransform.isInvertible() || !drawingSurface->hasValidContentsTexture()) { - if (shouldReleaseTextures) { - drawingSurface->releaseBackgroundTexture(); - drawingSurface->releaseContentsTexture(); - } + if (!contentsDeviceTransform.isInvertible()) return; - } - drawBackgroundFilters(quad, contentsDeviceTransform); + OwnPtr<CCScopedTexture> backgroundTexture = drawBackgroundFilters(quad, contentsDeviceTransform); // FIXME: Cache this value so that we don't have to do it for both the surface and its replica. // Apply filters to the contents texture. - SkBitmap filterBitmap = applyFilters(this, quad->filters(), drawingSurface->contentsTexture()); - int contentsTextureId = drawingSurface->contentsTexture()->textureId(); + SkBitmap filterBitmap = applyFilters(this, quad->filters(), contentsTexture); + int contentsTextureId = contentsTexture->id(); if (filterBitmap.getTexture()) { GrTexture* texture = reinterpret_cast<GrTexture*>(filterBitmap.getTexture()); contentsTextureId = texture->getTextureHandle(); } // Draw the background texture if there is one. - if (drawingSurface->hasValidBackgroundTexture()) - copyTextureToFramebuffer(drawingSurface->backgroundTexture()->textureId(), quad->quadRect().size(), quad->layerTransform()); + if (backgroundTexture) { + ASSERT(backgroundTexture->size() == quad->quadRect().size()); + copyTextureToFramebuffer(backgroundTexture->id(), quad->quadRect().size(), quad->layerTransform()); + } - FloatQuad deviceQuad = contentsDeviceTransform.mapQuad(sharedGeometryQuad()); + bool clipped = false; + FloatQuad deviceQuad = CCMathUtil::mapQuad(contentsDeviceTransform, sharedGeometryQuad(), clipped); + ASSERT(!clipped); CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceQuad.boundingBox())); CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceQuad); @@ -661,16 +711,12 @@ void LayerRendererChromium::drawRenderPassQuad(const CCRenderPassDrawQuad* quad) GLC(context(), context()->uniform3fv(shaderEdgeLocation, 8, edge)); } - // Map device space quad to surface space. - FloatQuad surfaceQuad = contentsDeviceTransform.inverse().mapQuad(deviceLayerEdges.floatQuad()); + // Map device space quad to surface space. contentsDeviceTransform has no perspective since it was generated with to2dTransform() so we don't need to project. + FloatQuad surfaceQuad = CCMathUtil::mapQuad(contentsDeviceTransform.inverse(), deviceLayerEdges.floatQuad(), clipped); + ASSERT(!clipped); drawTexturedQuad(quad->layerTransform(), quad->quadRect().width(), quad->quadRect().height(), quad->opacity(), surfaceQuad, shaderMatrixLocation, shaderAlphaLocation, shaderQuadLocation); - - if (shouldReleaseTextures) { - drawingSurface->releaseBackgroundTexture(); - drawingSurface->releaseContentsTexture(); - } } void LayerRendererChromium::drawSolidColorQuad(const CCSolidColorDrawQuad* quad) @@ -683,11 +729,11 @@ void LayerRendererChromium::drawSolidColorQuad(const CCSolidColorDrawQuad* quad) WebTransformationMatrix tileTransform = quad->quadTransform(); tileTransform.translate(tileRect.x() + tileRect.width() / 2.0, tileRect.y() + tileRect.height() / 2.0); - const Color& color = quad->color(); + SkColor color = quad->color(); float opacity = quad->opacity(); - float alpha = (color.alpha() / 255.0) * opacity; + float alpha = (SkColorGetA(color) / 255.0) * opacity; - GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (color.red() / 255.0) * alpha, (color.green() / 255.0) * alpha, (color.blue() / 255.0) * alpha, alpha)); + GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha)); drawTexturedQuad(tileTransform, tileRect.width(), tileRect.height(), 1.0, FloatQuad(), @@ -762,6 +808,7 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad) bool clipped = false; FloatQuad deviceLayerQuad = CCMathUtil::mapQuad(deviceTransform, FloatQuad(quad->layerRect()), clipped); + ASSERT(!clipped); TileProgramUniforms uniforms; // For now, we simply skip anti-aliasing with the quad is clipped. This only happens @@ -846,7 +893,8 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad) // Map quad to layer space. WebTransformationMatrix inverseDeviceTransform = deviceTransform.inverse(); - localQuad = inverseDeviceTransform.mapQuad(deviceQuad.floatQuad()); + localQuad = CCMathUtil::mapQuad(inverseDeviceTransform, deviceQuad.floatQuad(), clipped); + ASSERT(!clipped); } else { // Move fragment shader transform to vertex shader. We can do this while // still producing correct results as fragmentTexTransformLocation @@ -1002,8 +1050,17 @@ void LayerRendererChromium::drawTextureQuad(const CCTextureDrawQuad* quad) GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); - if (!quad->premultipliedAlpha()) - GLC(context(), context()->blendFunc(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); + if (!quad->premultipliedAlpha()) { + // As it turns out, the premultiplied alpha blending function (ONE, ONE_MINUS_SRC_ALPHA) + // will never cause the alpha channel to be set to anything less than 1.0 if it is + // initialized to that value! Therefore, premultipliedAlpha being false is the first + // situation we can generally see an alpha channel less than 1.0 coming out of the + // compositor. This is causing platform differences in some layout tests (see + // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use a separate + // blend function for the alpha channel to avoid modifying it. Don't use colorMask for this + // as it has performance implications on some platforms. + GLC(context(), context()->blendFuncSeparate(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA, GraphicsContext3D::ZERO, GraphicsContext3D::ONE)); + } WebTransformationMatrix quadTransform = quad->quadTransform(); IntRect quadRect = quad->quadRect(); @@ -1042,8 +1099,10 @@ void LayerRendererChromium::drawIOSurfaceQuad(const CCIOSurfaceDrawQuad* quad) GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0)); } -void LayerRendererChromium::drawHeadsUpDisplay(ManagedTexture* hudTexture, const IntSize& hudSize) +void LayerRendererChromium::drawHeadsUpDisplay(const CCScopedTexture* hudTexture, const IntSize& hudSize) { + ASSERT(hudTexture->id()); + GLC(m_context, m_context->enable(GraphicsContext3D::BLEND)); GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST)); @@ -1052,9 +1111,7 @@ void LayerRendererChromium::drawHeadsUpDisplay(ManagedTexture* hudTexture, const const HeadsUpDisplayProgram* program = headsUpDisplayProgram(); ASSERT(program && program->initialized()); GLC(m_context, m_context->activeTexture(GraphicsContext3D::TEXTURE0)); - if (!hudTexture->textureId()) - hudTexture->allocate(m_implTextureAllocator.get()); - GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, hudTexture->textureId())); + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, hudTexture->id())); GLC(m_context, m_context->useProgram(program->program())); GLC(m_context, m_context->uniform1i(program->fragmentShader().samplerLocation(), 0)); @@ -1070,9 +1127,6 @@ void LayerRendererChromium::finishDrawingFrame() { GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST)); GLC(m_context, m_context->disable(GraphicsContext3D::BLEND)); - - m_implTextureManager->unprotectAllTextures(); - m_implTextureManager->deleteEvictedTextures(m_implTextureAllocator.get()); } void LayerRendererChromium::toGLMatrix(float* flattened, const WebTransformationMatrix& m) @@ -1151,7 +1205,7 @@ void LayerRendererChromium::copyTextureToFramebuffer(int textureId, const IntSiz void LayerRendererChromium::finish() { - TRACE_EVENT("LayerRendererChromium::finish", this, 0); + TRACE_EVENT0("cc", "LayerRendererChromium::finish"); m_context->finish(); } @@ -1160,7 +1214,7 @@ bool LayerRendererChromium::swapBuffers(const IntRect& subBuffer) ASSERT(m_visible); ASSERT(!m_isFramebufferDiscarded); - TRACE_EVENT("LayerRendererChromium::swapBuffers", this, 0); + TRACE_EVENT0("cc", "LayerRendererChromium::swapBuffers"); // We're done! Time to swapbuffers! if (m_capabilities.usingPartialSwap) { @@ -1301,14 +1355,14 @@ void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& re } } -bool LayerRendererChromium::getFramebufferTexture(ManagedTexture* texture, const IntRect& deviceRect) +bool LayerRendererChromium::getFramebufferTexture(CCScopedTexture* texture, const IntRect& deviceRect) { - if (!texture->reserve(deviceRect.size(), GraphicsContext3D::RGB)) + ASSERT(!texture->id() || (texture->size() == deviceRect.size() && texture->format() == GraphicsContext3D::RGB)); + + if (!texture->id() && !texture->allocate(deviceRect.size(), GraphicsContext3D::RGB)) return false; - if (!texture->textureId()) - texture->allocate(m_implTextureAllocator.get()); - GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture->textureId())); + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture->id())); GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, texture->format(), deviceRect.x(), deviceRect.y(), deviceRect.width(), deviceRect.height(), 0)); return true; @@ -1316,13 +1370,13 @@ bool LayerRendererChromium::getFramebufferTexture(ManagedTexture* texture, const bool LayerRendererChromium::isCurrentRenderPass(const CCRenderPass* renderPass) { - return m_currentRenderPass == renderPass && !m_currentManagedTexture; + return m_currentRenderPass == renderPass && !m_currentTexture; } bool LayerRendererChromium::useRenderPass(const CCRenderPass* renderPass) { m_currentRenderPass = renderPass; - m_currentManagedTexture = 0; + m_currentTexture = 0; if (renderPass == m_defaultRenderPass) { GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); @@ -1330,27 +1384,31 @@ bool LayerRendererChromium::useRenderPass(const CCRenderPass* renderPass) return true; } - if (!renderPass->targetSurface()->prepareContentsTexture(this)) + CCScopedTexture* texture = m_renderPassTextures.get(renderPass->id()); + ASSERT(texture); + + if (!texture->id() && !texture->allocate(renderPassTextureSize(renderPass), renderPassTextureFormat(renderPass))) return false; - return bindFramebufferToTexture(renderPass->targetSurface()->contentsTexture(), renderPass->framebufferOutputRect()); + return bindFramebufferToTexture(texture, renderPass->framebufferOutputRect()); } -bool LayerRendererChromium::useManagedTexture(ManagedTexture* texture, const IntRect& viewportRect) +bool LayerRendererChromium::useScopedTexture(const CCScopedTexture* texture, const IntRect& viewportRect) { + ASSERT(texture->id()); + m_currentRenderPass = 0; - m_currentManagedTexture = texture; + m_currentTexture = texture; return bindFramebufferToTexture(texture, viewportRect); } -bool LayerRendererChromium::bindFramebufferToTexture(ManagedTexture* texture, const IntRect& framebufferRect) +bool LayerRendererChromium::bindFramebufferToTexture(const CCScopedTexture* texture, const IntRect& framebufferRect) { - GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId)); + ASSERT(texture->id()); - if (!texture->textureId()) - texture->allocate(m_implTextureAllocator.get()); - GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, texture->textureId(), 0)); + GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId)); + GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, texture->id(), 0)); #if !defined ( NDEBUG ) if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { @@ -1407,7 +1465,7 @@ void LayerRendererChromium::setDrawFramebufferRect(const IntRect& drawRect, bool bool LayerRendererChromium::initializeSharedObjects() { - TRACE_EVENT("LayerRendererChromium::initializeSharedObjects", this, 0); + TRACE_EVENT0("cc", "LayerRendererChromium::initializeSharedObjects"); makeContextCurrent(); // Create an FBO for doing offscreen rendering. @@ -1422,16 +1480,13 @@ bool LayerRendererChromium::initializeSharedObjects() GLC(m_context, m_context->flush()); - m_implTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()), - TextureManager::reclaimLimitBytes(viewportSize()), - m_capabilities.maxTextureSize); - m_textureCopier = AcceleratedTextureCopier::create(m_context); + m_textureCopier = AcceleratedTextureCopier::create(m_context, m_isUsingBindUniform); if (m_textureUploaderSetting == ThrottledUploader) m_textureUploader = ThrottledTextureUploader::create(m_context); else m_textureUploader = UnthrottledTextureUploader::create(); - m_contentsTextureAllocator = TrackingTextureAllocator::create(m_context); - m_implTextureAllocator = TrackingTextureAllocator::create(m_context); + m_contentsTextureAllocator = TrackingTextureAllocator::create(m_context, m_capabilities.maxTextureSize); + m_implTextureAllocator = TrackingTextureAllocator::create(m_context, m_capabilities.maxTextureSize); if (m_capabilities.usingTextureUsageHint) m_implTextureAllocator->setTextureUsageHint(TrackingTextureAllocator::FramebufferAttachment); if (m_capabilities.usingTextureStorageExtension) { @@ -1447,8 +1502,8 @@ const LayerRendererChromium::TileCheckerboardProgram* LayerRendererChromium::til if (!m_tileCheckerboardProgram) m_tileCheckerboardProgram = adoptPtr(new TileCheckerboardProgram(m_context)); if (!m_tileCheckerboardProgram->initialized()) { - TRACE_EVENT("LayerRendererChromium::checkerboardProgram::initalize", this, 0); - m_tileCheckerboardProgram->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::checkerboardProgram::initalize"); + m_tileCheckerboardProgram->initialize(m_context, m_isUsingBindUniform); } return m_tileCheckerboardProgram.get(); } @@ -1458,8 +1513,8 @@ const LayerRendererChromium::SolidColorProgram* LayerRendererChromium::solidColo if (!m_solidColorProgram) m_solidColorProgram = adoptPtr(new SolidColorProgram(m_context)); if (!m_solidColorProgram->initialized()) { - TRACE_EVENT("LayerRendererChromium::solidColorProgram::initialize", this, 0); - m_solidColorProgram->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::solidColorProgram::initialize"); + m_solidColorProgram->initialize(m_context, m_isUsingBindUniform); } return m_solidColorProgram.get(); } @@ -1469,8 +1524,8 @@ const LayerRendererChromium::HeadsUpDisplayProgram* LayerRendererChromium::heads if (!m_headsUpDisplayProgram) m_headsUpDisplayProgram = adoptPtr(new HeadsUpDisplayProgram(m_context)); if (!m_headsUpDisplayProgram->initialized()) { - TRACE_EVENT("LayerRendererChromium::headsUpDisplayProgram::initialize", this, 0); - m_headsUpDisplayProgram->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::headsUpDisplayProgram::initialize"); + m_headsUpDisplayProgram->initialize(m_context, m_isUsingBindUniform); } return m_headsUpDisplayProgram.get(); } @@ -1479,8 +1534,8 @@ const LayerRendererChromium::RenderPassProgram* LayerRendererChromium::renderPas { ASSERT(m_renderPassProgram); if (!m_renderPassProgram->initialized()) { - TRACE_EVENT("LayerRendererChromium::renderPassProgram::initialize", this, 0); - m_renderPassProgram->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::renderPassProgram::initialize"); + m_renderPassProgram->initialize(m_context, m_isUsingBindUniform); } return m_renderPassProgram.get(); } @@ -1490,8 +1545,8 @@ const LayerRendererChromium::RenderPassProgramAA* LayerRendererChromium::renderP if (!m_renderPassProgramAA) m_renderPassProgramAA = adoptPtr(new RenderPassProgramAA(m_context)); if (!m_renderPassProgramAA->initialized()) { - TRACE_EVENT("LayerRendererChromium::renderPassProgramAA::initialize", this, 0); - m_renderPassProgramAA->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::renderPassProgramAA::initialize"); + m_renderPassProgramAA->initialize(m_context, m_isUsingBindUniform); } return m_renderPassProgramAA.get(); } @@ -1501,8 +1556,8 @@ const LayerRendererChromium::RenderPassMaskProgram* LayerRendererChromium::rende if (!m_renderPassMaskProgram) m_renderPassMaskProgram = adoptPtr(new RenderPassMaskProgram(m_context)); if (!m_renderPassMaskProgram->initialized()) { - TRACE_EVENT("LayerRendererChromium::renderPassMaskProgram::initialize", this, 0); - m_renderPassMaskProgram->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::renderPassMaskProgram::initialize"); + m_renderPassMaskProgram->initialize(m_context, m_isUsingBindUniform); } return m_renderPassMaskProgram.get(); } @@ -1512,8 +1567,8 @@ const LayerRendererChromium::RenderPassMaskProgramAA* LayerRendererChromium::ren if (!m_renderPassMaskProgramAA) m_renderPassMaskProgramAA = adoptPtr(new RenderPassMaskProgramAA(m_context)); if (!m_renderPassMaskProgramAA->initialized()) { - TRACE_EVENT("LayerRendererChromium::renderPassMaskProgramAA::initialize", this, 0); - m_renderPassMaskProgramAA->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::renderPassMaskProgramAA::initialize"); + m_renderPassMaskProgramAA->initialize(m_context, m_isUsingBindUniform); } return m_renderPassMaskProgramAA.get(); } @@ -1522,8 +1577,8 @@ const LayerRendererChromium::TileProgram* LayerRendererChromium::tileProgram() { ASSERT(m_tileProgram); if (!m_tileProgram->initialized()) { - TRACE_EVENT("LayerRendererChromium::tileProgram::initialize", this, 0); - m_tileProgram->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::tileProgram::initialize"); + m_tileProgram->initialize(m_context, m_isUsingBindUniform); } return m_tileProgram.get(); } @@ -1532,8 +1587,8 @@ const LayerRendererChromium::TileProgramOpaque* LayerRendererChromium::tileProgr { ASSERT(m_tileProgramOpaque); if (!m_tileProgramOpaque->initialized()) { - TRACE_EVENT("LayerRendererChromium::tileProgramOpaque::initialize", this, 0); - m_tileProgramOpaque->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::tileProgramOpaque::initialize"); + m_tileProgramOpaque->initialize(m_context, m_isUsingBindUniform); } return m_tileProgramOpaque.get(); } @@ -1543,8 +1598,8 @@ const LayerRendererChromium::TileProgramAA* LayerRendererChromium::tileProgramAA if (!m_tileProgramAA) m_tileProgramAA = adoptPtr(new TileProgramAA(m_context)); if (!m_tileProgramAA->initialized()) { - TRACE_EVENT("LayerRendererChromium::tileProgramAA::initialize", this, 0); - m_tileProgramAA->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::tileProgramAA::initialize"); + m_tileProgramAA->initialize(m_context, m_isUsingBindUniform); } return m_tileProgramAA.get(); } @@ -1554,8 +1609,8 @@ const LayerRendererChromium::TileProgramSwizzle* LayerRendererChromium::tileProg if (!m_tileProgramSwizzle) m_tileProgramSwizzle = adoptPtr(new TileProgramSwizzle(m_context)); if (!m_tileProgramSwizzle->initialized()) { - TRACE_EVENT("LayerRendererChromium::tileProgramSwizzle::initialize", this, 0); - m_tileProgramSwizzle->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::tileProgramSwizzle::initialize"); + m_tileProgramSwizzle->initialize(m_context, m_isUsingBindUniform); } return m_tileProgramSwizzle.get(); } @@ -1565,8 +1620,8 @@ const LayerRendererChromium::TileProgramSwizzleOpaque* LayerRendererChromium::ti if (!m_tileProgramSwizzleOpaque) m_tileProgramSwizzleOpaque = adoptPtr(new TileProgramSwizzleOpaque(m_context)); if (!m_tileProgramSwizzleOpaque->initialized()) { - TRACE_EVENT("LayerRendererChromium::tileProgramSwizzleOpaque::initialize", this, 0); - m_tileProgramSwizzleOpaque->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::tileProgramSwizzleOpaque::initialize"); + m_tileProgramSwizzleOpaque->initialize(m_context, m_isUsingBindUniform); } return m_tileProgramSwizzleOpaque.get(); } @@ -1576,8 +1631,8 @@ const LayerRendererChromium::TileProgramSwizzleAA* LayerRendererChromium::tilePr if (!m_tileProgramSwizzleAA) m_tileProgramSwizzleAA = adoptPtr(new TileProgramSwizzleAA(m_context)); if (!m_tileProgramSwizzleAA->initialized()) { - TRACE_EVENT("LayerRendererChromium::tileProgramSwizzleAA::initialize", this, 0); - m_tileProgramSwizzleAA->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::tileProgramSwizzleAA::initialize"); + m_tileProgramSwizzleAA->initialize(m_context, m_isUsingBindUniform); } return m_tileProgramSwizzleAA.get(); } @@ -1587,8 +1642,8 @@ const LayerRendererChromium::TextureProgram* LayerRendererChromium::textureProgr if (!m_textureProgram) m_textureProgram = adoptPtr(new TextureProgram(m_context)); if (!m_textureProgram->initialized()) { - TRACE_EVENT("LayerRendererChromium::textureProgram::initialize", this, 0); - m_textureProgram->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::textureProgram::initialize"); + m_textureProgram->initialize(m_context, m_isUsingBindUniform); } return m_textureProgram.get(); } @@ -1598,8 +1653,8 @@ const LayerRendererChromium::TextureProgramFlip* LayerRendererChromium::textureP if (!m_textureProgramFlip) m_textureProgramFlip = adoptPtr(new TextureProgramFlip(m_context)); if (!m_textureProgramFlip->initialized()) { - TRACE_EVENT("LayerRendererChromium::textureProgramFlip::initialize", this, 0); - m_textureProgramFlip->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::textureProgramFlip::initialize"); + m_textureProgramFlip->initialize(m_context, m_isUsingBindUniform); } return m_textureProgramFlip.get(); } @@ -1609,8 +1664,8 @@ const LayerRendererChromium::TextureIOSurfaceProgram* LayerRendererChromium::tex if (!m_textureIOSurfaceProgram) m_textureIOSurfaceProgram = adoptPtr(new TextureIOSurfaceProgram(m_context)); if (!m_textureIOSurfaceProgram->initialized()) { - TRACE_EVENT("LayerRendererChromium::textureIOSurfaceProgram::initialize", this, 0); - m_textureIOSurfaceProgram->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::textureIOSurfaceProgram::initialize"); + m_textureIOSurfaceProgram->initialize(m_context, m_isUsingBindUniform); } return m_textureIOSurfaceProgram.get(); } @@ -1620,8 +1675,8 @@ const LayerRendererChromium::VideoYUVProgram* LayerRendererChromium::videoYUVPro if (!m_videoYUVProgram) m_videoYUVProgram = adoptPtr(new VideoYUVProgram(m_context)); if (!m_videoYUVProgram->initialized()) { - TRACE_EVENT("LayerRendererChromium::videoYUVProgram::initialize", this, 0); - m_videoYUVProgram->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::videoYUVProgram::initialize"); + m_videoYUVProgram->initialize(m_context, m_isUsingBindUniform); } return m_videoYUVProgram.get(); } @@ -1631,8 +1686,8 @@ const LayerRendererChromium::VideoStreamTextureProgram* LayerRendererChromium::v if (!m_videoStreamTextureProgram) m_videoStreamTextureProgram = adoptPtr(new VideoStreamTextureProgram(m_context)); if (!m_videoStreamTextureProgram->initialized()) { - TRACE_EVENT("LayerRendererChromium::streamTextureProgram::initialize", this, 0); - m_videoStreamTextureProgram->initialize(m_context); + TRACE_EVENT0("cc", "LayerRendererChromium::streamTextureProgram::initialize"); + m_videoStreamTextureProgram->initialize(m_context, m_isUsingBindUniform); } return m_videoStreamTextureProgram.get(); } diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h index 34254b00b..6afe66806 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -51,13 +51,13 @@ class CCDebugBorderDrawQuad; class CCDrawQuad; class CCIOSurfaceDrawQuad; class CCRenderPassDrawQuad; +class CCScopedTexture; class CCSolidColorDrawQuad; class CCStreamVideoDrawQuad; class CCTextureDrawQuad; class CCTileDrawQuad; class CCYUVVideoDrawQuad; class GeometryBinding; -class ManagedTexture; class ScopedEnsureFramebufferAllocation; // Class that handles drawing of composited render layers using GL. @@ -80,11 +80,13 @@ public: const FloatQuad& sharedGeometryQuad() const { return m_sharedGeometryQuad; } virtual void decideRenderPassAllocationsForFrame(const CCRenderPassList&) OVERRIDE; + virtual bool haveCachedResourcesForRenderPassId(int id) const OVERRIDE; + virtual void beginDrawingFrame(const CCRenderPass* defaultRenderPass) OVERRIDE; virtual void drawRenderPass(const CCRenderPass*, const FloatRect& framebufferDamageRect) OVERRIDE; virtual void finishDrawingFrame() OVERRIDE; - virtual void drawHeadsUpDisplay(ManagedTexture*, const IntSize& hudSize) OVERRIDE; + virtual void drawHeadsUpDisplay(const CCScopedTexture*, const IntSize& hudSize) OVERRIDE; // waits for rendering to finish virtual void finish() OVERRIDE; @@ -98,9 +100,8 @@ public: const GeometryBinding* sharedGeometry() const { return m_sharedGeometry.get(); } virtual void getFramebufferPixels(void *pixels, const IntRect&) OVERRIDE; - bool getFramebufferTexture(ManagedTexture*, const IntRect& deviceRect); + bool getFramebufferTexture(CCScopedTexture*, const IntRect& deviceRect); - virtual TextureManager* implTextureManager() const OVERRIDE { return m_implTextureManager.get(); } virtual TextureCopier* textureCopier() const OVERRIDE { return m_textureCopier.get(); } virtual TextureUploader* textureUploader() const OVERRIDE { return m_textureUploader.get(); } virtual TextureAllocator* implTextureAllocator() const OVERRIDE { return m_implTextureAllocator.get(); } @@ -123,13 +124,15 @@ protected: bool isFramebufferDiscarded() const { return m_isFramebufferDiscarded; } bool initialize(); + void releaseRenderPassTextures(); + private: static void toGLMatrix(float*, const WebKit::WebTransformationMatrix&); void drawQuad(const CCDrawQuad*); void drawCheckerboardQuad(const CCCheckerboardDrawQuad*); void drawDebugBorderQuad(const CCDebugBorderDrawQuad*); - void drawBackgroundFilters(const CCRenderPassDrawQuad*, const WebKit::WebTransformationMatrix& deviceTransform); + PassOwnPtr<CCScopedTexture> drawBackgroundFilters(const CCRenderPassDrawQuad*, const WebKit::WebTransformationMatrix& deviceTransform); void drawRenderPassQuad(const CCRenderPassDrawQuad*); void drawSolidColorQuad(const CCSolidColorDrawQuad*); void drawStreamVideoQuad(const CCStreamVideoDrawQuad*); @@ -140,17 +143,15 @@ private: void setDrawFramebufferRect(const IntRect&, bool flipY); - // The current drawing target is either a RenderPass or ManagedTexture. Use these functions to switch to a new drawing target. + // The current drawing target is either a RenderPass or ScopedTexture. Use these functions to switch to a new drawing target. bool useRenderPass(const CCRenderPass*); - bool useManagedTexture(ManagedTexture*, const IntRect& viewportRect); + bool useScopedTexture(const CCScopedTexture*, const IntRect& viewportRect); bool isCurrentRenderPass(const CCRenderPass*); - bool bindFramebufferToTexture(ManagedTexture*, const IntRect& viewportRect); + bool bindFramebufferToTexture(const CCScopedTexture*, const IntRect& viewportRect); void clearRenderPass(const CCRenderPass*, const FloatRect& framebufferDamageRect); - void releaseRenderPassTextures(); - bool makeContextCurrent(); bool initializeSharedObjects(); @@ -168,10 +169,13 @@ private: // WebGraphicsContext3D::WebGraphicsContextLostCallback implementation. virtual void onContextLost() OVERRIDE; + static IntSize renderPassTextureSize(const CCRenderPass*); + static GC3Denum renderPassTextureFormat(const CCRenderPass*); + LayerRendererCapabilities m_capabilities; const CCRenderPass* m_currentRenderPass; - ManagedTexture* m_currentManagedTexture; + const CCScopedTexture* m_currentTexture; unsigned m_offscreenFramebufferId; OwnPtr<GeometryBinding> m_sharedGeometry; @@ -257,18 +261,20 @@ private: OwnPtr<SolidColorProgram> m_solidColorProgram; OwnPtr<HeadsUpDisplayProgram> m_headsUpDisplayProgram; - OwnPtr<TextureManager> m_implTextureManager; OwnPtr<AcceleratedTextureCopier> m_textureCopier; OwnPtr<TextureUploader> m_textureUploader; OwnPtr<TrackingTextureAllocator> m_contentsTextureAllocator; OwnPtr<TrackingTextureAllocator> m_implTextureAllocator; + HashMap<int, OwnPtr<CCScopedTexture> > m_renderPassTextures; + WebKit::WebGraphicsContext3D* m_context; const CCRenderPass* m_defaultRenderPass; bool m_isViewportChanged; bool m_isFramebufferDiscarded; + bool m_isUsingBindUniform; bool m_visible; TextureUploaderOption m_textureUploaderSetting; }; diff --git a/Source/WebCore/platform/graphics/chromium/LayerTextureSubImage.cpp b/Source/WebCore/platform/graphics/chromium/LayerTextureSubImage.cpp index 4aa9965e7..b87b43d94 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTextureSubImage.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerTextureSubImage.cpp @@ -68,7 +68,7 @@ void LayerTextureSubImage::uploadWithTexSubImage(const uint8_t* image, const Int const IntRect& sourceRect, const IntRect& destRect, GC3Denum format, CCGraphicsContext* context) { - TRACE_EVENT("LayerTextureSubImage::uploadWithTexSubImage", this, 0); + TRACE_EVENT0("cc", "LayerTextureSubImage::uploadWithTexSubImage"); if (!m_subImage) m_subImage = adoptArrayPtr(new uint8_t[m_subImageSize.width() * m_subImageSize.height() * 4]); @@ -101,7 +101,7 @@ void LayerTextureSubImage::uploadWithMapTexSubImage(const uint8_t* image, const const IntRect& sourceRect, const IntRect& destRect, GC3Denum format, CCGraphicsContext* context) { - TRACE_EVENT("LayerTextureSubImage::uploadWithMapTexSubImage", this, 0); + TRACE_EVENT0("cc", "LayerTextureSubImage::uploadWithMapTexSubImage"); WebKit::WebGraphicsContext3D* context3d = context->context3D(); if (!context3d) { // FIXME: Implement this path for software compositing. diff --git a/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h index cec8ebcd8..fd8ed883c 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h +++ b/Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h @@ -29,8 +29,9 @@ #if USE(ACCELERATED_COMPOSITING) -#include "ManagedTexture.h" #include "GraphicsTypes3D.h" +#include "cc/CCGraphicsContext.h" +#include "cc/CCPrioritizedTexture.h" #include <wtf/RefCounted.h> namespace WebCore { @@ -48,14 +49,15 @@ public: public: virtual ~Texture() { } - ManagedTexture* texture() { return m_texture.get(); } + CCPrioritizedTexture* texture() { return m_texture.get(); } + void swapTextureWith(OwnPtr<CCPrioritizedTexture>& texture) { m_texture.swap(texture); } virtual void prepareRect(const IntRect& /* sourceRect */) { } virtual void updateRect(CCGraphicsContext*, TextureAllocator*, const IntRect& sourceRect, const IntRect& destRect) = 0; protected: - explicit Texture(PassOwnPtr<ManagedTexture> texture) : m_texture(texture) { } + explicit Texture(PassOwnPtr<CCPrioritizedTexture> texture) : m_texture(texture) { } private: - OwnPtr<ManagedTexture> m_texture; + OwnPtr<CCPrioritizedTexture> m_texture; }; virtual ~LayerTextureUpdater() { } @@ -65,7 +67,7 @@ public: SampledTexelFormatBGRA, SampledTexelFormatInvalid, }; - virtual PassOwnPtr<Texture> createTexture(TextureManager*) = 0; + virtual PassOwnPtr<Texture> createTexture(CCPrioritizedTextureManager*) = 0; // Returns the format of the texel uploaded by this interface. // This format should not be confused by texture internal format. // This format specifies the component order in the sampled texel. @@ -73,7 +75,7 @@ public: virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) = 0; // The |resultingOpaqueRect| gives back a region of the layer that was painted opaque. If the layer is marked opaque in the updater, // then this region should be ignored in preference for the entire layer's area. - virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect) { } + virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) { } // Set true by the layer when it is known that the entire output is going to be opaque. virtual void setOpaque(bool) { } diff --git a/Source/WebCore/platform/graphics/chromium/LinkHighlight.cpp b/Source/WebCore/platform/graphics/chromium/LinkHighlight.cpp index 3bc1e63da..1b2c61e69 100644 --- a/Source/WebCore/platform/graphics/chromium/LinkHighlight.cpp +++ b/Source/WebCore/platform/graphics/chromium/LinkHighlight.cpp @@ -92,7 +92,7 @@ ContentLayerChromium* LinkHighlight::contentLayer() return m_contentLayer.get(); } -void LinkHighlight::paintContents(SkCanvas* canvas, const IntRect&, IntRect&) +void LinkHighlight::paintContents(SkCanvas* canvas, const IntRect&, FloatRect&) { PlatformContextSkia platformContext(canvas); GraphicsContext gc(&platformContext); diff --git a/Source/WebCore/platform/graphics/chromium/LinkHighlight.h b/Source/WebCore/platform/graphics/chromium/LinkHighlight.h index 1fbef9ba9..1ccc3ebdf 100644 --- a/Source/WebCore/platform/graphics/chromium/LinkHighlight.h +++ b/Source/WebCore/platform/graphics/chromium/LinkHighlight.h @@ -45,7 +45,7 @@ public: ContentLayerChromium* contentLayer(); // ContentLayerDelegate implementation. - virtual void paintContents(SkCanvas*, const IntRect& clipRect, IntRect& opaque) OVERRIDE; + virtual void paintContents(SkCanvas*, const IntRect& clipRect, FloatRect& opaque) OVERRIDE; // CCLayerAnimationDelegate implementation. virtual void notifyAnimationStarted(double time) OVERRIDE; diff --git a/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.cpp b/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.cpp index 04548aecb..a5155e272 100644 --- a/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.cpp +++ b/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.cpp @@ -31,8 +31,10 @@ #include "GraphicsContext.h" #include "IntRect.h" #include "PlatformContextSkia.h" +#include <public/WebFloatRect.h> #include <public/WebRect.h> +using WebKit::WebFloatRect; using WebKit::WebRect; namespace WebCore { @@ -47,7 +49,7 @@ OpaqueRectTrackingContentLayerDelegate::~OpaqueRectTrackingContentLayerDelegate( { } -void OpaqueRectTrackingContentLayerDelegate::paintContents(SkCanvas* canvas, const WebRect& clip, WebRect& opaque) +void OpaqueRectTrackingContentLayerDelegate::paintContents(SkCanvas* canvas, const WebRect& clip, WebFloatRect& opaque) { PlatformContextSkia platformContext(canvas); platformContext.setTrackOpaqueRegion(!m_opaque); @@ -62,8 +64,7 @@ void OpaqueRectTrackingContentLayerDelegate::paintContents(SkCanvas* canvas, con // Transform tracked opaque paints back to our layer's content space. ASSERT(canvasToContentTransform.isInvertible()); ASSERT(canvasToContentTransform.preservesAxisAlignment()); - FloatRect opaqueCanvasRect = platformContext.opaqueRegion().asRect(); - opaque = enclosedIntRect(canvasToContentTransform.mapRect(opaqueCanvasRect)); + opaque = canvasToContentTransform.mapRect(platformContext.opaqueRegion().asRect()); } } diff --git a/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.h b/Source/WebCore/platform/graphics/chromium/OpaqueRectTrackingContentLayerDelegate.h index e325b36e1..bb5c2ae96 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::WebRect& opaque) OVERRIDE; + virtual void paintContents(SkCanvas*, const WebKit::WebRect& clip, WebKit::WebFloatRect& opaque) OVERRIDE; private: GraphicsContextPainter* m_painter; diff --git a/Source/WebCore/platform/graphics/chromium/ProgramBinding.cpp b/Source/WebCore/platform/graphics/chromium/ProgramBinding.cpp index 6afbb34ae..1abc2186a 100644 --- a/Source/WebCore/platform/graphics/chromium/ProgramBinding.cpp +++ b/Source/WebCore/platform/graphics/chromium/ProgramBinding.cpp @@ -34,6 +34,7 @@ #include "LayerRendererChromium.h" #include "TraceEvent.h" #include <public/WebGraphicsContext3D.h> +#include <wtf/text/CString.h> using WebKit::WebGraphicsContext3D; @@ -41,6 +42,8 @@ namespace WebCore { ProgramBindingBase::ProgramBindingBase() : m_program(0) + , m_vertexShaderId(0) + , m_fragmentShaderId(0) , m_initialized(false) { } @@ -49,6 +52,8 @@ ProgramBindingBase::~ProgramBindingBase() { // If you hit these asserts, you initialized but forgot to call cleanup(). ASSERT(!m_program); + ASSERT(!m_vertexShaderId); + ASSERT(!m_fragmentShaderId); ASSERT(!m_initialized); } @@ -60,10 +65,43 @@ static bool contextLost(WebGraphicsContext3D* context) void ProgramBindingBase::init(WebGraphicsContext3D* context, const String& vertexShader, const String& fragmentShader) { - m_program = createShaderProgram(context, vertexShader, fragmentShader); + TRACE_EVENT("ProgramBindingBase::init", this, 0); + m_vertexShaderId = loadShader(context, GraphicsContext3D::VERTEX_SHADER, vertexShader); + if (!m_vertexShaderId) { + if (!contextLost(context)) + LOG_ERROR("Failed to create vertex shader"); + return; + } + + m_fragmentShaderId = loadShader(context, GraphicsContext3D::FRAGMENT_SHADER, fragmentShader); + if (!m_fragmentShaderId) { + GLC(context, context->deleteShader(m_vertexShaderId)); + m_vertexShaderId = 0; + if (!contextLost(context)) + LOG_ERROR("Failed to create fragment shader"); + return; + } + + m_program = createShaderProgram(context, m_vertexShaderId, m_fragmentShaderId); ASSERT(m_program || contextLost(context)); } +void ProgramBindingBase::link(WebGraphicsContext3D* context) +{ + GLC(context, context->linkProgram(m_program)); + cleanupShaders(context); +#ifndef NDEBUG + int linked = 0; + GLC(context, context->getProgramiv(m_program, GraphicsContext3D::LINK_STATUS, &linked)); + if (!linked) { + if (!contextLost(context)) + LOG_ERROR("Failed to link shader program"); + GLC(context, context->deleteProgram(m_program)); + return; + } +#endif +} + void ProgramBindingBase::cleanup(WebGraphicsContext3D* context) { m_initialized = false; @@ -73,6 +111,8 @@ void ProgramBindingBase::cleanup(WebGraphicsContext3D* context) ASSERT(context); GLC(context, context->deleteProgram(m_program)); m_program = 0; + + cleanupShaders(context); } unsigned ProgramBindingBase::loadShader(WebGraphicsContext3D* context, unsigned type, const String& shaderSource) @@ -94,24 +134,8 @@ unsigned ProgramBindingBase::loadShader(WebGraphicsContext3D* context, unsigned return shader; } -unsigned ProgramBindingBase::createShaderProgram(WebGraphicsContext3D* context, const String& vertexShaderSource, const String& fragmentShaderSource) +unsigned ProgramBindingBase::createShaderProgram(WebGraphicsContext3D* context, unsigned vertexShader, unsigned fragmentShader) { - TRACE_EVENT0("cc", "ProgramBindingBase::createShaderProgram"); - unsigned vertexShader = loadShader(context, GraphicsContext3D::VERTEX_SHADER, vertexShaderSource); - if (!vertexShader) { - if (!contextLost(context)) - LOG_ERROR("Failed to create vertex shader"); - return 0; - } - - unsigned fragmentShader = loadShader(context, GraphicsContext3D::FRAGMENT_SHADER, fragmentShaderSource); - if (!fragmentShader) { - GLC(context, context->deleteShader(vertexShader)); - if (!contextLost(context)) - LOG_ERROR("Failed to create fragment shader"); - return 0; - } - unsigned programObject = context->createProgram(); if (!programObject) { if (!contextLost(context)) @@ -126,23 +150,21 @@ unsigned ProgramBindingBase::createShaderProgram(WebGraphicsContext3D* context, GLC(context, context->bindAttribLocation(programObject, GeometryBinding::positionAttribLocation(), "a_position")); GLC(context, context->bindAttribLocation(programObject, GeometryBinding::texCoordAttribLocation(), "a_texCoord")); - GLC(context, context->linkProgram(programObject)); -#ifndef NDEBUG - int linked = 0; - GLC(context, context->getProgramiv(programObject, GraphicsContext3D::LINK_STATUS, &linked)); - if (!linked) { - if (!contextLost(context)) - LOG_ERROR("Failed to link shader program"); - GLC(context, context->deleteProgram(programObject)); - return 0; - } -#endif - - GLC(context, context->deleteShader(vertexShader)); - GLC(context, context->deleteShader(fragmentShader)); return programObject; } +void ProgramBindingBase::cleanupShaders(WebGraphicsContext3D* context) +{ + if (m_vertexShaderId) { + GLC(context, context->deleteShader(m_vertexShaderId)); + m_vertexShaderId = 0; + } + if (m_fragmentShaderId) { + GLC(context, context->deleteShader(m_fragmentShaderId)); + m_fragmentShaderId = 0; + } +} + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/ProgramBinding.h b/Source/WebCore/platform/graphics/chromium/ProgramBinding.h index 39048f903..c2d47dffc 100644 --- a/Source/WebCore/platform/graphics/chromium/ProgramBinding.h +++ b/Source/WebCore/platform/graphics/chromium/ProgramBinding.h @@ -42,6 +42,7 @@ public: ~ProgramBindingBase(); void init(WebKit::WebGraphicsContext3D*, const String& vertexShader, const String& fragmentShader); + void link(WebKit::WebGraphicsContext3D*); void cleanup(WebKit::WebGraphicsContext3D*); unsigned program() const { ASSERT(m_initialized); return m_program; } @@ -50,9 +51,12 @@ public: protected: unsigned loadShader(WebKit::WebGraphicsContext3D*, unsigned type, const String& shaderSource); - unsigned createShaderProgram(WebKit::WebGraphicsContext3D*, const String& vertexShaderSource, const String& fragmentShaderSource); + unsigned createShaderProgram(WebKit::WebGraphicsContext3D*, unsigned vertexShader, unsigned fragmentShader); + void cleanupShaders(WebKit::WebGraphicsContext3D*); unsigned m_program; + unsigned m_vertexShaderId; + unsigned m_fragmentShaderId; bool m_initialized; }; @@ -64,14 +68,24 @@ public: ProgramBindingBase::init(context, m_vertexShader.getShaderString(), m_fragmentShader.getShaderString()); } - void initialize(WebKit::WebGraphicsContext3D* context) + void initialize(WebKit::WebGraphicsContext3D* context, bool usingBindUniform) { ASSERT(context); ASSERT(m_program); ASSERT(!m_initialized); - m_vertexShader.init(context, m_program); - m_fragmentShader.init(context, m_program); + // Need to bind uniforms before linking + if (!usingBindUniform) + link(context); + + int baseUniformIndex = 0; + m_vertexShader.init(context, m_program, usingBindUniform, &baseUniformIndex); + m_fragmentShader.init(context, m_program, usingBindUniform, &baseUniformIndex); + + // Link after binding uniforms + if (usingBindUniform) + link(context); + m_initialized = true; } diff --git a/Source/WebCore/platform/graphics/chromium/RateLimiter.cpp b/Source/WebCore/platform/graphics/chromium/RateLimiter.cpp index 232f04719..55a190290 100644 --- a/Source/WebCore/platform/graphics/chromium/RateLimiter.cpp +++ b/Source/WebCore/platform/graphics/chromium/RateLimiter.cpp @@ -29,10 +29,35 @@ #include "RateLimiter.h" #include "TraceEvent.h" +#include "cc/CCProxy.h" +#include "cc/CCThread.h" #include <public/WebGraphicsContext3D.h> namespace WebCore { +class RateLimiter::Task : public CCThread::Task { +public: + static PassOwnPtr<Task> create(RateLimiter* rateLimiter) + { + return adoptPtr(new Task(rateLimiter)); + } + virtual ~Task() { } + +private: + explicit Task(RateLimiter* rateLimiter) + : CCThread::Task(this) + , m_rateLimiter(rateLimiter) + { + } + + virtual void performTask() OVERRIDE + { + m_rateLimiter->rateLimitContext(); + } + + RefPtr<RateLimiter> m_rateLimiter; +}; + PassRefPtr<RateLimiter> RateLimiter::create(WebKit::WebGraphicsContext3D* context, RateLimiterClient *client) { return adoptRef(new RateLimiter(context, client)); @@ -40,7 +65,7 @@ PassRefPtr<RateLimiter> RateLimiter::create(WebKit::WebGraphicsContext3D* contex RateLimiter::RateLimiter(WebKit::WebGraphicsContext3D* context, RateLimiterClient *client) : m_context(context) - , m_timer(this, &RateLimiter::rateLimitContext) + , m_active(false) , m_client(client) { ASSERT(context); @@ -52,19 +77,28 @@ RateLimiter::~RateLimiter() void RateLimiter::start() { - if (!m_timer.isActive()) - m_timer.startOneShot(0); + if (m_active) + return; + + TRACE_EVENT0("cc", "RateLimiter::start"); + m_active = true; + CCProxy::mainThread()->postTask(RateLimiter::Task::create(this)); } void RateLimiter::stop() { - m_timer.stop(); + TRACE_EVENT0("cc", "RateLimiter::stop"); + m_client = 0; } -void RateLimiter::rateLimitContext(Timer<RateLimiter>*) +void RateLimiter::rateLimitContext() { + if (!m_client) + return; + TRACE_EVENT0("cc", "RateLimiter::rateLimitContext"); + m_active = false; m_client->rateLimit(); m_context->rateLimitOffscreenContextCHROMIUM(); } diff --git a/Source/WebCore/platform/graphics/chromium/RateLimiter.h b/Source/WebCore/platform/graphics/chromium/RateLimiter.h index b786b90d4..0548fde5e 100644 --- a/Source/WebCore/platform/graphics/chromium/RateLimiter.h +++ b/Source/WebCore/platform/graphics/chromium/RateLimiter.h @@ -28,9 +28,8 @@ #if USE(ACCELERATED_COMPOSITING) -#include "Timer.h" +#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> namespace WebKit { class WebGraphicsContext3D; @@ -43,21 +42,29 @@ public: virtual void rateLimit() = 0; }; -// A class containing a timer, which calls rateLimitCHROMIUM on expiry +// A RateLimiter can be used to make sure that a single context does not dominate all execution time. +// To use, construct a RateLimiter class around the context and call start() whenever calls are made on the +// context outside of normal flow control. RateLimiter will block if the context is too far ahead of the +// compositor. class RateLimiter : public RefCounted<RateLimiter> { public: static PassRefPtr<RateLimiter> create(WebKit::WebGraphicsContext3D*, RateLimiterClient*); ~RateLimiter(); void start(); + + // Context and client will not be accessed after stop(). void stop(); private: RateLimiter(WebKit::WebGraphicsContext3D*, RateLimiterClient*); + class Task; + friend class Task; + void rateLimitContext(); + WebKit::WebGraphicsContext3D* m_context; - Timer<RateLimiter> m_timer; - void rateLimitContext(Timer<RateLimiter>*); + bool m_active; RateLimiterClient *m_client; }; diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp index a5c4c6082..fb2dd8bc6 100644 --- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp @@ -29,7 +29,6 @@ #include "RenderSurfaceChromium.h" -#include "FilterOperations.h" #include "LayerChromium.h" #include "cc/CCMathUtil.h" #include <public/WebTransformationMatrix.h> @@ -59,9 +58,9 @@ FloatRect RenderSurfaceChromium::drawableContentRect() const { FloatRect localContentRect(-0.5 * m_contentRect.width(), -0.5 * m_contentRect.height(), m_contentRect.width(), m_contentRect.height()); - FloatRect drawableContentRect = m_drawTransform.mapRect(localContentRect); + FloatRect drawableContentRect = CCMathUtil::mapClippedRect(m_drawTransform, localContentRect); if (m_owningLayer->replicaLayer()) - drawableContentRect.unite(m_replicaDrawTransform.mapRect(localContentRect)); + drawableContentRect.unite(CCMathUtil::mapClippedRect(m_replicaDrawTransform, localContentRect)); return drawableContentRect; } diff --git a/Source/WebCore/platform/graphics/chromium/ScrollbarLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ScrollbarLayerChromium.cpp index 5e23e9345..56c96a74a 100644 --- a/Source/WebCore/platform/graphics/chromium/ScrollbarLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ScrollbarLayerChromium.cpp @@ -76,12 +76,17 @@ void ScrollbarLayerChromium::pushPropertiesTo(CCLayerImpl* layer) scrollbarLayer->setScrollbarOverlayStyle(m_scrollbarOverlayStyle); - if (m_background && m_background->texture()->isReserved()) - scrollbarLayer->setBackgroundTextureId(m_background->texture()->textureId()); + if (m_backTrack && m_backTrack->texture()->haveBackingTexture()) + scrollbarLayer->setBackTrackTextureId(m_backTrack->texture()->textureId()); else - scrollbarLayer->setBackgroundTextureId(0); + scrollbarLayer->setBackTrackTextureId(0); - if (m_thumb && m_thumb->texture()->isReserved()) + if (m_foreTrack && m_foreTrack->texture()->haveBackingTexture()) + scrollbarLayer->setForeTrackTextureId(m_foreTrack->texture()->textureId()); + else + scrollbarLayer->setForeTrackTextureId(0); + + if (m_thumb && m_thumb->texture()->haveBackingTexture()) scrollbarLayer->setThumbTextureId(m_thumb->texture()->textureId()); else scrollbarLayer->setThumbTextureId(0); @@ -106,12 +111,12 @@ void ScrollbarLayerChromium::pushPropertiesTo(CCLayerImpl* layer) class ScrollbarBackgroundPainter : public LayerPainterChromium { WTF_MAKE_NONCOPYABLE(ScrollbarBackgroundPainter); public: - static PassOwnPtr<ScrollbarBackgroundPainter> create(ScrollbarThemeClient* scrollbar, ScrollbarThemeComposite* theme) + static PassOwnPtr<ScrollbarBackgroundPainter> create(ScrollbarThemeClient* scrollbar, ScrollbarThemeComposite* theme, ScrollbarPart trackPart) { - return adoptPtr(new ScrollbarBackgroundPainter(scrollbar, theme)); + return adoptPtr(new ScrollbarBackgroundPainter(scrollbar, theme, trackPart)); } - virtual void paint(SkCanvas* canvas, const IntRect& contentRect, IntRect&) OVERRIDE + virtual void paint(SkCanvas* canvas, const IntRect& contentRect, FloatRect&) OVERRIDE { PlatformContextSkia platformContext(canvas); platformContext.setDrawingToImageBuffer(true); @@ -138,26 +143,22 @@ public: m_theme->paintTrackBackground(&context, m_scrollbar, trackPaintRect); bool thumbPresent = m_theme->hasThumb(m_scrollbar); - if (thumbPresent) { - // FIXME: There's no "paint the whole track" part. Drawing both the - // BackTrackPart and the ForwardTrackPart in their splitTrack rects - // ends up leaving a distinctive line. Painting one part as the - // entire track appears to be identical to painting both and - // covering up the split between them with the thumb. - m_theme->paintTrackPiece(&context, m_scrollbar, trackPaintRect, BackTrackPart); - } + if (thumbPresent) + m_theme->paintTrackPiece(&context, m_scrollbar, trackPaintRect, m_trackPart); m_theme->paintTickmarks(&context, m_scrollbar, trackPaintRect); } private: - ScrollbarBackgroundPainter(ScrollbarThemeClient* scrollbar, ScrollbarThemeComposite* theme) + ScrollbarBackgroundPainter(ScrollbarThemeClient* scrollbar, ScrollbarThemeComposite* theme, ScrollbarPart trackPart) : m_scrollbar(scrollbar) , m_theme(theme) + , m_trackPart(trackPart) { } ScrollbarThemeClient* m_scrollbar; ScrollbarThemeComposite* m_theme; + ScrollbarPart m_trackPart; }; class ScrollbarThumbPainter : public LayerPainterChromium { @@ -168,7 +169,7 @@ public: return adoptPtr(new ScrollbarThumbPainter(scrollbar, theme)); } - virtual void paint(SkCanvas* canvas, const IntRect& contentRect, IntRect& opaque) OVERRIDE + virtual void paint(SkCanvas* canvas, const IntRect& contentRect, FloatRect& opaque) OVERRIDE { PlatformContextSkia platformContext(canvas); platformContext.setDrawingToImageBuffer(true); @@ -193,8 +194,8 @@ private: void ScrollbarLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) { if (!host || host != layerTreeHost()) { - m_backgroundUpdater.clear(); - m_background.clear(); + m_backTrackUpdater.clear(); + m_backTrack.clear(); m_thumbUpdater.clear(); m_thumb.clear(); } @@ -207,10 +208,18 @@ void ScrollbarLayerChromium::createTextureUpdaterIfNeeded() bool useMapSubImage = layerTreeHost()->layerRendererCapabilities().usingMapSub; m_textureFormat = layerTreeHost()->layerRendererCapabilities().bestTextureFormat; - if (!m_backgroundUpdater) - m_backgroundUpdater = BitmapCanvasLayerTextureUpdater::create(ScrollbarBackgroundPainter::create(m_scrollbar.get(), theme()), useMapSubImage); - if (!m_background) - m_background = m_backgroundUpdater->createTexture(layerTreeHost()->contentsTextureManager()); + if (!m_backTrackUpdater) + m_backTrackUpdater = BitmapCanvasLayerTextureUpdater::create(ScrollbarBackgroundPainter::create(m_scrollbar.get(), theme(), BackTrackPart), useMapSubImage); + if (!m_backTrack) + m_backTrack = m_backTrackUpdater->createTexture(layerTreeHost()->contentsTextureManager()); + + // Only create two-part track if we think the two parts could be different in appearance. + if (m_scrollbar->isCustomScrollbar()) { + if (!m_foreTrackUpdater) + m_foreTrackUpdater = BitmapCanvasLayerTextureUpdater::create(ScrollbarBackgroundPainter::create(m_scrollbar.get(), theme(), ForwardTrackPart), useMapSubImage); + if (!m_foreTrack) + m_foreTrack = m_foreTrackUpdater->createTexture(layerTreeHost()->contentsTextureManager()); + } if (!m_thumbUpdater) m_thumbUpdater = BitmapCanvasLayerTextureUpdater::create(ScrollbarThumbPainter::create(m_scrollbar.get(), theme()), useMapSubImage); @@ -220,28 +229,49 @@ void ScrollbarLayerChromium::createTextureUpdaterIfNeeded() void ScrollbarLayerChromium::updatePart(LayerTextureUpdater* painter, LayerTextureUpdater::Texture* texture, const IntRect& rect, CCTextureUpdater& updater) { - bool textureValid = texture->texture()->isValid(rect.size(), m_textureFormat); - // Skip painting and uploading if there are no invalidations. - if (textureValid && m_updateRect.isEmpty()) { - texture->texture()->reserve(rect.size(), m_textureFormat); + // Skip painting and uploading if there are no invalidations and + // we already have valid texture data. + if (texture->texture()->haveBackingTexture() + && texture->texture()->size() == rect.size() + && m_updateRect.isEmpty()) return; - } - // ScrollbarLayerChromium doesn't support partial uploads, so any - // invalidation is treated a full layer invalidation. - if (layerTreeHost()->bufferedUpdates() && textureValid) - layerTreeHost()->deleteTextureAfterCommit(texture->texture()->steal()); - - if (!texture->texture()->reserve(rect.size(), m_textureFormat)) + // We should always have enough memory for UI. + ASSERT(texture->texture()->canAcquireBackingTexture()); + if (!texture->texture()->canAcquireBackingTexture()) return; // Paint and upload the entire part. IntRect paintedOpaqueRect; - painter->prepareToUpdate(rect, rect.size(), 1, paintedOpaqueRect); + painter->prepareToUpdate(rect, rect.size(), 1, 1, paintedOpaqueRect); texture->prepareRect(rect); IntRect destRect(IntPoint(), rect.size()); - updater.appendUpdate(texture, rect, destRect); + updater.appendFullUpdate(texture, rect, destRect); +} + + +void ScrollbarLayerChromium::setTexturePriorities(const CCPriorityCalculator&) +{ + if (contentBounds().isEmpty()) + return; + + createTextureUpdaterIfNeeded(); + + bool drawsToRootSurface = !targetRenderSurface()->targetRenderSurface(); + if (m_backTrack) { + m_backTrack->texture()->setDimensions(contentBounds(), m_textureFormat); + m_backTrack->texture()->setRequestPriority(CCPriorityCalculator::uiPriority(drawsToRootSurface)); + } + if (m_foreTrack) { + m_foreTrack->texture()->setDimensions(contentBounds(), m_textureFormat); + m_foreTrack->texture()->setRequestPriority(CCPriorityCalculator::uiPriority(drawsToRootSurface)); + } + if (m_thumb) { + IntSize thumbSize = theme()->thumbRect(m_scrollbar.get()).size(); + m_thumb->texture()->setDimensions(thumbSize, m_textureFormat); + m_thumb->texture()->setRequestPriority(CCPriorityCalculator::uiPriority(drawsToRootSurface)); + } } void ScrollbarLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTracker*) @@ -253,7 +283,9 @@ void ScrollbarLayerChromium::update(CCTextureUpdater& updater, const CCOcclusion IntPoint scrollbarOrigin(m_scrollbar->x(), m_scrollbar->y()); IntRect contentRect(scrollbarOrigin, contentBounds()); - updatePart(m_backgroundUpdater.get(), m_background.get(), contentRect, updater); + updatePart(m_backTrackUpdater.get(), m_backTrack.get(), contentRect, updater); + if (m_foreTrack && m_foreTrackUpdater) + updatePart(m_foreTrackUpdater.get(), m_foreTrack.get(), contentRect, updater); // Consider the thumb to be at the origin when painting. IntRect thumbRect = IntRect(IntPoint(), theme()->thumbRect(m_scrollbar.get()).size()); diff --git a/Source/WebCore/platform/graphics/chromium/ScrollbarLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ScrollbarLayerChromium.h index af2215bd0..0a8a2a13b 100644 --- a/Source/WebCore/platform/graphics/chromium/ScrollbarLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ScrollbarLayerChromium.h @@ -44,6 +44,7 @@ public: static PassRefPtr<ScrollbarLayerChromium> create(Scrollbar*, int scrollLayerId); // LayerChromium interface + virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; virtual void update(CCTextureUpdater&, const CCOcclusionTracker*) OVERRIDE; virtual void setLayerTreeHost(CCLayerTreeHost*) OVERRIDE; virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; @@ -66,11 +67,13 @@ private: GC3Denum m_textureFormat; - RefPtr<LayerTextureUpdater> m_backgroundUpdater; + RefPtr<LayerTextureUpdater> m_backTrackUpdater; + RefPtr<LayerTextureUpdater> m_foreTrackUpdater; RefPtr<LayerTextureUpdater> m_thumbUpdater; // All the parts of the scrollbar except the thumb - OwnPtr<LayerTextureUpdater::Texture> m_background; + OwnPtr<LayerTextureUpdater::Texture> m_backTrack; + OwnPtr<LayerTextureUpdater::Texture> m_foreTrack; OwnPtr<LayerTextureUpdater::Texture> m_thumb; ScrollbarOverlayStyle m_scrollbarOverlayStyle; diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp index 2a140d1d7..7ee5a21b9 100644 --- a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp @@ -38,14 +38,38 @@ using WebKit::WebGraphicsContext3D; namespace WebCore { +namespace { + +static void getProgramUniformLocations(WebGraphicsContext3D* context, unsigned program, const char** shaderUniforms, size_t count, size_t maxLocations, int* locations, bool usingBindUniform, int* baseUniformIndex) +{ + for (size_t uniformIndex = 0; uniformIndex < count; uniformIndex ++) { + ASSERT(uniformIndex < maxLocations); + + if (usingBindUniform) { + locations[uniformIndex] = (*baseUniformIndex)++; + context->bindUniformLocationCHROMIUM(program, locations[uniformIndex], shaderUniforms[uniformIndex]); + } else + locations[uniformIndex] = context->getUniformLocation(program, shaderUniforms[uniformIndex]); + } +} + +} + VertexShaderPosTex::VertexShaderPosTex() : m_matrixLocation(-1) { } -void VertexShaderPosTex::init(WebGraphicsContext3D* context, unsigned program) +void VertexShaderPosTex::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_matrixLocation = context->getUniformLocation(program, "matrix"); + static const char* shaderUniforms[] = { + "matrix", + }; + int locations[1]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; ASSERT(m_matrixLocation != -1); } @@ -71,11 +95,20 @@ VertexShaderPosTexYUVStretch::VertexShaderPosTexYUVStretch() { } -void VertexShaderPosTexYUVStretch::init(WebGraphicsContext3D* context, unsigned program) +void VertexShaderPosTexYUVStretch::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_matrixLocation = context->getUniformLocation(program, "matrix"); - m_yWidthScaleFactorLocation = context->getUniformLocation(program, "y_widthScaleFactor"); - m_uvWidthScaleFactorLocation = context->getUniformLocation(program, "uv_widthScaleFactor"); + static const char* shaderUniforms[] = { + "matrix", + "y_widthScaleFactor", + "uv_widthScaleFactor", + }; + int locations[3]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + m_yWidthScaleFactorLocation = locations[1]; + m_uvWidthScaleFactorLocation = locations[2]; ASSERT(m_matrixLocation != -1 && m_yWidthScaleFactorLocation != -1 && m_uvWidthScaleFactorLocation != -1); } @@ -104,9 +137,16 @@ VertexShaderPos::VertexShaderPos() { } -void VertexShaderPos::init(WebGraphicsContext3D* context, unsigned program) +void VertexShaderPos::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_matrixLocation = context->getUniformLocation(program, "matrix"); + static const char* shaderUniforms[] = { + "matrix", + }; + int locations[1]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; ASSERT(m_matrixLocation != -1); } @@ -128,10 +168,18 @@ VertexShaderPosTexTransform::VertexShaderPosTexTransform() { } -void VertexShaderPosTexTransform::init(WebGraphicsContext3D* context, unsigned program) +void VertexShaderPosTexTransform::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_matrixLocation = context->getUniformLocation(program, "matrix"); - m_texTransformLocation = context->getUniformLocation(program, "texTransform"); + static const char* shaderUniforms[] = { + "matrix", + "texTransform", + }; + int locations[2]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + m_texTransformLocation = locations[1]; ASSERT(m_matrixLocation != -1 && m_texTransformLocation != -1); } @@ -170,10 +218,18 @@ String VertexShaderPosTexIdentity::getShaderString() const ); } -void VertexShaderQuad::init(WebGraphicsContext3D* context, unsigned program) +void VertexShaderQuad::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_matrixLocation = context->getUniformLocation(program, "matrix"); - m_pointLocation = context->getUniformLocation(program, "point"); + static const char* shaderUniforms[] = { + "matrix", + "point", + }; + int locations[2]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + m_pointLocation = locations[1]; ASSERT(m_matrixLocation != -1 && m_pointLocation != -1); } @@ -206,11 +262,20 @@ VertexShaderTile::VertexShaderTile() { } -void VertexShaderTile::init(WebGraphicsContext3D* context, unsigned program) +void VertexShaderTile::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_matrixLocation = context->getUniformLocation(program, "matrix"); - m_pointLocation = context->getUniformLocation(program, "point"); - m_vertexTexTransformLocation = context->getUniformLocation(program, "vertexTexTransform"); + static const char* shaderUniforms[] = { + "matrix", + "point", + "vertexTexTransform", + }; + int locations[3]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + m_pointLocation = locations[1]; + m_vertexTexTransformLocation = locations[2]; ASSERT(m_matrixLocation != -1 && m_pointLocation != -1 && m_vertexTexTransformLocation != -1); } @@ -243,10 +308,18 @@ VertexShaderVideoTransform::VertexShaderVideoTransform() { } -bool VertexShaderVideoTransform::init(WebGraphicsContext3D* context, unsigned program) +bool VertexShaderVideoTransform::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_matrixLocation = context->getUniformLocation(program, "matrix"); - m_texMatrixLocation = context->getUniformLocation(program, "texMatrix"); + static const char* shaderUniforms[] = { + "matrix", + "texMatrix", + }; + int locations[2]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + m_texMatrixLocation = locations[1]; return m_matrixLocation != -1 && m_texMatrixLocation != -1; } @@ -272,11 +345,18 @@ FragmentTexAlphaBinding::FragmentTexAlphaBinding() { } -void FragmentTexAlphaBinding::init(WebGraphicsContext3D* context, unsigned program) +void FragmentTexAlphaBinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_samplerLocation = context->getUniformLocation(program, "s_texture"); - m_alphaLocation = context->getUniformLocation(program, "alpha"); + static const char* shaderUniforms[] = { + "s_texture", + "alpha", + }; + int locations[2]; + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + m_alphaLocation = locations[1]; ASSERT(m_samplerLocation != -1 && m_alphaLocation != -1); } @@ -285,10 +365,16 @@ FragmentTexOpaqueBinding::FragmentTexOpaqueBinding() { } -void FragmentTexOpaqueBinding::init(WebGraphicsContext3D* context, unsigned program) +void FragmentTexOpaqueBinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_samplerLocation = context->getUniformLocation(program, "s_texture"); + static const char* shaderUniforms[] = { + "s_texture", + }; + int locations[1]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + m_samplerLocation = locations[0]; ASSERT(m_samplerLocation != -1); } @@ -307,10 +393,16 @@ String FragmentShaderRGBATexFlipAlpha::getShaderString() const ); } -bool FragmentShaderOESImageExternal::init(WebGraphicsContext3D* context, unsigned program) +bool FragmentShaderOESImageExternal::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_samplerLocation = context->getUniformLocation(program, "s_texture"); + static const char* shaderUniforms[] = { + "s_texture", + }; + int locations[1]; + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; return m_samplerLocation != -1; } @@ -437,12 +529,20 @@ FragmentShaderRGBATexAlphaAA::FragmentShaderRGBATexAlphaAA() { } -void FragmentShaderRGBATexAlphaAA::init(WebGraphicsContext3D* context, unsigned program) +void FragmentShaderRGBATexAlphaAA::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_samplerLocation = context->getUniformLocation(program, "s_texture"); - m_alphaLocation = context->getUniformLocation(program, "alpha"); - m_edgeLocation = context->getUniformLocation(program, "edge"); + static const char* shaderUniforms[] = { + "s_texture", + "alpha", + "edge", + }; + int locations[3]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + m_samplerLocation = locations[0]; + m_alphaLocation = locations[1]; + m_edgeLocation = locations[2]; ASSERT(m_samplerLocation != -1 && m_alphaLocation != -1 && m_edgeLocation != -1); } @@ -479,13 +579,22 @@ FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding() { } -void FragmentTexClampAlphaAABinding::init(WebGraphicsContext3D* context, unsigned program) +void FragmentTexClampAlphaAABinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_samplerLocation = context->getUniformLocation(program, "s_texture"); - m_alphaLocation = context->getUniformLocation(program, "alpha"); - m_fragmentTexTransformLocation = context->getUniformLocation(program, "fragmentTexTransform"); - m_edgeLocation = context->getUniformLocation(program, "edge"); + static const char* shaderUniforms[] = { + "s_texture", + "alpha", + "fragmentTexTransform", + "edge", + }; + int locations[4]; + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + m_alphaLocation = locations[1]; + m_fragmentTexTransformLocation = locations[2]; + m_edgeLocation = locations[3]; ASSERT(m_samplerLocation != -1 && m_alphaLocation != -1 && m_fragmentTexTransformLocation != -1 && m_edgeLocation != -1); } @@ -550,11 +659,20 @@ FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask() { } -void FragmentShaderRGBATexAlphaMask::init(WebGraphicsContext3D* context, unsigned program) +void FragmentShaderRGBATexAlphaMask::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_samplerLocation = context->getUniformLocation(program, "s_texture"); - m_maskSamplerLocation = context->getUniformLocation(program, "s_mask"); - m_alphaLocation = context->getUniformLocation(program, "alpha"); + static const char* shaderUniforms[] = { + "s_texture", + "s_mask", + "alpha", + }; + int locations[3]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + m_maskSamplerLocation = locations[1]; + m_alphaLocation = locations[2]; ASSERT(m_samplerLocation != -1 && m_maskSamplerLocation != -1 && m_alphaLocation != -1); } @@ -583,12 +701,22 @@ FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA() { } -void FragmentShaderRGBATexAlphaMaskAA::init(WebGraphicsContext3D* context, unsigned program) +void FragmentShaderRGBATexAlphaMaskAA::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_samplerLocation = context->getUniformLocation(program, "s_texture"); - m_maskSamplerLocation = context->getUniformLocation(program, "s_mask"); - m_alphaLocation = context->getUniformLocation(program, "alpha"); - m_edgeLocation = context->getUniformLocation(program, "edge"); + static const char* shaderUniforms[] = { + "s_texture", + "s_mask", + "alpha", + "edge", + }; + int locations[4]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + m_maskSamplerLocation = locations[1]; + m_alphaLocation = locations[2]; + m_edgeLocation = locations[3]; ASSERT(m_samplerLocation != -1 && m_maskSamplerLocation != -1 && m_alphaLocation != -1 && m_edgeLocation != -1); } @@ -629,14 +757,26 @@ FragmentShaderYUVVideo::FragmentShaderYUVVideo() { } -void FragmentShaderYUVVideo::init(WebGraphicsContext3D* context, unsigned program) +void FragmentShaderYUVVideo::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_yTextureLocation = context->getUniformLocation(program, "y_texture"); - m_uTextureLocation = context->getUniformLocation(program, "u_texture"); - m_vTextureLocation = context->getUniformLocation(program, "v_texture"); - m_alphaLocation = context->getUniformLocation(program, "alpha"); - m_ccMatrixLocation = context->getUniformLocation(program, "cc_matrix"); - m_yuvAdjLocation = context->getUniformLocation(program, "yuv_adj"); + static const char* shaderUniforms[] = { + "y_texture", + "u_texture", + "v_texture", + "alpha", + "cc_matrix", + "yuv_adj", + }; + int locations[6]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_yTextureLocation = locations[0]; + m_uTextureLocation = locations[1]; + m_vTextureLocation = locations[2]; + m_alphaLocation = locations[3]; + m_ccMatrixLocation = locations[4]; + m_yuvAdjLocation = locations[5]; ASSERT(m_yTextureLocation != -1 && m_uTextureLocation != -1 && m_vTextureLocation != -1 && m_alphaLocation != -1 && m_ccMatrixLocation != -1 && m_yuvAdjLocation != -1); @@ -672,9 +812,16 @@ FragmentShaderColor::FragmentShaderColor() { } -void FragmentShaderColor::init(WebGraphicsContext3D* context, unsigned program) +void FragmentShaderColor::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_colorLocation = context->getUniformLocation(program, "color"); + static const char* shaderUniforms[] = { + "color", + }; + int locations[1]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_colorLocation = locations[0]; ASSERT(m_colorLocation != -1); } @@ -697,11 +844,20 @@ FragmentShaderCheckerboard::FragmentShaderCheckerboard() { } -void FragmentShaderCheckerboard::init(WebGraphicsContext3D* context, unsigned program) +void FragmentShaderCheckerboard::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { - m_alphaLocation = context->getUniformLocation(program, "alpha"); - m_texTransformLocation = context->getUniformLocation(program, "texTransform"); - m_frequencyLocation = context->getUniformLocation(program, "frequency"); + static const char* shaderUniforms[] = { + "alpha", + "texTransform", + "frequency", + }; + int locations[3]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_alphaLocation = locations[0]; + m_texTransformLocation = locations[1]; + m_frequencyLocation = locations[2]; ASSERT(m_alphaLocation != -1 && m_texTransformLocation != -1 && m_frequencyLocation != -1); } diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h index 475b78962..00872e4a4 100644 --- a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h @@ -28,8 +28,8 @@ #if USE(ACCELERATED_COMPOSITING) -#include "PlatformString.h" #include "SkColorPriv.h" +#include <wtf/text/WTFString.h> namespace WebKit { class WebGraphicsContext3D; @@ -41,7 +41,7 @@ class VertexShaderPosTex { public: VertexShaderPosTex(); - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); String getShaderString() const; int matrixLocation() const { return m_matrixLocation; } @@ -54,7 +54,7 @@ class VertexShaderPosTexYUVStretch { public: VertexShaderPosTexYUVStretch(); - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); String getShaderString() const; int matrixLocation() const { return m_matrixLocation; } @@ -71,7 +71,7 @@ class VertexShaderPos { public: VertexShaderPos(); - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); String getShaderString() const; int matrixLocation() const { return m_matrixLocation; } @@ -82,7 +82,7 @@ private: class VertexShaderPosTexIdentity { public: - void init(WebKit::WebGraphicsContext3D*, unsigned program) { } + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex) { } String getShaderString() const; }; @@ -90,7 +90,7 @@ class VertexShaderPosTexTransform { public: VertexShaderPosTexTransform(); - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); String getShaderString() const; int matrixLocation() const { return m_matrixLocation; } @@ -105,7 +105,7 @@ class VertexShaderQuad { public: VertexShaderQuad(); - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); String getShaderString() const; int matrixLocation() const { return m_matrixLocation; } @@ -120,7 +120,7 @@ class VertexShaderTile { public: VertexShaderTile(); - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); String getShaderString() const; int matrixLocation() const { return m_matrixLocation; } @@ -137,7 +137,7 @@ class VertexShaderVideoTransform { public: VertexShaderVideoTransform(); - bool init(WebKit::WebGraphicsContext3D*, unsigned program); + bool init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); String getShaderString() const; int matrixLocation() const { return m_matrixLocation; } @@ -152,7 +152,7 @@ class FragmentTexAlphaBinding { public: FragmentTexAlphaBinding(); - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); int alphaLocation() const { return m_alphaLocation; } int edgeLocation() const { return -1; } int fragmentTexTransformLocation() const { return -1; } @@ -167,7 +167,7 @@ class FragmentTexOpaqueBinding { public: FragmentTexOpaqueBinding(); - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); int alphaLocation() const { return -1; } int edgeLocation() const { return -1; } int fragmentTexTransformLocation() const { return -1; } @@ -223,7 +223,7 @@ public: class FragmentShaderOESImageExternal : public FragmentTexAlphaBinding { public: String getShaderString() const; - bool init(WebKit::WebGraphicsContext3D*, unsigned program); + bool init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); private: int m_samplerLocation; }; @@ -232,7 +232,7 @@ class FragmentShaderRGBATexAlphaAA { public: FragmentShaderRGBATexAlphaAA(); - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); String getShaderString() const; int alphaLocation() const { return m_alphaLocation; } @@ -249,7 +249,7 @@ class FragmentTexClampAlphaAABinding { public: FragmentTexClampAlphaAABinding(); - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); int alphaLocation() const { return m_alphaLocation; } int samplerLocation() const { return m_samplerLocation; } int fragmentTexTransformLocation() const { return m_fragmentTexTransformLocation; } @@ -278,7 +278,7 @@ public: FragmentShaderRGBATexAlphaMask(); String getShaderString() const; - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); int alphaLocation() const { return m_alphaLocation; } int samplerLocation() const { return m_samplerLocation; } int maskSamplerLocation() const { return m_maskSamplerLocation; } @@ -294,7 +294,7 @@ public: FragmentShaderRGBATexAlphaMaskAA(); String getShaderString() const; - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); int alphaLocation() const { return m_alphaLocation; } int samplerLocation() const { return m_samplerLocation; } int maskSamplerLocation() const { return m_maskSamplerLocation; } @@ -312,7 +312,7 @@ public: FragmentShaderYUVVideo(); String getShaderString() const; - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); int yTextureLocation() const { return m_yTextureLocation; } int uTextureLocation() const { return m_uTextureLocation; } @@ -335,7 +335,7 @@ public: FragmentShaderColor(); String getShaderString() const; - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); int colorLocation() const { return m_colorLocation; } private: @@ -347,7 +347,7 @@ public: FragmentShaderCheckerboard(); String getShaderString() const; - void init(WebKit::WebGraphicsContext3D*, unsigned program); + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); int alphaLocation() const { return m_alphaLocation; } int texTransformLocation() const { return m_texTransformLocation; } int frequencyLocation() const { return m_frequencyLocation; } diff --git a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp index c1177fbcd..f7bdb6f36 100644 --- a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp @@ -30,9 +30,7 @@ #include "SkPictureCanvasLayerTextureUpdater.h" -#include "GraphicsContext.h" #include "LayerPainterChromium.h" -#include "PlatformContextSkia.h" #include "SkCanvas.h" #include "TraceEvent.h" @@ -48,16 +46,16 @@ SkPictureCanvasLayerTextureUpdater::~SkPictureCanvasLayerTextureUpdater() { } -void SkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, float contentsScale, IntRect& resultingOpaqueRect) +void SkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) { SkCanvas* canvas = m_picture.beginRecording(contentRect.width(), contentRect.height()); - paintContents(canvas, contentRect, contentsScale, resultingOpaqueRect); + paintContents(canvas, contentRect, contentsWidthScale, contentsHeightScale, resultingOpaqueRect); m_picture.endRecording(); } void SkPictureCanvasLayerTextureUpdater::drawPicture(SkCanvas* canvas) { - TRACE_EVENT("SkPictureCanvasLayerTextureUpdater::drawPicture", this, 0); + TRACE_EVENT0("cc", "SkPictureCanvasLayerTextureUpdater::drawPicture"); canvas->drawPicture(m_picture); } diff --git a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h index e297e050e..a51f44f59 100644 --- a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h +++ b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h @@ -52,7 +52,7 @@ public: protected: explicit SkPictureCanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium>); - virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect) OVERRIDE; + virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) OVERRIDE; void drawPicture(SkCanvas*); bool layerIsOpaque() const { return m_layerIsOpaque; } diff --git a/Source/WebCore/platform/graphics/chromium/TextureCopier.cpp b/Source/WebCore/platform/graphics/chromium/TextureCopier.cpp index 0f2309068..33243c855 100644 --- a/Source/WebCore/platform/graphics/chromium/TextureCopier.cpp +++ b/Source/WebCore/platform/graphics/chromium/TextureCopier.cpp @@ -34,8 +34,9 @@ namespace WebCore { #if USE(ACCELERATED_COMPOSITING) -AcceleratedTextureCopier::AcceleratedTextureCopier(WebKit::WebGraphicsContext3D* context) +AcceleratedTextureCopier::AcceleratedTextureCopier(WebKit::WebGraphicsContext3D* context, bool usingBindUniforms) : m_context(context) + , m_usingBindUniforms(usingBindUniforms) { ASSERT(m_context); GLC(m_context, m_fbo = m_context->createFramebuffer()); @@ -67,7 +68,7 @@ AcceleratedTextureCopier::~AcceleratedTextureCopier() void AcceleratedTextureCopier::copyTexture(CCGraphicsContext* ccContext, unsigned sourceTextureId, unsigned destTextureId, const IntSize& size) { - TRACE_EVENT("TextureCopier::copyTexture", this, 0); + TRACE_EVENT0("cc", "TextureCopier::copyTexture"); WebKit::WebGraphicsContext3D* context = ccContext->context3D(); if (!context) { @@ -90,7 +91,7 @@ void AcceleratedTextureCopier::copyTexture(CCGraphicsContext* ccContext, unsigne GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST)); if (!m_blitProgram->initialized()) - m_blitProgram->initialize(context); + m_blitProgram->initialize(context, m_usingBindUniforms); // TODO: Use EXT_framebuffer_blit if available. GLC(context, context->useProgram(m_blitProgram->program())); diff --git a/Source/WebCore/platform/graphics/chromium/TextureCopier.h b/Source/WebCore/platform/graphics/chromium/TextureCopier.h index 646189ab6..c2bcd427c 100644 --- a/Source/WebCore/platform/graphics/chromium/TextureCopier.h +++ b/Source/WebCore/platform/graphics/chromium/TextureCopier.h @@ -53,16 +53,16 @@ protected: class AcceleratedTextureCopier : public TextureCopier { WTF_MAKE_NONCOPYABLE(AcceleratedTextureCopier); public: - static PassOwnPtr<AcceleratedTextureCopier> create(WebKit::WebGraphicsContext3D* context) + static PassOwnPtr<AcceleratedTextureCopier> create(WebKit::WebGraphicsContext3D* context, bool usingBindUniforms) { - return adoptPtr(new AcceleratedTextureCopier(context)); + return adoptPtr(new AcceleratedTextureCopier(context, usingBindUniforms)); } virtual ~AcceleratedTextureCopier(); virtual void copyTexture(CCGraphicsContext*, unsigned sourceTextureId, unsigned destTextureId, const IntSize&); protected: - explicit AcceleratedTextureCopier(WebKit::WebGraphicsContext3D*); + AcceleratedTextureCopier(WebKit::WebGraphicsContext3D*, bool usingBindUniforms); private: typedef ProgramBinding<VertexShaderPosTexIdentity, FragmentShaderRGBATex> BlitProgram; @@ -71,6 +71,7 @@ private: Platform3DObject m_fbo; Platform3DObject m_positionBuffer; OwnPtr<BlitProgram> m_blitProgram; + bool m_usingBindUniforms; }; #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/TextureManager.cpp b/Source/WebCore/platform/graphics/chromium/TextureManager.cpp index d1f52faeb..485c72228 100644 --- a/Source/WebCore/platform/graphics/chromium/TextureManager.cpp +++ b/Source/WebCore/platform/graphics/chromium/TextureManager.cpp @@ -195,7 +195,7 @@ void TextureManager::unprotectAllTextures() void TextureManager::evictTexture(TextureToken token, TextureInfo info) { - TRACE_EVENT("TextureManager::evictTexture", this, 0); + TRACE_EVENT0("cc", "TextureManager::evictTexture"); removeTexture(token, info); } diff --git a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp index 6e052b7fa..5c4bc05ce 100644 --- a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp @@ -57,7 +57,7 @@ public: } LayerTextureUpdater::Texture* texture() { return m_texture.get(); } - ManagedTexture* managedTexture() { return m_texture->texture(); } + CCPrioritizedTexture* managedTexture() { return m_texture->texture(); } bool isDirty() const { return !dirtyRect.isEmpty(); } void copyAndClearDirty() @@ -220,7 +220,7 @@ void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer) if (!tile) continue; tile->isInUseOnImpl = false; - if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) { + if (!tile->managedTexture()->haveBackingTexture()) { invalidTiles.append(tile); continue; } @@ -234,7 +234,7 @@ void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer) m_tiler->takeTile((*iter)->i(), (*iter)->j()); } -TextureManager* TiledLayerChromium::textureManager() const +CCPrioritizedTextureManager* TiledLayerChromium::textureManager() const { if (!layerTreeHost()) return 0; @@ -262,7 +262,11 @@ UpdatableTile* TiledLayerChromium::tileAt(int i, int j) const UpdatableTile* TiledLayerChromium::createTile(int i, int j) { + createTextureUpdaterIfNeeded(); + OwnPtr<UpdatableTile> tile(UpdatableTile::create(textureUpdater()->createTexture(textureManager()))); + tile->managedTexture()->setDimensions(m_tiler->tileSize(), m_textureFormat); + UpdatableTile* addedTile = tile.get(); m_tiler->addTile(tile.release(), i, j); @@ -279,8 +283,10 @@ UpdatableTile* TiledLayerChromium::createTile(int i, int j) void TiledLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect) { + float contentsWidthScale = static_cast<float>(contentBounds().width()) / bounds().width(); + float contentsHeightScale = static_cast<float>(contentBounds().height()) / bounds().height(); FloatRect scaledDirtyRect(dirtyRect); - scaledDirtyRect.scale(contentsScale()); + scaledDirtyRect.scale(contentsWidthScale, contentsHeightScale); IntRect dirty = enclosingIntRect(scaledDirtyRect); invalidateRect(dirty); LayerChromium::setNeedsDisplayRect(dirtyRect); @@ -318,25 +324,6 @@ void TiledLayerChromium::invalidateRect(const IntRect& layerRect) } } -void TiledLayerChromium::protectTileTextures(const IntRect& layerRect) -{ - if (m_tiler->isEmpty() || layerRect.isEmpty()) - return; - - int left, top, right, bottom; - m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom); - - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = tileAt(i, j); - if (!tile || !tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) - continue; - - tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat); - } - } -} - // Returns true if tile is dirty and only part of it needs to be updated. bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) { @@ -347,7 +334,7 @@ bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) // we don't modify textures currently used for drawing by the impl thread. bool TiledLayerChromium::tileNeedsBufferedUpdate(UpdatableTile* tile) { - if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) + if (!tile->managedTexture()->haveBackingTexture()) return false; if (!tile->isDirty()) @@ -363,6 +350,9 @@ void TiledLayerChromium::updateTiles(bool idle, int left, int top, int right, in { createTextureUpdaterIfNeeded(); + // We shouldn't track any occlusion metrics during idle painting. + ASSERT(!idle || !occlusion); + // Create tiles as needed, expanding a dirty rect to contain all // the dirty regions currently being drawn. All dirty tiles that are to be painted // get their updateRect set to dirtyRect and dirtyRect cleared. This way if @@ -371,6 +361,7 @@ void TiledLayerChromium::updateTiles(bool idle, int left, int top, int right, in for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); + ASSERT(tile); // Did setTexturePriorites get skipped? if (!tile) tile = createTile(i, j); @@ -378,7 +369,7 @@ void TiledLayerChromium::updateTiles(bool idle, int left, int top, int right, in if (!m_tiler) CRASH(); - if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) { + if (!tile->managedTexture()->haveBackingTexture()) { // Sets the dirty rect to a full-sized tile with border texels. tile->dirtyRect = m_tiler->tileRect(tile); } @@ -397,19 +388,11 @@ void TiledLayerChromium::updateTiles(bool idle, int left, int top, int right, in // any single time through the function. tile->updated = true; - if (layerTreeHost() && layerTreeHost()->bufferedUpdates() && tileNeedsBufferedUpdate(tile)) { - // FIXME: Decide if partial update should be allowed based on cost - // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 - if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->requestPartialTextureUpdate()) - tile->partialUpdate = true; - else { - layerTreeHost()->deleteTextureAfterCommit(tile->managedTexture()->steal()); - // Sets the dirty rect to a full-sized tile with border texels. - tile->dirtyRect = m_tiler->tileRect(tile); - } - } + // Always try to get memory for visible textures. + if (!idle && !tile->managedTexture()->canAcquireBackingTexture()) + tile->managedTexture()->requestLate(); - if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat)) { + if (!tile->managedTexture()->canAcquireBackingTexture()) { m_skipsIdlePaint = true; if (!idle) { m_skipsDraw = true; @@ -451,11 +434,11 @@ void TiledLayerChromium::updateTiles(bool idle, int left, int top, int right, in // Calling prepareToUpdate() calls into WebKit to paint, which may have the side // effect of disabling compositing, which causes our reference to the texture updater to be deleted. - // However, we can't free the memory backing the GraphicsContext until the paint finishes, + // However, we can't free the memory backing the SkCanvas until the paint finishes, // so we grab a local reference here to hold the updater alive until the paint completes. RefPtr<LayerTextureUpdater> protector(textureUpdater()); IntRect paintedOpaqueRect; - textureUpdater()->prepareToUpdate(paintRect, m_tiler->tileSize(), contentsScale(), paintedOpaqueRect); + textureUpdater()->prepareToUpdate(paintRect, m_tiler->tileSize(), 1 / widthScale, 1 / heightScale, paintedOpaqueRect); m_didPaint = true; for (int j = top; j <= bottom; ++j) { @@ -527,36 +510,82 @@ void TiledLayerChromium::updateTiles(bool idle, int left, int top, int right, in if (tile->partialUpdate) updater.appendPartialUpdate(tile->texture(), sourceRect, destRect); else - updater.appendUpdate(tile->texture(), sourceRect, destRect); + updater.appendFullUpdate(tile->texture(), sourceRect, destRect); } } } -void TiledLayerChromium::reserveTextures() +void TiledLayerChromium::setTexturePriorities(const CCPriorityCalculator& priorityCalc) { - updateBounds(); + setTexturePrioritiesInRect(priorityCalc, visibleLayerRect()); +} - const IntRect& layerRect = visibleLayerRect(); - if (layerRect.isEmpty() || m_tiler->hasEmptyBounds()) - return; +void TiledLayerChromium::setTexturePrioritiesInRect(const CCPriorityCalculator& priorityCalc, const IntRect& visibleRect) +{ + updateBounds(); + resetUpdateState(); - int left, top, right, bottom; - m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom); + IntRect prepaintRect = idlePaintRect(visibleRect); + bool drawsToRootSurface = !targetRenderSurface()->targetRenderSurface(); + + // Minimally create the tiles in the desired pre-paint rect. + if (!prepaintRect.isEmpty()) { + int left, top, right, bottom; + m_tiler->layerRectToTileIndices(prepaintRect, left, top, right, bottom); + for (int j = top; j <= bottom; ++j) + for (int i = left; i <= right; ++i) + if (!tileAt(i, j)) + createTile(i, j); + } - createTextureUpdaterIfNeeded(); - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = tileAt(i, j); - if (!tile) - tile = createTile(i, j); + // Create additional textures for double-buffered updates when needed. + // These textures must stay alive while the updated textures are incrementally + // uploaded, swapped atomically via pushProperties, and finally deleted + // after the commit is complete, after which they can be recycled. + if (!visibleRect.isEmpty()) { + int left, top, right, bottom; + m_tiler->layerRectToTileIndices(visibleRect, left, top, right, bottom); + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + UpdatableTile* tile = tileAt(i, j); + if (!tile) + tile = createTile(i, j); + // We need an additional texture if the tile needs a buffered-update and it's not a partial update. + // FIXME: Decide if partial update should be allowed based on cost + // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 + if (!layerTreeHost() || !layerTreeHost()->bufferedUpdates() || !tileNeedsBufferedUpdate(tile)) + continue; + if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->requestPartialTextureUpdate()) { + tile->partialUpdate = true; + continue; + } - if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) tile->dirtyRect = m_tiler->tileRect(tile); - - if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat)) - return; + LayerTextureUpdater::Texture* backBuffer = tile->texture(); + backBuffer->texture()->setRequestPriority(priorityCalc.priorityFromVisibility(true, drawsToRootSurface)); + OwnPtr<CCPrioritizedTexture> frontBuffer = CCPrioritizedTexture::create(backBuffer->texture()->textureManager(), + backBuffer->texture()->size(), + backBuffer->texture()->format()); + // Swap backBuffer into frontBuffer and add it to delete after commit queue. + backBuffer->swapTextureWith(frontBuffer); + layerTreeHost()->deleteTextureAfterCommit(frontBuffer.release()); + } } } + + // Now set priorities on all tiles. + for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { + UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); + IntRect tileRect = m_tiler->tileRect(tile); + // FIXME: This indicates the "small animated layer" case. This special case + // can be removed soon with better priorities, but for now paint these layers after + // 512 pixels of pre-painting. Later we can just pass an animating flag etc. to the + // calculator and it can take care of this special case if we still need it. + if (visibleRect.isEmpty() && !prepaintRect.isEmpty()) + tile->managedTexture()->setRequestPriority(priorityCalc.priorityFromDistance(512, drawsToRootSurface)); + else if (!visibleRect.isEmpty()) + tile->managedTexture()->setRequestPriority(priorityCalc.priorityFromDistance(visibleRect, tileRect, drawsToRootSurface)); + } } Region TiledLayerChromium::visibleContentOpaqueRegion() const @@ -577,12 +606,12 @@ void TiledLayerChromium::resetUpdateState() if (!tile) continue; tile->updateRect = IntRect(); - tile->partialUpdate = false; tile->updated = false; + tile->partialUpdate = false; } } -void TiledLayerChromium::updateLayerRect(CCTextureUpdater& updater, const IntRect& layerRect, const CCOcclusionTracker* occlusion) +void TiledLayerChromium::updateLayerRect(CCTextureUpdater& updater, const IntRect& contentRect, const CCOcclusionTracker* occlusion) { m_skipsDraw = false; m_skipsIdlePaint = false; @@ -590,44 +619,30 @@ void TiledLayerChromium::updateLayerRect(CCTextureUpdater& updater, const IntRec updateBounds(); - resetUpdateState(); - - if (layerRect.isEmpty() || m_tiler->hasEmptyBounds()) + if (m_tiler->hasEmptyBounds()) return; - int left, top, right, bottom; - m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom); - - updateTiles(false, left, top, right, bottom, updater, occlusion); -} + // Visible painting. Only paint visible tiles if the visible rect isn't empty. + if (!contentRect.isEmpty()) { + int left, top, right, bottom; + m_tiler->layerRectToTileIndices(contentRect, left, top, right, bottom); + updateTiles(false, left, top, right, bottom, updater, occlusion); + } -void TiledLayerChromium::idleUpdateLayerRect(CCTextureUpdater& updater, const IntRect& layerRect, const CCOcclusionTracker* occlusion) -{ // Abort if we have already painted or run out of memory. if (m_skipsIdlePaint || m_didPaint) return; - ASSERT(m_tiler); - - updateBounds(); - - if (m_tiler->hasEmptyBounds()) - return; - - IntRect idlePaintLayerRect = idlePaintRect(layerRect); - if (idlePaintLayerRect.isEmpty()) + // If we have already painting everything visible. Do some pre-painting while idle. + IntRect idlePaintContentRect = idlePaintRect(contentRect); + if (idlePaintContentRect.isEmpty()) return; - // Protect any textures in the pre-paint area, as we would steal them from other layers - // over time anyhow. This ensures we don't lose tiles in the first rounds of idle painting - // that we have already painted. - protectTileTextures(idlePaintLayerRect); - int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom; - m_tiler->layerRectToTileIndices(idlePaintLayerRect, prepaintLeft, prepaintTop, prepaintRight, prepaintBottom); + m_tiler->layerRectToTileIndices(idlePaintContentRect, prepaintLeft, prepaintTop, prepaintRight, prepaintBottom); // If the layer is not visible, we have nothing to expand from, so instead we prepaint the outer-most set of tiles. - if (layerRect.isEmpty()) { + if (contentRect.isEmpty()) { updateTiles(true, prepaintLeft, prepaintTop, prepaintRight, prepaintTop, updater, 0); if (m_didPaint || m_skipsIdlePaint) return; @@ -642,7 +657,7 @@ void TiledLayerChromium::idleUpdateLayerRect(CCTextureUpdater& updater, const In } int left, top, right, bottom; - m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom); + m_tiler->layerRectToTileIndices(contentRect, left, top, right, bottom); // Otherwise, prepaint anything that was occluded but inside the layer's visible region. updateTiles(true, left, top, right, bottom, updater, 0); @@ -678,7 +693,7 @@ void TiledLayerChromium::idleUpdateLayerRect(CCTextureUpdater& updater, const In } } -bool TiledLayerChromium::needsIdlePaint(const IntRect& layerRect) +bool TiledLayerChromium::needsIdlePaint(const IntRect& contentRect) { if (m_skipsIdlePaint) return false; @@ -686,45 +701,54 @@ bool TiledLayerChromium::needsIdlePaint(const IntRect& layerRect) if (m_tiler->hasEmptyBounds()) return false; - IntRect idlePaintLayerRect = idlePaintRect(layerRect); - if (idlePaintLayerRect.isEmpty()) + IntRect idlePaintContentRect = idlePaintRect(contentRect); + if (idlePaintContentRect.isEmpty()) return false; int left, top, right, bottom; - m_tiler->layerRectToTileIndices(idlePaintLayerRect, left, top, right, bottom); + m_tiler->layerRectToTileIndices(idlePaintContentRect, left, top, right, bottom); + for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { // If the layerRect is empty, then we are painting the outer-most set of tiles only. - if (layerRect.isEmpty() && i != left && i != right && j != top && j != bottom) + if (contentRect.isEmpty() && i != left && i != right && j != top && j != bottom) continue; UpdatableTile* tile = tileAt(i, j); - if (!tile || !tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat) || tile->isDirty()) + ASSERT(tile); // Did setTexturePriorities get skipped? + if (!tile) + continue; + + bool updated = tile->updated; + bool canAcquire = tile->managedTexture()->canAcquireBackingTexture(); + bool dirty = tile->isDirty() || !tile->managedTexture()->haveBackingTexture(); + if (!updated && canAcquire && dirty) return true; } } return false; } -IntRect TiledLayerChromium::idlePaintRect(const IntRect& visibleLayerRect) +IntRect TiledLayerChromium::idlePaintRect(const IntRect& visibleRect) { + IntRect contentRect(IntPoint::zero(), contentBounds()); + // For layers that are animating transforms but not visible at all, we don't know what part // of them is going to become visible. For small layers we return the entire layer, for larger // ones we avoid prepainting the layer at all. - if (visibleLayerRect.isEmpty()) { + if (visibleRect.isEmpty()) { bool isSmallLayer = m_tiler->numTilesX() <= 9 && m_tiler->numTilesY() <= 9 && m_tiler->numTilesX() * m_tiler->numTilesY() <= 9; if ((drawTransformIsAnimating() || screenSpaceTransformIsAnimating()) && isSmallLayer) - return IntRect(IntPoint(), contentBounds()); + return contentRect; return IntRect(); } - IntRect prepaintRect = visibleLayerRect; - // FIXME: This can be made a lot larger if we can: - // - reserve memory at a lower priority than for visible content - // - only reserve idle paint tiles up to a memory reclaim threshold and - // - insure we play nicely with other layers + // FIXME: This can be made a lot larger now! We should increase + // this slowly while insuring it doesn't cause any perf issues. + IntRect prepaintRect = visibleRect; prepaintRect.inflateX(m_tiler->tileSize().width()); - prepaintRect.inflateY(m_tiler->tileSize().height()); - prepaintRect.intersect(IntRect(IntPoint::zero(), contentBounds())); + prepaintRect.inflateY(m_tiler->tileSize().height() * 2); + prepaintRect.intersect(contentRect); + return prepaintRect; } diff --git a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h index d5b64e916..d2ed45c04 100644 --- a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h @@ -56,11 +56,7 @@ public: virtual void setLayerTreeHost(CCLayerTreeHost*) OVERRIDE; - // Reserves all existing and valid tile textures to protect them from being - // recycled by the texture manager. - void protectTileTextures(const IntRect& layerRect); - - virtual void reserveTextures() OVERRIDE; + virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; virtual Region visibleContentOpaqueRegion() const OVERRIDE; @@ -89,10 +85,7 @@ protected: // Prepare data needed to update textures that intersect with layerRect. void updateLayerRect(CCTextureUpdater&, const IntRect& layerRect, const CCOcclusionTracker*); - // Same as above, but this will try to paint additional surrounding content if idle. - void idleUpdateLayerRect(CCTextureUpdater&, const IntRect& layerRect, const CCOcclusionTracker*); - - // After preparing an update, returns true if more pre-painting is needed. + // After preparing an update, returns true if more painting is needed. bool needsIdlePaint(const IntRect& layerRect); IntRect idlePaintRect(const IntRect& visibleLayerRect); @@ -100,7 +93,7 @@ protected: bool skipsDraw() const { return m_skipsDraw; } // Virtual for testing - virtual TextureManager* textureManager() const; + virtual CCPrioritizedTextureManager* textureManager() const; private: virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl() OVERRIDE; @@ -111,6 +104,8 @@ private: bool tileOnlyNeedsPartialUpdate(UpdatableTile*); bool tileNeedsBufferedUpdate(UpdatableTile*); + void setTexturePrioritiesInRect(const CCPriorityCalculator&, const IntRect& visibleLayerRect); + void updateTiles(bool idle, int left, int top, int right, int bottom, CCTextureUpdater&, const CCOcclusionTracker*); UpdatableTile* tileAt(int, int) const; diff --git a/Source/WebCore/platform/graphics/chromium/TrackingTextureAllocator.cpp b/Source/WebCore/platform/graphics/chromium/TrackingTextureAllocator.cpp index 8e586e25a..c589a3c6e 100644 --- a/Source/WebCore/platform/graphics/chromium/TrackingTextureAllocator.cpp +++ b/Source/WebCore/platform/graphics/chromium/TrackingTextureAllocator.cpp @@ -33,8 +33,9 @@ namespace WebCore { -TrackingTextureAllocator::TrackingTextureAllocator(WebKit::WebGraphicsContext3D* context) +TrackingTextureAllocator::TrackingTextureAllocator(WebKit::WebGraphicsContext3D* context, int maxTextureSize) : m_context(context) + , m_maxTextureSize(maxTextureSize) , m_currentMemoryUseBytes(0) , m_textureUsageHint(Any) , m_useTextureStorageExt(false) @@ -71,6 +72,9 @@ static bool isTextureFormatSupportedForStorage(GC3Denum format) unsigned TrackingTextureAllocator::createTexture(const IntSize& size, GC3Denum format) { + if (size.width() > m_maxTextureSize || size.height() > m_maxTextureSize) + return 0; + m_currentMemoryUseBytes += TextureManager::memoryUseBytes(size, format); unsigned textureId = 0; diff --git a/Source/WebCore/platform/graphics/chromium/TrackingTextureAllocator.h b/Source/WebCore/platform/graphics/chromium/TrackingTextureAllocator.h index c10c25721..78ef40d1b 100644 --- a/Source/WebCore/platform/graphics/chromium/TrackingTextureAllocator.h +++ b/Source/WebCore/platform/graphics/chromium/TrackingTextureAllocator.h @@ -38,9 +38,9 @@ namespace WebCore { class TrackingTextureAllocator : public TextureAllocator { WTF_MAKE_NONCOPYABLE(TrackingTextureAllocator); public: - static PassOwnPtr<TrackingTextureAllocator> create(WebKit::WebGraphicsContext3D* context) + static PassOwnPtr<TrackingTextureAllocator> create(WebKit::WebGraphicsContext3D* context, int maxTextureSize) { - return adoptPtr(new TrackingTextureAllocator(context)); + return adoptPtr(new TrackingTextureAllocator(context, maxTextureSize)); } virtual ~TrackingTextureAllocator(); @@ -56,9 +56,10 @@ public: void setUseTextureStorageExt(bool useStorageExt) { m_useTextureStorageExt = useStorageExt; } protected: - explicit TrackingTextureAllocator(WebKit::WebGraphicsContext3D*); + TrackingTextureAllocator(WebKit::WebGraphicsContext3D*, int maxTextureSize); WebKit::WebGraphicsContext3D* m_context; + int m_maxTextureSize; size_t m_currentMemoryUseBytes; TextureUsageHint m_textureUsageHint; bool m_useTextureStorageExt; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp index 1dbb59408..da9942663 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp @@ -186,6 +186,7 @@ FloatRect CCDamageTracker::removeRectFromCurrentFrame(int layerID, bool& layerIs void CCDamageTracker::saveRectForNextFrame(int layerID, const FloatRect& targetSpaceRect) { // This layer should not yet exist in next frame's history. + ASSERT(layerID > 0); ASSERT(m_nextRectHistory->find(layerID) == m_nextRectHistory->end()); m_nextRectHistory->set(layerID, targetSpaceRect); } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h index 8d6a2ee8d..a86c587af 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h @@ -70,14 +70,7 @@ private: // To correctly track exposed regions, two hashtables of rects are maintained. // The "current" map is used to compute exposed regions of the current frame, while // the "next" map is used to collect layer rects that are used in the next frame. - struct RectMapKeyTraits : HashTraits<int> { - static const bool emptyValueIsZero = false; - static const bool needsDestruction = false; - static int emptyValue() { return -1; } - static void constructDeletedValue(int& slot) { slot = -2; } - static bool isDeletedValue(int value) { return value == -2; } - }; - typedef HashMap<int, FloatRect, DefaultHash<int>::Hash, RectMapKeyTraits> RectMap; + typedef HashMap<int, FloatRect> RectMap; OwnPtr<RectMap> m_currentRectHistory; OwnPtr<RectMap> m_nextRectHistory; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDebugBorderDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCDebugBorderDrawQuad.cpp index b4a71dc5f..1527c47c5 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCDebugBorderDrawQuad.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCDebugBorderDrawQuad.cpp @@ -29,18 +29,18 @@ namespace WebCore { -PassOwnPtr<CCDebugBorderDrawQuad> CCDebugBorderDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const Color& color, int width) +PassOwnPtr<CCDebugBorderDrawQuad> CCDebugBorderDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color, int width) { return adoptPtr(new CCDebugBorderDrawQuad(sharedQuadState, quadRect, color, width)); } -CCDebugBorderDrawQuad::CCDebugBorderDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const Color& color, int width) +CCDebugBorderDrawQuad::CCDebugBorderDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color, int width) : CCDrawQuad(sharedQuadState, CCDrawQuad::DebugBorder, quadRect) , m_color(color) , m_width(width) { m_quadOpaque = false; - if (m_color.hasAlpha()) + if (SkColorGetA(m_color) < 255) m_needsBlending = true; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDebugBorderDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCDebugBorderDrawQuad.h index 0226aed76..ea1cf8476 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCDebugBorderDrawQuad.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCDebugBorderDrawQuad.h @@ -26,7 +26,7 @@ #ifndef CCDebugBorderDrawQuad_h #define CCDebugBorderDrawQuad_h -#include "Color.h" +#include "SkColor.h" #include "cc/CCDrawQuad.h" #include <wtf/PassOwnPtr.h> @@ -35,15 +35,15 @@ namespace WebCore { class CCDebugBorderDrawQuad : public CCDrawQuad { WTF_MAKE_NONCOPYABLE(CCDebugBorderDrawQuad); public: - static PassOwnPtr<CCDebugBorderDrawQuad> create(const CCSharedQuadState*, const IntRect&, const Color&, int width); + static PassOwnPtr<CCDebugBorderDrawQuad> create(const CCSharedQuadState*, const IntRect&, SkColor, int width); - const Color& color() const { return m_color; }; + SkColor color() const { return m_color; }; int width() const { return m_width; } private: - CCDebugBorderDrawQuad(const CCSharedQuadState*, const IntRect&, const Color&, int width); + CCDebugBorderDrawQuad(const CCSharedQuadState*, const IntRect&, SkColor, int width); - Color m_color; + SkColor m_color; int m_width; }; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.cpp index 17d5946ec..c6132178e 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.cpp @@ -40,10 +40,10 @@ CCDebugRectHistory::CCDebugRectHistory() bool CCDebugRectHistory::enabled(const CCLayerTreeSettings& settings) { - return settings.showPaintRects || settings.showPropertyChangedRects || settings.showSurfaceDamageRects; + return settings.showPaintRects || settings.showPropertyChangedRects || settings.showSurfaceDamageRects || settings.showScreenSpaceRects || settings.showReplicaScreenSpaceRects || settings.showOccludingRects; } -void CCDebugRectHistory::saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, const Vector<CCLayerImpl*>& renderSurfaceLayerList, const CCLayerTreeSettings& settings) +void CCDebugRectHistory::saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, const Vector<CCLayerImpl*>& renderSurfaceLayerList, const Vector<IntRect>& occludingScreenSpaceRects, const CCLayerTreeSettings& settings) { // For now, clear all rects from previous frames. In the future we may want to store // all debug rects for a history of many frames. @@ -57,6 +57,12 @@ void CCDebugRectHistory::saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, c if (settings.showSurfaceDamageRects) saveSurfaceDamageRects(renderSurfaceLayerList); + + if (settings.showScreenSpaceRects) + saveScreenSpaceRects(renderSurfaceLayerList); + + if (settings.showOccludingRects) + saveOccludingRects(occludingScreenSpaceRects); } @@ -104,6 +110,26 @@ void CCDebugRectHistory::saveSurfaceDamageRects(const Vector<CCLayerImpl* >& ren } } +void CCDebugRectHistory::saveScreenSpaceRects(const Vector<CCLayerImpl* >& renderSurfaceLayerList) +{ + for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { + CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; + CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); + ASSERT(renderSurface); + + m_debugRects.append(CCDebugRect(ScreenSpaceRectType, CCMathUtil::mapClippedRect(renderSurface->screenSpaceTransform(), renderSurface->contentRect()))); + + if (renderSurfaceLayer->replicaLayer()) + m_debugRects.append(CCDebugRect(ReplicaScreenSpaceRectType, CCMathUtil::mapClippedRect(renderSurface->replicaScreenSpaceTransform(), renderSurface->contentRect()))); + } +} + +void CCDebugRectHistory::saveOccludingRects(const Vector<IntRect>& occludingRects) +{ + for (size_t i = 0; i < occludingRects.size(); ++i) + m_debugRects.append(CCDebugRect(OccludingRectType, occludingRects[i])); +} + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.h b/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.h index bb3cdb79d..7fd00c3f6 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCDebugRectHistory.h @@ -28,6 +28,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "FloatRect.h" +#include "IntRect.h" #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> @@ -37,7 +38,7 @@ namespace WebCore { class CCLayerImpl; struct CCLayerTreeSettings; -// There are currently three types of debug rects: +// There are currently six types of debug rects: // // - Paint rects (update rects): regions of a layer that needed to be re-uploaded to the // texture resource; in most cases implying that WebCore had to repaint them, too. @@ -50,7 +51,13 @@ struct CCLayerTreeSettings; // layers and surfaces that contribute to it. This includes (1) paint rects, (2) property- // changed rects, and (3) newly exposed areas. // -enum DebugRectType { PaintRectType, PropertyChangedRectType, SurfaceDamageRectType }; +// - Screen space rects: this is the region the contents occupy in screen space. +// +// - Replica screen space rects: this is the region the replica's contents occupy in screen space. +// +// - Occluding rects: these are the regions that contribute to the occluded region. +// +enum DebugRectType { PaintRectType, PropertyChangedRectType, SurfaceDamageRectType, ScreenSpaceRectType, ReplicaScreenSpaceRectType, OccludingRectType }; struct CCDebugRect { CCDebugRect(DebugRectType newType, FloatRect newRect) @@ -75,7 +82,7 @@ public: bool enabled(const CCLayerTreeSettings&); // Note: Saving debug rects must happen before layers' change tracking is reset. - void saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, const Vector<CCLayerImpl*>& renderSurfaceLayerList, const CCLayerTreeSettings&); + void saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, const Vector<CCLayerImpl*>& renderSurfaceLayerList, const Vector<IntRect>& occludingScreenSpaceRects, const CCLayerTreeSettings&); const Vector<CCDebugRect>& debugRects() { return m_debugRects; } @@ -85,6 +92,8 @@ private: void savePaintRects(CCLayerImpl*); void savePropertyChangedRects(const Vector<CCLayerImpl*>& renderSurfaceLayerList); void saveSurfaceDamageRects(const Vector<CCLayerImpl* >& renderSurfaceLayerList); + void saveScreenSpaceRects(const Vector<CCLayerImpl* >& renderSurfaceLayerList); + void saveOccludingRects(const Vector<IntRect>& occludingScreenSpaceRects); Vector<CCDebugRect> m_debugRects; }; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp index 3ab393fd9..df7f31554 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp @@ -66,7 +66,7 @@ void CCFrameRateController::setActive(bool active) { if (m_timeSource->active() == active) return; - TRACE_EVENT("CCFrameRateController::setActive", 0, (active ? "active" : "inactive")); + TRACE_EVENT1("cc", "CCFrameRateController::setActive", "active", active); m_timeSource->setActive(active); } @@ -81,7 +81,7 @@ void CCFrameRateController::onTimerTick() // Don't forward the tick if we have too many frames in flight. if (m_maxFramesPending && m_numFramesPending >= m_maxFramesPending) { - TRACE_EVENT("CCFrameRateController::onTimerTickButMaxFramesPending", 0, 0); + TRACE_EVENT0("cc", "CCFrameRateController::onTimerTickButMaxFramesPending"); return; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCGraphicsContext.h b/Source/WebCore/platform/graphics/chromium/cc/CCGraphicsContext.h index 43536a421..405885ffb 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCGraphicsContext.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCGraphicsContext.h @@ -29,6 +29,7 @@ #include <public/WebGraphicsContext3D.h> #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> namespace WebCore { diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp index f3d415dcf..731f770c0 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp @@ -63,7 +63,7 @@ bool CCHeadsUpDisplay::showPlatformLayerTree(const CCLayerTreeSettings& settings bool CCHeadsUpDisplay::showDebugRects(const CCLayerTreeSettings& settings) const { - return settings.showPaintRects || settings.showPropertyChangedRects || settings.showSurfaceDamageRects; + return settings.showPaintRects || settings.showPropertyChangedRects || settings.showSurfaceDamageRects || settings.showScreenSpaceRects || settings.showReplicaScreenSpaceRects || settings.showOccludingRects; } void CCHeadsUpDisplay::draw(CCLayerTreeHostImpl* layerTreeHostImpl) @@ -75,20 +75,20 @@ void CCHeadsUpDisplay::draw(CCLayerTreeHostImpl* layerTreeHostImpl) return; } if (!m_hudTexture) - m_hudTexture = ManagedTexture::create(layerRenderer->implTextureManager()); + m_hudTexture = CCScopedTexture::create(layerRenderer->implTextureAllocator()); const CCLayerTreeSettings& settings = layerTreeHostImpl->settings(); // Use a fullscreen texture only if we need to... IntSize hudSize; if (showPlatformLayerTree(settings) || showDebugRects(settings)) { - hudSize.setWidth(min(2048, layerTreeHostImpl->viewportSize().width())); - hudSize.setHeight(min(2048, layerTreeHostImpl->viewportSize().height())); + hudSize.setWidth(min(2048, layerTreeHostImpl->deviceViewportSize().width())); + hudSize.setHeight(min(2048, layerTreeHostImpl->deviceViewportSize().height())); } else { hudSize.setWidth(512); hudSize.setHeight(128); } - if (!m_hudTexture->reserve(hudSize, GraphicsContext3D::RGBA)) + if (!m_hudTexture->id() && !m_hudTexture->allocate(hudSize, GraphicsContext3D::RGBA)) return; // Render pixels into the texture. @@ -104,7 +104,7 @@ void CCHeadsUpDisplay::draw(CCLayerTreeHostImpl* layerTreeHostImpl) { PlatformCanvas::AutoLocker locker(&canvas); - m_hudTexture->bindTexture(layerTreeHostImpl->context(), layerRenderer->implTextureAllocator()); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_hudTexture->id())); bool uploadedViaMap = false; if (layerRenderer->capabilities().usingMapSub) { uint8_t* pixelDest = static_cast<uint8_t*>(context->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, hudSize.width(), hudSize.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY)); @@ -122,8 +122,6 @@ void CCHeadsUpDisplay::draw(CCLayerTreeHostImpl* layerTreeHostImpl) } layerRenderer->drawHeadsUpDisplay(m_hudTexture.get(), hudSize); - - m_hudTexture->unreserve(); } void CCHeadsUpDisplay::drawHudContents(GraphicsContext* context, CCLayerTreeHostImpl* layerTreeHostImpl, const CCLayerTreeSettings& settings, const IntSize& hudSize) @@ -244,6 +242,27 @@ void CCHeadsUpDisplay::drawDebugRects(GraphicsContext* context, CCDebugRectHisto context->fillRect(debugRects[i].rect, Color(200, 100, 0, 30), ColorSpaceDeviceRGB); context->strokeRect(debugRects[i].rect, 2.0); } + + if (debugRects[i].type == ReplicaScreenSpaceRectType) { + // Screen space rects in green. + context->setStrokeColor(Color(100, 200, 0, 255), ColorSpaceDeviceRGB); + context->fillRect(debugRects[i].rect, Color(100, 200, 0, 30), ColorSpaceDeviceRGB); + context->strokeRect(debugRects[i].rect, 2.0); + } + + if (debugRects[i].type == ScreenSpaceRectType) { + // Screen space rects in purple. + context->setStrokeColor(Color(100, 0, 200, 255), ColorSpaceDeviceRGB); + context->fillRect(debugRects[i].rect, Color(100, 0, 200, 10), ColorSpaceDeviceRGB); + context->strokeRect(debugRects[i].rect, 2.0); + } + + if (debugRects[i].type == OccludingRectType) { + // Occluding rects in a reddish color. + context->setStrokeColor(Color(200, 0, 100, 255), ColorSpaceDeviceRGB); + context->fillRect(debugRects[i].rect, Color(200, 0, 100, 10), ColorSpaceDeviceRGB); + context->strokeRect(debugRects[i].rect, 2.0); + } } } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h index c505a2086..266bf51e1 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h @@ -27,8 +27,8 @@ #if USE(ACCELERATED_COMPOSITING) -#include "ManagedTexture.h" #include "cc/CCFontAtlas.h" +#include "cc/CCScopedTexture.h" namespace WebCore { @@ -36,6 +36,7 @@ class CCDebugRectHistory; class CCFrameRateCounter; class CCLayerTreeHostImpl; class GraphicsContext; +class TexureAllocator; struct CCLayerTreeSettings; @@ -66,7 +67,7 @@ private: bool showPlatformLayerTree(const CCLayerTreeSettings&) const; bool showDebugRects(const CCLayerTreeSettings&) const; - OwnPtr<ManagedTexture> m_hudTexture; + OwnPtr<CCScopedTexture> m_hudTexture; OwnPtr<CCFontAtlas> m_fontAtlas; }; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp index 02ed80f1e..bd3e6e60c 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp @@ -26,7 +26,6 @@ #include "cc/CCLayerAnimationController.h" -#include "GraphicsLayer.h" // for KeyframeValueList #include "cc/CCActiveAnimation.h" #include "cc/CCKeyframedAnimationCurve.h" #include <public/WebTransformationMatrix.h> diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp index a3ab4f3b4..44772156d 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp @@ -54,6 +54,7 @@ CCLayerImpl::CCLayerImpl(int id) , m_scrollable(false) , m_shouldScrollOnMainThread(false) , m_haveWheelEventHandlers(false) + , m_backgroundColor(0) , m_doubleSided(true) , m_layerPropertyChanged(false) , m_layerSurfacePropertyChanged(false) @@ -74,7 +75,7 @@ CCLayerImpl::CCLayerImpl(int id) , m_drawDepth(0) , m_drawOpacity(0) , m_drawOpacityIsAnimating(false) - , m_debugBorderColor(0, 0, 0, 0) + , m_debugBorderColor(0) , m_debugBorderWidth(0) , m_drawTransformIsAnimating(false) , m_screenSpaceTransformIsAnimating(false) @@ -84,7 +85,7 @@ CCLayerImpl::CCLayerImpl(int id) , m_layerAnimationController(CCLayerAnimationController::create(this)) { ASSERT(CCProxy::isImplThread()); - ASSERT(m_layerId >= 0); + ASSERT(m_layerId > 0); } CCLayerImpl::~CCLayerImpl() @@ -230,7 +231,7 @@ const IntRect CCLayerImpl::getDrawRect() const // Form the matrix used by the shader to map the corners of the layer's // bounds into the view space. FloatRect layerRect(-0.5 * bounds().width(), -0.5 * bounds().height(), bounds().width(), bounds().height()); - IntRect mappedRect = enclosingIntRect(drawTransform().mapRect(layerRect)); + IntRect mappedRect = enclosingIntRect(CCMathUtil::mapClippedRect(drawTransform(), layerRect)); return mappedRect; } @@ -440,7 +441,7 @@ void CCLayerImpl::setAnchorPointZ(float anchorPointZ) noteLayerPropertyChangedForSubtree(); } -void CCLayerImpl::setBackgroundColor(const Color& backgroundColor) +void CCLayerImpl::setBackgroundColor(SkColor backgroundColor) { if (m_backgroundColor == backgroundColor) return; @@ -541,7 +542,7 @@ bool CCLayerImpl::transformIsAnimating() const return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Transform); } -void CCLayerImpl::setDebugBorderColor(Color debugBorderColor) +void CCLayerImpl::setDebugBorderColor(SkColor debugBorderColor) { if (m_debugBorderColor == debugBorderColor) return; @@ -561,7 +562,7 @@ void CCLayerImpl::setDebugBorderWidth(float debugBorderWidth) bool CCLayerImpl::hasDebugBorders() const { - return debugBorderColor().alpha() && debugBorderWidth() > 0; + return SkColorGetA(m_debugBorderColor) && debugBorderWidth() > 0; } void CCLayerImpl::setContentBounds(const IntSize& contentBounds) diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h index c735b919d..00a351b22 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h @@ -26,10 +26,10 @@ #ifndef CCLayerImpl_h #define CCLayerImpl_h -#include "Color.h" #include "FloatRect.h" #include "IntRect.h" #include "Region.h" +#include "SkColor.h" #include "TextStream.h" #include "cc/CCInputHandler.h" #include "cc/CCLayerAnimationController.h" @@ -111,8 +111,8 @@ public: void setAnchorPointZ(float); float anchorPointZ() const { return m_anchorPointZ; } - void setBackgroundColor(const Color&); - Color backgroundColor() const { return m_backgroundColor; } + void setBackgroundColor(SkColor); + SkColor backgroundColor() const { return m_backgroundColor; } void setFilters(const WebKit::WebFilterOperations&); const WebKit::WebFilterOperations& filters() const { return m_filters; } @@ -154,8 +154,8 @@ public: const WebKit::WebTransformationMatrix& sublayerTransform() const { return m_sublayerTransform; } // Debug layer border - visual effect only, do not change geometry/clipping/etc. - void setDebugBorderColor(Color); - Color debugBorderColor() const { return m_debugBorderColor; } + void setDebugBorderColor(SkColor); + SkColor debugBorderColor() const { return m_debugBorderColor; } void setDebugBorderWidth(float); float debugBorderWidth() const { return m_debugBorderWidth; } bool hasDebugBorders() const; @@ -317,7 +317,7 @@ private: bool m_shouldScrollOnMainThread; bool m_haveWheelEventHandlers; Region m_nonFastScrollableRegion; - Color m_backgroundColor; + SkColor m_backgroundColor; // Whether the "back" of this layer should draw. bool m_doubleSided; @@ -371,7 +371,7 @@ private: bool m_drawOpacityIsAnimating; // Debug borders. - Color m_debugBorderColor; + SkColor m_debugBorderColor; float m_debugBorderWidth; // Debug layer name. diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp index 351112bd5..414b20526 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp @@ -85,8 +85,8 @@ CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCLayerTre , m_pageScaleFactor(1) , m_minPageScaleFactor(1) , m_maxPageScaleFactor(1) - , m_triggerIdlePaints(true) - , m_backgroundColor(Color::white) + , m_triggerIdleUpdates(true) + , m_backgroundColor(SK_ColorWHITE) , m_hasTransparentBackground(false) , m_partialTextureUpdateRequests(0) { @@ -96,7 +96,7 @@ CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCLayerTre bool CCLayerTreeHost::initialize() { - TRACE_EVENT("CCLayerTreeHost::initialize", this, 0); + TRACE_EVENT0("cc", "CCLayerTreeHost::initialize"); if (CCProxy::hasImplThread()) m_proxy = CCThreadProxy::create(this); @@ -122,11 +122,14 @@ bool CCLayerTreeHost::initialize() CCLayerTreeHost::~CCLayerTreeHost() { ASSERT(CCProxy::isMainThread()); - TRACE_EVENT("CCLayerTreeHost::~CCLayerTreeHost", this, 0); + TRACE_EVENT0("cc", "CCLayerTreeHost::~CCLayerTreeHost"); ASSERT(m_proxy); m_proxy->stop(); m_proxy.clear(); numLayerTreeInstances--; + RateLimiterMap::iterator it = m_rateLimiters.begin(); + if (it != m_rateLimiters.end()) + it->second->stop(); } void CCLayerTreeHost::setSurfaceReady() @@ -136,7 +139,7 @@ void CCLayerTreeHost::setSurfaceReady() void CCLayerTreeHost::initializeLayerRenderer() { - TRACE_EVENT("CCLayerTreeHost::initializeLayerRenderer", this, 0); + TRACE_EVENT0("cc", "CCLayerTreeHost::initializeLayerRenderer"); if (!m_proxy->initializeLayerRenderer()) { // Uh oh, better tell the client that we can't do anything with this context. m_client->didRecreateContext(false); @@ -149,7 +152,7 @@ void CCLayerTreeHost::initializeLayerRenderer() // Update m_settings based on partial update capability. m_settings.maxPartialTextureUpdates = min(m_settings.maxPartialTextureUpdates, m_proxy->maxPartialTextureUpdates()); - m_contentsTextureManager = TextureManager::create(0, 0, m_proxy->layerRendererCapabilities().maxTextureSize); + m_contentsTextureManager = CCPrioritizedTextureManager::create(0, m_proxy->layerRendererCapabilities().maxTextureSize); m_layerRendererInitialized = true; @@ -198,7 +201,7 @@ void CCLayerTreeHost::deleteContentsTexturesOnImplThread(TextureAllocator* alloc { ASSERT(CCProxy::isImplThread()); if (m_layerRendererInitialized) - m_contentsTextureManager->evictAndDeleteAllTextures(allocator); + m_contentsTextureManager->clearAllMemory(allocator); } void CCLayerTreeHost::acquireLayerTextures() @@ -225,10 +228,9 @@ void CCLayerTreeHost::layout() void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) { ASSERT(CCProxy::isImplThread()); - TRACE_EVENT("CCLayerTreeHost::commitTo", this, 0); + TRACE_EVENT0("cc", "CCLayerTreeHost::commitTo"); - m_contentsTextureManager->reduceMemoryToLimit(m_contentsTextureManager->preferredMemoryLimitBytes()); - m_contentsTextureManager->deleteEvictedTextures(hostImpl->contentsTextureAllocator()); + m_contentsTextureManager->reduceMemory(hostImpl->contentsTextureAllocator()); } // This function commits the CCLayerTreeHost to an impl tree. When modifying @@ -260,7 +262,6 @@ void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) void CCLayerTreeHost::commitComplete() { m_deleteTextureAfterCommitList.clear(); - m_contentsTextureManager->unprotectAllTextures(); m_client->didCommit(); } @@ -278,7 +279,7 @@ PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayer void CCLayerTreeHost::didLoseContext() { - TRACE_EVENT("CCLayerTreeHost::didLoseContext", 0, this); + TRACE_EVENT0("cc", "CCLayerTreeHost::didLoseContext"); ASSERT(CCProxy::isMainThread()); m_contextLost = true; m_numFailedRecreateAttempts = 0; @@ -287,9 +288,9 @@ void CCLayerTreeHost::didLoseContext() bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect) { - m_triggerIdlePaints = false; + m_triggerIdleUpdates = false; bool ret = m_proxy->compositeAndReadback(pixels, rect); - m_triggerIdlePaints = true; + m_triggerIdleUpdates = true; return ret; } @@ -395,7 +396,7 @@ void CCLayerTreeHost::evictAllContentTextures() { ASSERT(CCProxy::isMainThread()); ASSERT(m_contentsTextureManager.get()); - m_contentsTextureManager->evictAndRemoveAllDeletedTextures(); + m_contentsTextureManager->allBackingTexturesWereDeleted(); } void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec) @@ -410,7 +411,7 @@ void CCLayerTreeHost::loseContext(int numTimes) m_proxy->loseContext(); } -TextureManager* CCLayerTreeHost::contentsTextureManager() const +CCPrioritizedTextureManager* CCLayerTreeHost::contentsTextureManager() const { return m_contentsTextureManager.get(); } @@ -442,10 +443,10 @@ bool CCLayerTreeHost::initializeLayerRendererIfNeeded() } -void CCLayerTreeHost::updateLayers(CCTextureUpdater& updater, size_t contentsMemoryLimitBytes) +void CCLayerTreeHost::updateLayers(CCTextureUpdater& updater, size_t memoryAllocationLimitBytes) { ASSERT(m_layerRendererInitialized); - ASSERT(contentsMemoryLimitBytes); + ASSERT(memoryAllocationLimitBytes); if (!rootLayer()) return; @@ -453,14 +454,14 @@ void CCLayerTreeHost::updateLayers(CCTextureUpdater& updater, size_t contentsMem if (viewportSize().isEmpty()) return; - m_contentsTextureManager->setMemoryAllocationLimitBytes(contentsMemoryLimitBytes); + m_contentsTextureManager->setMaxMemoryLimitBytes(memoryAllocationLimitBytes); updateLayers(rootLayer(), updater); } void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdater& updater) { - TRACE_EVENT("CCLayerTreeHost::updateLayers", this, 0); + TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers"); if (!rootLayer->renderSurface()) rootLayer->createRenderSurface(); @@ -476,7 +477,7 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdater& u rootRenderSurface->clearLayerList(); { - TRACE_EVENT("CCLayerTreeHost::updateLayers::calcDrawEtc", this, 0); + TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers::calcDrawEtc"); WebTransformationMatrix identityMatrix; WebTransformationMatrix deviceScaleTransform; deviceScaleTransform.scale(m_deviceScaleFactor); @@ -489,73 +490,88 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdater& u // Reset partial texture update requests. m_partialTextureUpdateRequests = 0; - reserveTextures(updateList); - - paintLayerContents(updateList, PaintVisible, updater); - if (!m_triggerIdlePaints) - return; - - size_t preferredLimitBytes = m_contentsTextureManager->preferredMemoryLimitBytes(); - size_t maxLimitBytes = m_contentsTextureManager->maxMemoryLimitBytes(); - m_contentsTextureManager->reduceMemoryToLimit(preferredLimitBytes); - if (m_contentsTextureManager->currentMemoryUseBytes() >= preferredLimitBytes) - return; + prioritizeTextures(updateList); - // Idle painting should fail when we hit the preferred memory limit, - // otherwise it will always push us towards the maximum limit. - m_contentsTextureManager->setMaxMemoryLimitBytes(preferredLimitBytes); - // The second (idle) paint will be a no-op in layers where painting already occured above. - paintLayerContents(updateList, PaintIdle, updater); - m_contentsTextureManager->setMaxMemoryLimitBytes(maxLimitBytes); + bool needMoreUpdates = paintLayerContents(updateList, updater); + if (m_triggerIdleUpdates && needMoreUpdates) + setNeedsCommit(); for (size_t i = 0; i < updateList.size(); ++i) updateList[i]->clearRenderSurface(); } -void CCLayerTreeHost::reserveTextures(const LayerList& updateList) +void CCLayerTreeHost::prioritizeTextures(const LayerList& updateList) { // Use BackToFront since it's cheap and this isn't order-dependent. typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType; + m_contentsTextureManager->clearPriorities(); + + CCPriorityCalculator calculator; CCLayerIteratorType end = CCLayerIteratorType::end(&updateList); for (CCLayerIteratorType it = CCLayerIteratorType::begin(&updateList); it != end; ++it) { - if (!it.representsItself() || !it->alwaysReserveTextures()) + if (it.representsItself()) + it->setTexturePriorities(calculator); + else if (it.representsTargetRenderSurface()) { + if (it->maskLayer()) + it->maskLayer()->setTexturePriorities(calculator); + if (it->replicaLayer() && it->replicaLayer()->maskLayer()) + it->replicaLayer()->maskLayer()->setTexturePriorities(calculator); + } + } + + size_t readbackBytes = 0; + size_t maxBackgroundTextureBytes = 0; + size_t contentsTextureBytes = 0; + + // Start iteration at 1 to skip the root surface as it does not have a texture cost. + for (size_t i = 1; i < updateList.size(); ++i) { + LayerChromium* renderSurfaceLayer = updateList[i].get(); + RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface(); + + size_t bytes = TextureManager::memoryUseBytes(renderSurface->contentRect().size(), GraphicsContext3D::RGBA); + contentsTextureBytes += bytes; + + if (renderSurface->backgroundFilters().isEmpty()) continue; - it->reserveTextures(); + + if (bytes > maxBackgroundTextureBytes) + maxBackgroundTextureBytes = bytes; + if (!readbackBytes) + readbackBytes = TextureManager::memoryUseBytes(m_deviceViewportSize, GraphicsContext3D::RGBA); } -} + size_t renderSurfacesBytes = readbackBytes + maxBackgroundTextureBytes + contentsTextureBytes; -// static -void CCLayerTreeHost::update(LayerChromium* layer, PaintType paintType, CCTextureUpdater& updater, const CCOcclusionTracker* occlusion) -{ - ASSERT(layer); - ASSERT(PaintVisible == paintType || PaintIdle == paintType); - if (PaintVisible == paintType) - layer->update(updater, occlusion); - else - layer->idleUpdate(updater, occlusion); + m_contentsTextureManager->prioritizeTextures(renderSurfacesBytes); } -void CCLayerTreeHost::paintMasksForRenderSurface(LayerChromium* renderSurfaceLayer, PaintType paintType, CCTextureUpdater& updater) +bool CCLayerTreeHost::paintMasksForRenderSurface(LayerChromium* renderSurfaceLayer, CCTextureUpdater& updater) { // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point // in code, we already know that at least something will be drawn into this render surface, so the // mask and replica should be painted. + bool needMoreUpdates = false; LayerChromium* maskLayer = renderSurfaceLayer->maskLayer(); - if (maskLayer) - update(maskLayer, paintType, updater, 0); + if (maskLayer) { + maskLayer->update(updater, 0); + needMoreUpdates |= maskLayer->needMoreUpdates(); + } LayerChromium* replicaMaskLayer = renderSurfaceLayer->replicaLayer() ? renderSurfaceLayer->replicaLayer()->maskLayer() : 0; - if (replicaMaskLayer) - update(replicaMaskLayer, paintType, updater, 0); + if (replicaMaskLayer) { + replicaMaskLayer->update(updater, 0); + needMoreUpdates |= replicaMaskLayer->needMoreUpdates(); + } + return needMoreUpdates; } -void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, PaintType paintType, CCTextureUpdater& updater) +bool CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, CCTextureUpdater& updater) { // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk. typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType; + bool needMoreUpdates = false; bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off. CCOcclusionTracker occlusionTracker(IntRect(IntPoint(), deviceViewportSize()), recordMetricsForFrame); occlusionTracker.setMinimumTrackingSize(CCOcclusionTracker::preferredMinimumTrackingSize()); @@ -566,16 +582,21 @@ void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList if (it.representsTargetRenderSurface()) { ASSERT(it->renderSurface()->drawOpacity() || it->renderSurface()->drawOpacityIsAnimating()); - paintMasksForRenderSurface(*it, paintType, updater); + needMoreUpdates |= paintMasksForRenderSurface(*it, updater); } else if (it.representsItself()) { ASSERT(!it->bounds().isEmpty()); - update(*it, paintType, updater, &occlusionTracker); + it->update(updater, &occlusionTracker); + needMoreUpdates |= it->needMoreUpdates(); } occlusionTracker.leaveLayer(it); } + occlusionTracker.overdrawMetrics().didUseContentsTextureMemoryBytes(m_contentsTextureManager->memoryAboveCutoffBytes()); + occlusionTracker.overdrawMetrics().didUseRenderSurfaceTextureMemoryBytes(m_contentsTextureManager->memoryForRenderSurfacesBytes()); occlusionTracker.overdrawMetrics().recordMetrics(this); + + return needMoreUpdates; } static LayerChromium* findFirstScrollableLayer(LayerChromium* layer) @@ -662,7 +683,7 @@ bool CCLayerTreeHost::requestPartialTextureUpdate() return true; } -void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<ManagedTexture> texture) +void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<CCPrioritizedTexture> texture) { m_deleteTextureAfterCommitList.append(texture); } @@ -683,7 +704,7 @@ void CCLayerTreeHost::animateLayers(double monotonicTime) if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers) return; - TRACE_EVENT("CCLayerTreeHostImpl::animateLayers", this, 0); + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers"); m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), monotonicTime); } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h index 23ac33140..c2143eae5 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h @@ -25,15 +25,19 @@ #ifndef CCLayerTreeHost_h #define CCLayerTreeHost_h -#include "Color.h" #include "GraphicsContext3D.h" #include "GraphicsTypes3D.h" #include "IntRect.h" #include "RateLimiter.h" +#include "SkColor.h" #include "cc/CCAnimationEvents.h" +#include "cc/CCGraphicsContext.h" +#include "cc/CCLayerTreeHostCommon.h" #include "cc/CCOcclusionTracker.h" +#include "cc/CCPrioritizedTextureManager.h" #include "cc/CCProxy.h" + #include <limits> #include <wtf/HashMap.h> #include <wtf/OwnPtr.h> @@ -50,7 +54,7 @@ class CCTextureUpdater; class ManagedTexture; class Region; class TextureAllocator; -class TextureManager; +class CCPrioritizedTextureManager; struct CCRenderingStats; struct CCScrollAndScaleSet; @@ -85,6 +89,9 @@ struct CCLayerTreeSettings { , showPaintRects(false) , showPropertyChangedRects(false) , showSurfaceDamageRects(false) + , showScreenSpaceRects(false) + , showReplicaScreenSpaceRects(false) + , showOccludingRects(false) , refreshRate(0) , maxPartialTextureUpdates(std::numeric_limits<size_t>::max()) , defaultTileSize(IntSize(256, 256)) @@ -98,6 +105,9 @@ struct CCLayerTreeSettings { bool showPaintRects; bool showPropertyChangedRects; bool showSurfaceDamageRects; + bool showScreenSpaceRects; + bool showReplicaScreenSpaceRects; + bool showOccludingRects; double refreshRate; size_t maxPartialTextureUpdates; IntSize defaultTileSize; @@ -226,11 +236,11 @@ public: void setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor); - void setBackgroundColor(const Color& color) { m_backgroundColor = color; } + void setBackgroundColor(SkColor color) { m_backgroundColor = color; } void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; } - TextureManager* contentsTextureManager() const; + CCPrioritizedTextureManager* contentsTextureManager() const; // This will cause contents texture manager to evict all textures, but // without deleting them. This happens after all content textures have @@ -253,7 +263,7 @@ public: bool bufferedUpdates(); bool requestPartialTextureUpdate(); - void deleteTextureAfterCommit(PassOwnPtr<ManagedTexture>); + void deleteTextureAfterCommit(PassOwnPtr<CCPrioritizedTexture>); void setDeviceScaleFactor(float); float deviceScaleFactor() const { return m_deviceScaleFactor; } @@ -264,18 +274,17 @@ protected: private: typedef Vector<RefPtr<LayerChromium> > LayerList; - typedef Vector<OwnPtr<ManagedTexture> > TextureList; + typedef Vector<OwnPtr<CCPrioritizedTexture> > TextureList; void initializeLayerRenderer(); - enum PaintType { PaintVisible, PaintIdle }; - static void update(LayerChromium*, PaintType, CCTextureUpdater&, const CCOcclusionTracker*); - void paintLayerContents(const LayerList&, PaintType, CCTextureUpdater&); - void paintMasksForRenderSurface(LayerChromium*, PaintType, CCTextureUpdater&); + static void update(LayerChromium*, CCTextureUpdater&, const CCOcclusionTracker*); + bool paintLayerContents(const LayerList&, CCTextureUpdater&); + bool paintMasksForRenderSurface(LayerChromium*, CCTextureUpdater&); void updateLayers(LayerChromium*, CCTextureUpdater&); - // Pre-reserve textures for any layer marked "always reserve textures" - void reserveTextures(const LayerList&); + + void prioritizeTextures(const LayerList& updateList); void animateLayers(double monotonicTime); bool animateLayersRecursive(LayerChromium* current, double monotonicTime); @@ -298,7 +307,7 @@ private: int m_numFailedRecreateAttempts; RefPtr<LayerChromium> m_rootLayer; - OwnPtr<TextureManager> m_contentsTextureManager; + OwnPtr<CCPrioritizedTextureManager> m_contentsTextureManager; CCLayerTreeSettings m_settings; @@ -313,8 +322,9 @@ private: float m_pageScaleFactor; float m_minPageScaleFactor, m_maxPageScaleFactor; - bool m_triggerIdlePaints; - Color m_backgroundColor; + bool m_triggerIdleUpdates; + + SkColor m_backgroundColor; bool m_hasTransparentBackground; TextureList m_deleteTextureAfterCommitList; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp index c59707a4b..51ae04802 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp @@ -188,19 +188,6 @@ static bool isScaleOrTranslation(const WebTransformationMatrix& m) && m.m44(); } -static inline bool layerOpacityIsOpaque(CCLayerImpl* layer) -{ - return layer->opacity() == 1; -} - -static inline bool layerOpacityIsOpaque(LayerChromium* layer) -{ - // If the opacity is being animated then the opacity on the main thread is unreliable - // (since the impl thread may be using a different opacity), so it should not be trusted. - // In particular, it should not be treated as opaque. - return layer->opacity() == 1 && !layer->opacityIsAnimating(); -} - static inline bool transformToParentIsKnown(CCLayerImpl*) { return true; @@ -303,16 +290,11 @@ static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlig return true; // If the layer clips its descendants but it is not axis-aligned with respect to its parent. - // On the main thread, when the transform is being animated, it is treated as unknown and we - // always error on the side of making a render surface, to let us consider descendents as - // not animating relative to their target to aid culling. - if (layer->masksToBounds() && (!axisAlignedWithRespectToParent || !transformToParentIsKnown(layer)) && descendantDrawsContent) + if (layer->masksToBounds() && !axisAlignedWithRespectToParent && descendantDrawsContent) return true; // If the layer has opacity != 1 and does not have a preserves-3d transform style. - // On the main thread, when opacity is being animated, it is treated as neither 1 - // nor 0. - if (!layerOpacityIsOpaque(layer) && !layer->preserves3D() && descendantDrawsContent) + if (layer->opacity() != 1 && !layer->preserves3D() && descendantDrawsContent) return true; return false; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp index 1dca36a60..26a09e70f 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp @@ -129,6 +129,7 @@ CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCLayerTreeSettings& settings, CC , m_sentPageScaleDelta(1) , m_minPageScale(0) , m_maxPageScale(0) + , m_backgroundColor(0) , m_hasTransparentBackground(false) , m_needsAnimateLayers(false) , m_pinchGestureActive(false) @@ -154,6 +155,7 @@ void CCLayerTreeHostImpl::beginCommit() void CCLayerTreeHostImpl::commitComplete() { + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::commitComplete"); // Recompute max scroll position; must be after layer content bounds are // updated. updateMaxScrollPosition(); @@ -162,14 +164,22 @@ void CCLayerTreeHostImpl::commitComplete() bool CCLayerTreeHostImpl::canDraw() { - if (!m_rootLayerImpl) + if (!m_rootLayerImpl) { + TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no root layer"); return false; - if (viewportSize().isEmpty()) + } + if (viewportSize().isEmpty()) { + TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw empty viewport"); return false; - if (!m_layerRenderer) + } + if (!m_layerRenderer) { + TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no layerRenderer"); return false; - if (m_contentsTexturesWerePurgedSinceLastCommit) + } + if (m_contentsTexturesWerePurgedSinceLastCommit) { + TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw contents textures purged"); return false; + } return true; } @@ -285,7 +295,10 @@ bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame) CCLayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex]; CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); - OwnPtr<CCRenderPass> pass = CCRenderPass::create(renderSurface); + // FIXME: Make this unique across all CCLayerTreeHostImpls. + int globalRenderPassId = renderSurfaceLayer->id(); + + OwnPtr<CCRenderPass> pass = CCRenderPass::create(renderSurface, globalRenderPassId); surfacePassMap.add(renderSurface, pass.get()); frame.renderPasses.append(pass.release()); } @@ -294,6 +307,9 @@ bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame) CCOcclusionTrackerImpl occlusionTracker(enclosingIntRect(m_rootScissorRect), recordMetricsForFrame); occlusionTracker.setMinimumTrackingSize(CCOcclusionTrackerImpl::preferredMinimumTrackingSize()); + if (settings().showOccludingRects) + occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects); + // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk. typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType; @@ -337,8 +353,9 @@ bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame) if (drawFrame) occlusionTracker.overdrawMetrics().recordMetrics(this); + removeRenderPasses(CullRenderPassesWithNoQuads(), frame); m_layerRenderer->decideRenderPassAllocationsForFrame(frame.renderPasses); - removePassesWithCachedTextures(frame.renderPasses, frame.skippedPasses); + removeRenderPasses(CullRenderPassesWithCachedTextures(*m_layerRenderer), frame); return drawFrame; } @@ -389,6 +406,7 @@ IntSize CCLayerTreeHostImpl::contentSize() const return m_rootScrollLayerImpl->children()[0]->contentBounds(); } +// static void CCLayerTreeHostImpl::removeRenderPassesRecursive(CCRenderPassList& passes, size_t bottomPass, const CCRenderPass* firstToRemove, CCRenderPassList& skippedPasses) { size_t removeIndex = passes.find(firstToRemove); @@ -418,10 +436,41 @@ void CCLayerTreeHostImpl::removeRenderPassesRecursive(CCRenderPassList& passes, skippedPasses.append(removedPass.release()); } -void CCLayerTreeHostImpl::removePassesWithCachedTextures(CCRenderPassList& passes, CCRenderPassList& skippedPasses) +bool CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const CCRenderPassList&, const CCRenderPassDrawQuad& quad) const +{ + return quad.contentsChangedSinceLastFrame().isEmpty() && m_renderer.haveCachedResourcesForRenderPassId(quad.renderPassId()); +} + +bool CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const CCRenderPassList& passList, const CCRenderPassDrawQuad& quad) const { - for (int passIndex = passes.size() - 1; passIndex >= 0; --passIndex) { - CCRenderPass* currentPass = passes[passIndex].get(); + size_t passIndex = passList.find(quad.renderPass()); + ASSERT(passIndex != notFound); + + // If any quad or RenderPass draws into this RenderPass, then keep it. + const CCQuadList& quadList = passList[passIndex]->quadList(); + for (CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) { + CCDrawQuad* currentQuad = quadListIterator->get(); + + if (currentQuad->material() != CCDrawQuad::RenderPass) + return false; + + const CCRenderPassDrawQuad* quadInPass = static_cast<CCRenderPassDrawQuad*>(currentQuad); + if (passList.contains(quadInPass->renderPass())) + return false; + } + return true; +} + +// Defined for linking tests. +template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&); +template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&); + +// static +template<typename RenderPassCuller> +void CCLayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame) +{ + for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) { + CCRenderPass* currentPass = frame.renderPasses[it].get(); const CCQuadList& quadList = currentPass->quadList(); CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); @@ -432,23 +481,18 @@ void CCLayerTreeHostImpl::removePassesWithCachedTextures(CCRenderPassList& passe continue; CCRenderPassDrawQuad* renderPassQuad = static_cast<CCRenderPassDrawQuad*>(currentQuad); - CCRenderSurface* targetSurface = renderPassQuad->renderPass()->targetSurface(); - - if (targetSurface->contentsChanged() || !targetSurface->hasCachedContentsTexture()) + if (!culler.shouldRemoveRenderPass(frame.renderPasses, *renderPassQuad)) continue; - // Reserve the texture immediately. We do not need to pass in layer renderer - // since the texture already exists, just needs to be reserved. - if (!targetSurface->prepareContentsTexture(0)) - continue; - - // We are changing the vector in the middle of reverse iteration. - // We are guaranteed that any data from iterator to the end will not change. - // Capture the iterator position from the end, and restore it after the change. - int positionFromEnd = passes.size() - passIndex; - removeRenderPassesRecursive(passes, passIndex, renderPassQuad->renderPass(), skippedPasses); - passIndex = passes.size() - positionFromEnd; - ASSERT(passIndex >= 0); + // We are changing the vector in the middle of iteration. Because we + // delete render passes that draw into the current pass, we are + // guaranteed that any data from the iterator to the end will not + // change. So, capture the iterator position from the end of the + // list, and restore it after the change. + int positionFromEnd = frame.renderPasses.size() - it; + removeRenderPassesRecursive(frame.renderPasses, it, renderPassQuad->renderPass(), frame.skippedPasses); + it = frame.renderPasses.size() - positionFromEnd; + ASSERT(it >= 0); } } } @@ -474,6 +518,7 @@ void CCLayerTreeHostImpl::releaseContentsTextures() { contentsTextureAllocator()->deleteAllTextures(); m_contentsTexturesWerePurgedSinceLastCommit = true; + m_client->setNeedsCommitOnImplThread(); } void CCLayerTreeHostImpl::setMemoryAllocationLimitBytes(size_t bytes) @@ -512,7 +557,7 @@ void CCLayerTreeHostImpl::drawLayers(const FrameData& frame) } if (m_debugRectHistory->enabled(settings())) - m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, settings()); + m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, settings()); if (m_headsUpDisplay->enabled(settings())) m_headsUpDisplay->draw(this); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h index 726037f17..49f2fc62b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h @@ -25,7 +25,7 @@ #ifndef CCLayerTreeHostImpl_h #define CCLayerTreeHostImpl_h -#include "Color.h" +#include "SkColor.h" #include "cc/CCAnimationEvents.h" #include "cc/CCInputHandler.h" #include "cc/CCLayerSorter.h" @@ -42,9 +42,10 @@ class CCDebugRectHistory; class CCFontAtlas; class CCFrameRateCounter; class CCHeadsUpDisplay; -class CCPageScaleAnimation; class CCLayerImpl; class CCLayerTreeHostImplTimeSourceAdapter; +class CCPageScaleAnimation; +class CCRenderPassDrawQuad; class LayerRendererChromium; class TextureAllocator; struct LayerRendererCapabilities; @@ -82,6 +83,7 @@ public: virtual void scheduleAnimation(); struct FrameData { + Vector<IntRect> occludingScreenSpaceRects; CCRenderPassList renderPasses; CCRenderPassList skippedPasses; CCLayerList* renderSurfaceLayerList; @@ -162,8 +164,8 @@ public: void startPageScaleAnimation(const IntSize& tragetPosition, bool useAnchor, float scale, double durationSec); - const Color& backgroundColor() const { return m_backgroundColor; } - void setBackgroundColor(const Color& color) { m_backgroundColor = color; } + SkColor backgroundColor() const { return m_backgroundColor; } + void setBackgroundColor(SkColor color) { m_backgroundColor = color; } bool hasTransparentBackground() const { return m_hasTransparentBackground; } void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; } @@ -176,8 +178,35 @@ public: CCFrameRateCounter* fpsCounter() const { return m_fpsCounter.get(); } CCDebugRectHistory* debugRectHistory() const { return m_debugRectHistory.get(); } - // Removes all render passes for which we have cached textures, and which did not change their content. - static void removePassesWithCachedTextures(CCRenderPassList& passes, CCRenderPassList& skippedPasses); + class CullRenderPassesWithCachedTextures { + public: + bool shouldRemoveRenderPass(const CCRenderPassList&, const CCRenderPassDrawQuad&) const; + + // Iterates from the root first, in order to remove the surfaces closest + // to the root with cached textures, and all surfaces that draw into + // them. + size_t renderPassListBegin(const CCRenderPassList& list) const { return list.size() - 1; } + size_t renderPassListEnd(const CCRenderPassList&) const { return 0 - 1; } + size_t renderPassListNext(size_t it) const { return it - 1; } + + CullRenderPassesWithCachedTextures(CCRenderer& renderer) : m_renderer(renderer) { } + private: + CCRenderer& m_renderer; + }; + + class CullRenderPassesWithNoQuads { + public: + bool shouldRemoveRenderPass(const CCRenderPassList&, const CCRenderPassDrawQuad&) const; + + // Iterates in draw order, so that when a surface is removed, and its + // target becomes empty, then its target can be removed also. + size_t renderPassListBegin(const CCRenderPassList&) const { return 0; } + size_t renderPassListEnd(const CCRenderPassList& list) const { return list.size(); } + size_t renderPassListNext(size_t it) const { return it + 1; } + }; + + template<typename RenderPassCuller> + static void removeRenderPasses(RenderPassCuller, FrameData&); protected: CCLayerTreeHostImpl(const CCLayerTreeSettings&, CCLayerTreeHostImplClient*); @@ -245,7 +274,7 @@ private: float m_sentPageScaleDelta; float m_minPageScale, m_maxPageScale; - Color m_backgroundColor; + SkColor m_backgroundColor; bool m_hasTransparentBackground; // If this is true, it is necessary to traverse the layer tree ticking the animators. diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp index 8471b3e6a..007e74d49 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp @@ -278,13 +278,13 @@ FloatQuad CCMathUtil::projectQuad(const WebTransformationMatrix& transform, cons { FloatQuad projectedQuad; bool clippedPoint; - projectedQuad.setP1(transform.projectPoint(q.p1(), &clippedPoint)); + projectedQuad.setP1(projectPoint(transform, q.p1(), clippedPoint)); clipped = clippedPoint; - projectedQuad.setP2(transform.projectPoint(q.p2(), &clippedPoint)); + projectedQuad.setP2(projectPoint(transform, q.p2(), clippedPoint)); clipped |= clippedPoint; - projectedQuad.setP3(transform.projectPoint(q.p3(), &clippedPoint)); + projectedQuad.setP3(projectPoint(transform, q.p3(), clippedPoint)); clipped |= clippedPoint; - projectedQuad.setP4(transform.projectPoint(q.p4(), &clippedPoint)); + projectedQuad.setP4(projectPoint(transform, q.p4(), clippedPoint)); clipped |= clippedPoint; return projectedQuad; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp index 4836eb528..b49ff9083 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp @@ -45,6 +45,7 @@ template<typename LayerType, typename RenderSurfaceType> CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, bool recordMetricsForFrame) : m_scissorRectInScreenSpace(scissorRectInScreenSpace) , m_overdrawMetrics(CCOverdrawMetrics::create(recordMetricsForFrame)) + , m_occludingScreenSpaceRects(0) { } @@ -150,9 +151,9 @@ static inline Region transformSurfaceOpaqueRegion(const RenderSurfaceType* surfa Region transformedRegion; Vector<IntRect> rects = region.rects(); - // Clipping has been verified above, so mapRect will give correct results. for (size_t i = 0; i < rects.size(); ++i) { - IntRect transformedRect = enclosedIntRect(transform.mapRect(FloatRect(rects[i]))); + // We've already checked for clipping in the mapQuad call above, these calls should not clip anything further. + IntRect transformedRect = enclosedIntRect(CCMathUtil::mapClippedRect(transform, FloatRect(rects[i]))); if (!surface->clipRect().isEmpty()) transformedRect.intersect(surface->clipRect()); transformedRegion.unite(transformedRect); @@ -307,7 +308,7 @@ static inline WebTransformationMatrix contentToTargetSurfaceTransform(const Laye // FIXME: Remove usePaintTracking when paint tracking is on for paint culling. template<typename LayerType> -static inline void addOcclusionBehindLayer(Region& region, const LayerType* layer, const WebTransformationMatrix& transform, const Region& opaqueContents, const IntRect& scissorRect, const IntSize& minimumTrackingSize) +static inline void addOcclusionBehindLayer(Region& region, const LayerType* layer, const WebTransformationMatrix& transform, const Region& opaqueContents, const IntRect& scissorRect, const IntSize& minimumTrackingSize, Vector<IntRect>* occludingScreenSpaceRects) { ASSERT(layer->visibleLayerRect().contains(opaqueContents.bounds())); @@ -318,12 +319,15 @@ static inline void addOcclusionBehindLayer(Region& region, const LayerType* laye return; Vector<IntRect> contentRects = opaqueContents.rects(); - // We verify that the possible bounds of this region are not clipped above, so we can use mapRect() safely here. for (size_t i = 0; i < contentRects.size(); ++i) { - IntRect transformedRect = enclosedIntRect(transform.mapRect(FloatRect(contentRects[i]))); + // We've already checked for clipping in the mapQuad call above, these calls should not clip anything further. + IntRect transformedRect = enclosedIntRect(CCMathUtil::mapClippedRect(transform, FloatRect(contentRects[i]))); transformedRect.intersect(scissorRect); - if (transformedRect.width() >= minimumTrackingSize.width() || transformedRect.height() >= minimumTrackingSize.height()) + if (transformedRect.width() >= minimumTrackingSize.width() || transformedRect.height() >= minimumTrackingSize.height()) { + if (occludingScreenSpaceRects) + occludingScreenSpaceRects->append(transformedRect); region.unite(transformedRect); + } } } @@ -347,7 +351,7 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::markOccludedBehindLay IntRect scissorInTarget = layerScissorRectInTargetSurface(layer); if (layerTransformsToTargetKnown(layer)) - addOcclusionBehindLayer<LayerType>(m_stack.last().occlusionInTarget, layer, contentToTargetSurfaceTransform<LayerType>(layer), opaqueContents, scissorInTarget, m_minimumTrackingSize); + addOcclusionBehindLayer<LayerType>(m_stack.last().occlusionInTarget, layer, contentToTargetSurfaceTransform<LayerType>(layer), opaqueContents, scissorInTarget, m_minimumTrackingSize, 0); // We must clip the occlusion within the layer's scissorInTarget within screen space as well. If the scissor rect can't be moved to screen space and // remain rectilinear, then we don't add any occlusion in screen space. @@ -360,7 +364,7 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::markOccludedBehindLay if (clipped || !scissorInScreenQuad.isRectilinear()) return; IntRect scissorInScreenRect = intersection(m_scissorRectInScreenSpace, enclosedIntRect(scissorInScreenQuad.boundingBox())); - addOcclusionBehindLayer<LayerType>(m_stack.last().occlusionInScreen, layer, contentToScreenSpaceTransform<LayerType>(layer), opaqueContents, scissorInScreenRect, m_minimumTrackingSize); + addOcclusionBehindLayer<LayerType>(m_stack.last().occlusionInScreen, layer, contentToScreenSpaceTransform<LayerType>(layer), opaqueContents, scissorInScreenRect, m_minimumTrackingSize, m_occludingScreenSpaceRects); } } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h index 19e533536..027fab71d 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h @@ -72,6 +72,9 @@ public: static IntSize preferredMinimumTrackingSize() { return IntSize(160, 160); } + // The following is used for visualization purposes. + void setOccludingScreenSpaceRectsContainer(Vector<IntRect>* rects) { m_occludingScreenSpaceRects = rects; } + protected: struct StackObject { StackObject() : surface(0) { } @@ -111,6 +114,9 @@ private: IntRect m_scissorRectInScreenSpace; OwnPtr<CCOverdrawMetrics> m_overdrawMetrics; IntSize m_minimumTrackingSize; + + // This is used for visualizing the occlusion tracking process. + Vector<IntRect>* m_occludingScreenSpaceRects; }; typedef CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium> CCOcclusionTracker; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.cpp index 0cc2fa5ec..c5b6f3ae7 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.cpp @@ -33,6 +33,7 @@ #include "TraceEvent.h" #include "cc/CCLayerTreeHost.h" #include "cc/CCLayerTreeHostImpl.h" +#include "cc/CCMathUtil.h" #include <public/Platform.h> #include <public/WebTransformationMatrix.h> @@ -46,6 +47,8 @@ CCOverdrawMetrics::CCOverdrawMetrics(bool recordMetricsForFrame) , m_pixelsUploadedOpaque(0) , m_pixelsUploadedTranslucent(0) , m_tilesCulledForUpload(0) + , m_contentsTextureUseBytes(0) + , m_renderSurfaceTextureUseBytes(0) , m_pixelsDrawnOpaque(0) , m_pixelsDrawnTranslucent(0) , m_pixelsCulledForDrawing(0) @@ -57,13 +60,25 @@ static inline float wedgeProduct(const FloatPoint& p1, const FloatPoint& p2) return p1.x() * p2.y() - p1.y() * p2.x(); } -// Computes area of quads that are possibly non-rectangular. Can be easily extended to polygons. -static inline float quadArea(const FloatQuad& quad) +// Calculates area of an arbitrary convex polygon with up to 8 points. +static inline float polygonArea(const FloatPoint points[8], int numPoints) { - return fabs(0.5 * (wedgeProduct(quad.p1(), quad.p2()) + - wedgeProduct(quad.p2(), quad.p3()) + - wedgeProduct(quad.p3(), quad.p4()) + - wedgeProduct(quad.p4(), quad.p1()))); + if (numPoints < 3) + return 0; + + float area = 0; + for (int i = 0; i < numPoints; ++i) + area += wedgeProduct(points[i], points[(i+1)%numPoints]); + return fabs(0.5f * area); +} + +// Takes a given quad, maps it by the given transformation, and gives the area of the resulting polygon. +static inline float areaOfMappedQuad(const WebTransformationMatrix& transform, const FloatQuad& quad) +{ + FloatPoint clippedQuad[8]; + int numVerticesInClippedQuad = 0; + CCMathUtil::mapClippedQuad(transform, quad, clippedQuad, numVerticesInClippedQuad); + return polygonArea(clippedQuad, numVerticesInClippedQuad); } void CCOverdrawMetrics::didPaint(const IntRect& paintedRect) @@ -85,20 +100,36 @@ void CCOverdrawMetrics::didUpload(const WebTransformationMatrix& transformToTarg if (!m_recordMetricsForFrame) return; - float uploadArea = quadArea(transformToTarget.mapQuad(FloatQuad(uploadRect))); - float uploadOpaqueArea = quadArea(transformToTarget.mapQuad(FloatQuad(intersection(opaqueRect, uploadRect)))); + float uploadArea = areaOfMappedQuad(transformToTarget, FloatQuad(uploadRect)); + float uploadOpaqueArea = areaOfMappedQuad(transformToTarget, FloatQuad(intersection(opaqueRect, uploadRect))); m_pixelsUploadedOpaque += uploadOpaqueArea; m_pixelsUploadedTranslucent += uploadArea - uploadOpaqueArea; } +void CCOverdrawMetrics::didUseContentsTextureMemoryBytes(size_t contentsTextureUseBytes) +{ + if (!m_recordMetricsForFrame) + return; + + m_contentsTextureUseBytes += contentsTextureUseBytes; +} + +void CCOverdrawMetrics::didUseRenderSurfaceTextureMemoryBytes(size_t renderSurfaceUseBytes) +{ + if (!m_recordMetricsForFrame) + return; + + m_renderSurfaceTextureUseBytes += renderSurfaceUseBytes; +} + void CCOverdrawMetrics::didCullForDrawing(const WebTransformationMatrix& transformToTarget, const IntRect& beforeCullRect, const IntRect& afterCullRect) { if (!m_recordMetricsForFrame) return; - float beforeCullArea = quadArea(transformToTarget.mapQuad(FloatQuad(beforeCullRect))); - float afterCullArea = quadArea(transformToTarget.mapQuad(FloatQuad(afterCullRect))); + float beforeCullArea = areaOfMappedQuad(transformToTarget, FloatQuad(beforeCullRect)); + float afterCullArea = areaOfMappedQuad(transformToTarget, FloatQuad(afterCullRect)); m_pixelsCulledForDrawing += beforeCullArea - afterCullArea; } @@ -108,8 +139,8 @@ void CCOverdrawMetrics::didDraw(const WebTransformationMatrix& transformToTarget if (!m_recordMetricsForFrame) return; - float afterCullArea = quadArea(transformToTarget.mapQuad(FloatQuad(afterCullRect))); - float afterCullOpaqueArea = quadArea(transformToTarget.mapQuad(FloatQuad(intersection(opaqueRect, afterCullRect)))); + float afterCullArea = areaOfMappedQuad(transformToTarget, FloatQuad(afterCullRect)); + float afterCullOpaqueArea = areaOfMappedQuad(transformToTarget, FloatQuad(intersection(opaqueRect, afterCullRect))); m_pixelsDrawnOpaque += afterCullOpaqueArea; m_pixelsDrawnTranslucent += afterCullArea - afterCullOpaqueArea; @@ -134,6 +165,8 @@ void CCOverdrawMetrics::recordMetricsInternal(MetricsType metricsType, const Lay float normalization = 1000.f / (layerTreeHost->deviceViewportSize().width() * layerTreeHost->deviceViewportSize().height()); // This gives approximately 100x the percentage of tiles to fill the viewport once, if all tiles were 256x256. float tileNormalization = 10000.f / (layerTreeHost->deviceViewportSize().width() / 256.f * layerTreeHost->deviceViewportSize().height() / 256.f); + // This gives approximately 10x the percentage of bytes to fill the viewport once, assuming 4 bytes per pixel. + float byteNormalization = normalization / 4; switch (metricsType) { case DrawingToScreen: @@ -151,6 +184,10 @@ void CCOverdrawMetrics::recordMetricsInternal(MetricsType metricsType, const Lay WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountOpaque_Upload", static_cast<int>(normalization * m_pixelsUploadedOpaque), 100, 1000000, 50); WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountTranslucent_Upload", static_cast<int>(normalization * m_pixelsUploadedTranslucent), 100, 1000000, 50); WebKit::Platform::current()->histogramCustomCounts("Renderer4.tileCountCulled_Upload", static_cast<int>(tileNormalization * m_tilesCulledForUpload), 100, 10000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.renderSurfaceTextureBytes_ViewportScaled", static_cast<int>(byteNormalization * m_renderSurfaceTextureUseBytes), 10, 1000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.renderSurfaceTextureBytes_Unscaled", static_cast<int>(m_renderSurfaceTextureUseBytes / 1000), 1000, 100000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.contentsTextureBytes_ViewportScaled", static_cast<int>(byteNormalization * m_contentsTextureUseBytes), 10, 1000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.contentsTextureBytes_Unscaled", static_cast<int>(m_contentsTextureUseBytes / 1000), 1000, 100000000, 50); { TRACE_COUNTER_ID1("cc", "UploadTilesCulled", layerTreeHost, m_tilesCulledForUpload); @@ -160,6 +197,10 @@ void CCOverdrawMetrics::recordMetricsInternal(MetricsType metricsType, const Lay // This must be in a different scope than the TRACE_EVENT2 above. TRACE_EVENT1("cc", "CCOverdrawPaintMetrics", "PixelsPainted", m_pixelsPainted); } + { + // This must be in a different scope than the TRACE_EVENTs above. + TRACE_EVENT2("cc", "CCOverdrawPaintMetrics", "ContentsTextureBytes", m_contentsTextureUseBytes, "RenderSurfaceTextureBytes", m_renderSurfaceTextureUseBytes); + } break; } } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.h b/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.h index 715f5e151..f0dab0e93 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCOverdrawMetrics.h @@ -49,6 +49,10 @@ public: void didCullTileForUpload(); // Records pixels that were uploaded to texture memory. void didUpload(const WebKit::WebTransformationMatrix& transformToTarget, const IntRect& uploadRect, const IntRect& opaqueRect); + // Record contents texture(s) behind present using the given number of bytes. + void didUseContentsTextureMemoryBytes(size_t contentsTextureUseBytes); + // Record RenderSurface texture(s) being present using the given number of bytes. + void didUseRenderSurfaceTextureMemoryBytes(size_t renderSurfaceUseBytes); // These methods are used for saving metrics during draw. @@ -93,6 +97,10 @@ private: float m_pixelsUploadedTranslucent; // Count of tiles that were invalidated but not uploaded. int m_tilesCulledForUpload; + // Count the number of bytes in contents textures. + unsigned long long m_contentsTextureUseBytes; + // Count the number of bytes in RenderSurface textures. + unsigned long long m_renderSurfaceTextureUseBytes; // These values are used for saving metrics during draw. diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTexture.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTexture.cpp new file mode 100644 index 000000000..d8cc17485 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTexture.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2012, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "CCPrioritizedTexture.h" + +#include "CCPrioritizedTextureManager.h" +#include "CCPriorityCalculator.h" +#include "LayerRendererChromium.h" +#include <algorithm> + +using namespace std; + +namespace WebCore { + +CCPrioritizedTexture::CCPrioritizedTexture(CCPrioritizedTextureManager* manager, IntSize size, GC3Denum format) + : m_size(size) + , m_format(format) + , m_memorySizeBytes(0) + , m_priority(CCPriorityCalculator::lowestPriority()) + , m_isAbovePriorityCutoff(false) + , m_currentBacking(0) + , m_manager(0) +{ + // m_manager is set in registerTexture() so validity can be checked. + ASSERT(format || size.isEmpty()); + if (format) + m_memorySizeBytes = TextureManager::memoryUseBytes(size, format); + if (manager) + manager->registerTexture(this); +} + +CCPrioritizedTexture::~CCPrioritizedTexture() +{ + if (m_manager) + m_manager->unregisterTexture(this); +} + +void CCPrioritizedTexture::setTextureManager(CCPrioritizedTextureManager* manager) +{ + if (m_manager == manager) + return; + if (m_manager) + m_manager->unregisterTexture(this); + if (manager) + manager->registerTexture(this); +} + +void CCPrioritizedTexture::setDimensions(IntSize size, GC3Denum format) +{ + if (m_format != format || m_size != size) { + m_isAbovePriorityCutoff = false; + m_format = format; + m_size = size; + m_memorySizeBytes = TextureManager::memoryUseBytes(size, format); + ASSERT(m_manager || !m_currentBacking); + if (m_manager) + m_manager->returnBackingTexture(this); + } +} + +bool CCPrioritizedTexture::requestLate() +{ + if (!m_manager) + return false; + return m_manager->requestLate(this); +} + +void CCPrioritizedTexture::acquireBackingTexture(TextureAllocator* allocator) +{ + ASSERT(m_isAbovePriorityCutoff); + if (m_isAbovePriorityCutoff) + m_manager->acquireBackingTextureIfNeeded(this, allocator); +} + +unsigned CCPrioritizedTexture::textureId() +{ + if (m_currentBacking) + return m_currentBacking->textureId(); + return 0; +} + +void CCPrioritizedTexture::bindTexture(CCGraphicsContext* context, TextureAllocator* allocator) +{ + ASSERT(m_isAbovePriorityCutoff); + if (m_isAbovePriorityCutoff) + acquireBackingTexture(allocator); + ASSERT(m_currentBacking); + WebKit::WebGraphicsContext3D* context3d = context->context3D(); + if (!context3d) { + // FIXME: Implement this path for software compositing. + return; + } + context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId()); +} + +void CCPrioritizedTexture::framebufferTexture2D(CCGraphicsContext* context, TextureAllocator* allocator) +{ + ASSERT(m_isAbovePriorityCutoff); + if (m_isAbovePriorityCutoff) + acquireBackingTexture(allocator); + ASSERT(m_currentBacking); + WebKit::WebGraphicsContext3D* context3d = context->context3D(); + if (!context3d) { + // FIXME: Implement this path for software compositing. + return; + } + context3d->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, textureId(), 0); +} + +void CCPrioritizedTexture::setCurrentBacking(CCPrioritizedTexture::Backing* backing) +{ + if (m_currentBacking == backing) + return; + m_currentBacking = backing; +} + +} // namespace WebCore + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTexture.h b/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTexture.h new file mode 100644 index 000000000..9ea2fb1e4 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTexture.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2012, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCPrioritizedTexture_h +#define CCPrioritizedTexture_h + +#include "CCPriorityCalculator.h" +#include "GraphicsContext3D.h" +#include "IntRect.h" +#include "IntSize.h" +#include "TextureManager.h" + +namespace WebCore { + +class CCPrioritizedTextureManager; +class CCPriorityCalculator; +class CCGraphicsContext; + +class CCPrioritizedTexture { + WTF_MAKE_NONCOPYABLE(CCPrioritizedTexture); +public: + static PassOwnPtr<CCPrioritizedTexture> create(CCPrioritizedTextureManager* manager, IntSize size, GC3Denum format) + { + return adoptPtr(new CCPrioritizedTexture(manager, size, format)); + } + static PassOwnPtr<CCPrioritizedTexture> create(CCPrioritizedTextureManager* manager) + { + return adoptPtr(new CCPrioritizedTexture(manager, IntSize(), 0)); + } + ~CCPrioritizedTexture(); + + // Texture properties. Changing these causes the backing texture to be lost. + // Setting these to the same value is a no-op. + void setTextureManager(CCPrioritizedTextureManager*); + CCPrioritizedTextureManager* textureManager() { return m_manager; } + void setDimensions(IntSize, GC3Denum format); + GC3Denum format() const { return m_format; } + IntSize size() const { return m_size; } + size_t memorySizeBytes() const { return m_memorySizeBytes; } + + // Set priority for the requested texture. + void setRequestPriority(int priority) { m_priority = priority; } + int requestPriority() const { return m_priority; } + + // After CCPrioritizedTexture::prioritizeTextures() is called, this returns + // if the the request succeeded and this texture can be acquired for use. + bool canAcquireBackingTexture() const { return m_isAbovePriorityCutoff; } + + // This returns whether we still have a backing texture. This can continue + // to be true even after canAquireBackingTexture() becomes false. In this + // case the texture can be used but shouldn't be updated since it will get + // taken away "soon". + bool haveBackingTexture() const { return !!currentBacking(); } + + // If canAquireBackingTexture() is true acquireBackingTexture() will acquire + // a backing texture for use. Call this whenever the texture is actually needed. + void acquireBackingTexture(TextureAllocator*); + + // FIXME: Request late is really a hack for when we are totally out of memory + // (all textures are visible) but we can still squeeze into the limit + // by not painting occluded textures. In this case the manager + // refuses all visible textures and requestLate() will enable + // canAquireBackingTexture() on a call-order basis. We might want to + // just remove this in the future (carefully) and just make sure we don't + // regress OOMs situations. + bool requestLate(); + + // These functions will aquire the texture if possible. If neither haveBackingTexture() + // nor canAquireBackingTexture() is true, an ID of zero will be used/returned. + void bindTexture(CCGraphicsContext*, TextureAllocator*); + void framebufferTexture2D(CCGraphicsContext*, TextureAllocator*); + unsigned textureId(); + +private: + friend class CCPrioritizedTextureManager; + + class Backing { + WTF_MAKE_NONCOPYABLE(Backing); + public: + IntSize size() const { return m_size; } + GC3Denum format() const { return m_format; } + size_t memorySizeBytes() const { return m_memorySizeBytes; } + unsigned textureId() const { return m_textureId; } + CCPrioritizedTexture* currentTexture() const { return m_currentTexture; } + void setCurrentTexture(CCPrioritizedTexture* current) { m_currentTexture = current; } + + private: + friend class CCPrioritizedTextureManager; + + Backing(IntSize size, GC3Denum format, unsigned textureId) + : m_size(size) + , m_format(format) + , m_memorySizeBytes(TextureManager::memoryUseBytes(size, format)) + , m_textureId(textureId) + , m_priority(CCPriorityCalculator::lowestPriority()) + , m_currentTexture(0) { } + ~Backing() { ASSERT(!m_currentTexture); } + + IntSize m_size; + GC3Denum m_format; + size_t m_memorySizeBytes; + unsigned m_textureId; + int m_priority; + CCPrioritizedTexture* m_currentTexture; + }; + + CCPrioritizedTexture(CCPrioritizedTextureManager*, IntSize, GC3Denum format); + + bool isAbovePriorityCutoff() { return m_isAbovePriorityCutoff; } + void setAbovePriorityCutoff(bool isAbovePriorityCutoff) { m_isAbovePriorityCutoff = isAbovePriorityCutoff; } + void setManagerInternal(CCPrioritizedTextureManager* manager) { m_manager = manager; } + + Backing* currentBacking() const { return m_currentBacking; } + void setCurrentBacking(Backing*); + + IntSize m_size; + GC3Denum m_format; + size_t m_memorySizeBytes; + + size_t m_priority; + bool m_isAbovePriorityCutoff; + + Backing* m_currentBacking; + CCPrioritizedTextureManager* m_manager; +}; + +} // WebCore + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTextureManager.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTextureManager.cpp new file mode 100644 index 000000000..5af53df04 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTextureManager.cpp @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2012, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "CCPrioritizedTextureManager.h" + +#include "CCPrioritizedTexture.h" +#include "CCPriorityCalculator.h" +#include "LayerRendererChromium.h" +#include "TraceEvent.h" +#include <algorithm> + +using namespace std; + +namespace WebCore { + +CCPrioritizedTextureManager::CCPrioritizedTextureManager(size_t maxMemoryLimitBytes, int) + : m_maxMemoryLimitBytes(maxMemoryLimitBytes) + , m_memoryUseBytes(0) + , m_memoryAboveCutoffBytes(0) + , m_memoryAvailableBytes(0) +{ +} + +CCPrioritizedTextureManager::~CCPrioritizedTextureManager() +{ + while (m_textures.size() > 0) + unregisterTexture(*m_textures.begin()); + + // Each remaining backing is a leaked opengl texture. We don't have the allocator + // to delete the textures at this time so clearMemory() needs to be called before this. + while (m_backings.size() > 0) + destroyBacking(*m_backings.begin(), 0); +} + +void CCPrioritizedTextureManager::prioritizeTextures(size_t renderSurfacesMemoryBytes) +{ + TRACE_EVENT0("cc", "CCPrioritizedTextureManager::prioritizeTextures"); + +#if !ASSERT_DISABLED + assertInvariants(); +#endif + + // Sorting textures in this function could be replaced by a slightly + // modified O(n) quick-select to partition textures rather than + // sort them (if performance of the sort becomes an issue). + + TextureVector& sortedTextures = m_tempTextureVector; + BackingVector& sortedBackings = m_tempBackingVector; + sortedTextures.clear(); + sortedBackings.clear(); + + // Copy all textures into a vector and sort them. + for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) + sortedTextures.append(*it); + std::sort(sortedTextures.begin(), sortedTextures.end(), compareTextures); + + m_memoryAvailableBytes = m_maxMemoryLimitBytes; + m_priorityCutoff = CCPriorityCalculator::lowestPriority(); + bool reservedRenderSurfaces = false; + size_t memoryBytes = 0; + for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextures.end(); ++it) { + if ((*it)->requestPriority() == CCPriorityCalculator::lowestPriority()) + break; + + // FIXME: We can make placeholder objects similar to textures to represent the render surface memory request. + if (!reservedRenderSurfaces && CCPriorityCalculator::priorityIsLower((*it)->requestPriority(), CCPriorityCalculator::renderSurfacePriority())) { + size_t newMemoryBytes = memoryBytes + renderSurfacesMemoryBytes; + if (newMemoryBytes > m_memoryAvailableBytes) { + m_priorityCutoff = (*it)->requestPriority(); + m_memoryAvailableBytes = memoryBytes; + break; + } + m_memoryAvailableBytes -= renderSurfacesMemoryBytes; + reservedRenderSurfaces = true; + } + + size_t newMemoryBytes = memoryBytes + (*it)->memorySizeBytes(); + if (newMemoryBytes > m_memoryAvailableBytes) { + m_priorityCutoff = (*it)->requestPriority(); + break; + } + + memoryBytes = newMemoryBytes; + } + + // Only allow textures if they are higher than the cutoff. All textures + // of the same priority are accepted or rejected together, rather than + // being partially allowed randomly. + m_memoryAboveCutoffBytes = 0; + for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextures.end(); ++it) { + bool isAbovePriorityCutoff = CCPriorityCalculator::priorityIsHigher((*it)->requestPriority(), m_priorityCutoff); + (*it)->setAbovePriorityCutoff(isAbovePriorityCutoff); + if (isAbovePriorityCutoff) + m_memoryAboveCutoffBytes += (*it)->memorySizeBytes(); + } + ASSERT(m_memoryAboveCutoffBytes <= m_memoryAvailableBytes); + + // Put backings in eviction/recycling order. + for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) + sortedBackings.append(*it); + std::sort(sortedBackings.begin(), sortedBackings.end(), compareBackings); + + for (BackingVector::iterator it = sortedBackings.begin(); it != sortedBackings.end(); ++it) { + m_backings.remove(*it); + m_backings.add(*it); + } + + sortedTextures.clear(); + sortedBackings.clear(); + +#if !ASSERT_DISABLED + assertInvariants(); + ASSERT(memoryAboveCutoffBytes() <= maxMemoryLimitBytes()); +#endif +} + +void CCPrioritizedTextureManager::clearPriorities() +{ + for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) { + // FIXME: We should remove this and just set all priorities to + // CCPriorityCalculator::lowestPriority() once we have priorities + // for all textures (we can't currently calculate distances for + // off-screen textures). + (*it)->setRequestPriority(CCPriorityCalculator::lingeringPriority((*it)->requestPriority())); + } +} + +bool CCPrioritizedTextureManager::requestLate(CCPrioritizedTexture* texture) +{ + // This is already above cutoff, so don't double count it's memory below. + if (texture->isAbovePriorityCutoff()) + return true; + + if (CCPriorityCalculator::priorityIsLower(texture->requestPriority(), m_priorityCutoff)) + return false; + + size_t newMemoryBytes = m_memoryAboveCutoffBytes + texture->memorySizeBytes(); + if (newMemoryBytes > m_memoryAvailableBytes) + return false; + + m_memoryAboveCutoffBytes = newMemoryBytes; + texture->setAbovePriorityCutoff(true); + if (texture->currentBacking()) { + m_backings.remove(texture->currentBacking()); + m_backings.add(texture->currentBacking()); + } + return true; +} + +void CCPrioritizedTextureManager::acquireBackingTextureIfNeeded(CCPrioritizedTexture* texture, TextureAllocator* allocator) +{ + ASSERT(texture->isAbovePriorityCutoff()); + if (texture->currentBacking() || !texture->isAbovePriorityCutoff()) + return; + + // Find a backing below, by either recycling or allocating. + CCPrioritizedTexture::Backing* backing = 0; + + // First try to recycle + for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { + if ((*it)->currentTexture() && (*it)->currentTexture()->isAbovePriorityCutoff()) + break; + if ((*it)->size() == texture->size() && (*it)->format() == texture->format()) { + backing = (*it); + break; + } + } + + // Otherwise reduce memory and just allocate a new backing texures. + if (!backing) { + reduceMemory(m_memoryAvailableBytes - texture->memorySizeBytes(), allocator); + backing = createBacking(texture->size(), texture->format(), allocator); + } + + // Move the used backing texture to the end of the eviction list. + if (backing->currentTexture()) + unlink(backing->currentTexture(), backing); + link(texture, backing); + m_backings.remove(backing); + m_backings.add(backing); +} + +void CCPrioritizedTextureManager::reduceMemory(size_t limitBytes, TextureAllocator* allocator) +{ + if (memoryUseBytes() <= limitBytes) + return; + // Destroy backings until we are below the limit, + // or until all backings remaining are above the cutoff. + while (memoryUseBytes() > limitBytes && m_backings.size() > 0) { + BackingSet::iterator it = m_backings.begin(); + if ((*it)->currentTexture() && (*it)->currentTexture()->isAbovePriorityCutoff()) + break; + destroyBacking((*it), allocator); + } +} + +void CCPrioritizedTextureManager::reduceMemory(TextureAllocator* allocator) +{ + reduceMemory(m_memoryAvailableBytes, allocator); + ASSERT(memoryUseBytes() <= maxMemoryLimitBytes()); + + // We currently collect backings from deleted textures for later recycling. + // However, if we do that forever we will always use the max limit even if + // we really need very little memory. This should probably be solved by reducing the + // limit externally, but until then this just does some "clean up" of unused + // backing textures (any more than 10%). + size_t wastedMemory = 0; + for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { + if ((*it)->currentTexture()) + break; + wastedMemory += (*it)->memorySizeBytes(); + } + size_t tenPercentOfMemory = m_memoryAvailableBytes / 10; + if (wastedMemory <= tenPercentOfMemory) + return; + reduceMemory(memoryUseBytes() - (wastedMemory - tenPercentOfMemory), allocator); +} + +void CCPrioritizedTextureManager::clearAllMemory(TextureAllocator* allocator) +{ + // Unlink and destroy all backing textures. + while (m_backings.size() > 0) { + BackingSet::iterator it = m_backings.begin(); + if ((*it)->currentTexture()) + unlink((*it)->currentTexture(), (*it)); + destroyBacking((*it), allocator); + } +} + +void CCPrioritizedTextureManager::allBackingTexturesWereDeleted() +{ + // Same as clearAllMemory, except all our textures were already + // deleted externally, so we don't delete them. Passing no + // allocator results in leaking the (now invalid) texture ids. + clearAllMemory(0); +} + +void CCPrioritizedTextureManager::unlink(CCPrioritizedTexture* texture, CCPrioritizedTexture::Backing* backing) +{ + ASSERT(texture && backing); + ASSERT(texture->currentBacking() == backing); + ASSERT(backing->currentTexture() == texture); + + texture->setCurrentBacking(0); + backing->setCurrentTexture(0); +} + +void CCPrioritizedTextureManager::link(CCPrioritizedTexture* texture, CCPrioritizedTexture::Backing* backing) +{ + ASSERT(texture && backing); + ASSERT(!texture->currentBacking()); + ASSERT(!backing->currentTexture()); + + texture->setCurrentBacking(backing); + backing->setCurrentTexture(texture); +} + + +void CCPrioritizedTextureManager::registerTexture(CCPrioritizedTexture* texture) +{ + ASSERT(texture); + ASSERT(!texture->textureManager()); + ASSERT(!texture->currentBacking()); + ASSERT(m_textures.find(texture) == m_textures.end()); + + texture->setManagerInternal(this); + m_textures.add(texture); + +} + +void CCPrioritizedTextureManager::unregisterTexture(CCPrioritizedTexture* texture) +{ + ASSERT(texture); + ASSERT(m_textures.find(texture) != m_textures.end()); + + returnBackingTexture(texture); + texture->setManagerInternal(0); + m_textures.remove(texture); + texture->setAbovePriorityCutoff(false); +} + + +void CCPrioritizedTextureManager::returnBackingTexture(CCPrioritizedTexture* texture) +{ + if (texture->currentBacking()) { + // Move the backing texture to the front for eviction/recycling and unlink it. + m_backings.remove(texture->currentBacking()); + m_backings.insertBefore(m_backings.begin(), texture->currentBacking()); + unlink(texture, texture->currentBacking()); + } +} + +CCPrioritizedTexture::Backing* CCPrioritizedTextureManager::createBacking(IntSize size, GC3Denum format, TextureAllocator* allocator) +{ + ASSERT(allocator); + + unsigned textureId = allocator->createTexture(size, format); + CCPrioritizedTexture::Backing* backing = new CCPrioritizedTexture::Backing(size, format, textureId); + m_memoryUseBytes += backing->memorySizeBytes(); + // Put backing texture at the front for eviction, since it isn't in use yet. + m_backings.insertBefore(m_backings.begin(), backing); + return backing; +} + +void CCPrioritizedTextureManager::destroyBacking(CCPrioritizedTexture::Backing* backing, TextureAllocator* allocator) +{ + ASSERT(backing); + ASSERT(!backing->currentTexture() || !backing->currentTexture()->isAbovePriorityCutoff()); + ASSERT(m_backings.find(backing) != m_backings.end()); + + if (allocator) + allocator->deleteTexture(backing->textureId(), backing->size(), backing->format()); + if (backing->currentTexture()) + unlink(backing->currentTexture(), backing); + m_memoryUseBytes -= backing->memorySizeBytes(); + m_backings.remove(backing); + + delete backing; +} + + +#if !ASSERT_DISABLED +void CCPrioritizedTextureManager::assertInvariants() +{ + // If we hit any of these asserts, there is a bug in this class. To see + // where the bug is, call this function at the beginning and end of + // every public function. + + // Backings/textures must be doubly-linked and only to other backings/textures in this manager. + for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { + if ((*it)->currentTexture()) { + ASSERT(m_textures.find((*it)->currentTexture()) != m_textures.end()); + ASSERT((*it)->currentTexture()->currentBacking() == (*it)); + } + } + for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) { + if ((*it)->currentBacking()) { + ASSERT(m_backings.find((*it)->currentBacking()) != m_backings.end()); + ASSERT((*it)->currentBacking()->currentTexture() == (*it)); + } + } + + // At all times, backings that can be evicted must always come before + // backings that can't be evicted in the backing texture list (otherwise + // reduceMemory will not find all textures available for eviction/recycling). + bool reachedProtected = false; + for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { + if ((*it)->currentTexture() && (*it)->currentTexture()->isAbovePriorityCutoff()) + reachedProtected = true; + if (reachedProtected) + ASSERT((*it)->currentTexture() && (*it)->currentTexture()->isAbovePriorityCutoff()); + } +} +#endif + + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTextureManager.h b/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTextureManager.h new file mode 100644 index 000000000..3c70b2b2a --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPrioritizedTextureManager.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2012, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCPrioritizedTextureManager_h +#define CCPrioritizedTextureManager_h + +#include "CCPrioritizedTexture.h" +#include "CCPriorityCalculator.h" +#include "GraphicsContext3D.h" +#include "IntRect.h" +#include "IntSize.h" +#include "TextureManager.h" + +namespace WebCore { + +class CCPrioritizedTexture; +class CCPriorityCalculator; + +class CCPrioritizedTextureManager { + WTF_MAKE_NONCOPYABLE(CCPrioritizedTextureManager); +public: + static PassOwnPtr<CCPrioritizedTextureManager> create(size_t maxMemoryLimitBytes, int maxTextureSize) + { + return adoptPtr(new CCPrioritizedTextureManager(maxMemoryLimitBytes, maxTextureSize)); + } + PassOwnPtr<CCPrioritizedTexture> createTexture(IntSize size, GC3Denum format) + { + return adoptPtr(new CCPrioritizedTexture(this, size, format)); + } + ~CCPrioritizedTextureManager(); + + // memoryUseBytes() describes the number of bytes used by existing allocated textures. + // memoryAboveCutoffBytes() describes the number of bytes that would be used if all + // textures that are above the cutoff were allocated. + // memoryUseBytes() <= memoryAboveCutoffBytes() should always be true. + size_t memoryUseBytes() const { return m_memoryUseBytes; } + size_t memoryAboveCutoffBytes() const { return m_memoryAboveCutoffBytes; } + size_t memoryForRenderSurfacesBytes() const { return m_maxMemoryLimitBytes - m_memoryAvailableBytes; } + + void setMaxMemoryLimitBytes(size_t bytes) { m_maxMemoryLimitBytes = bytes; } + size_t maxMemoryLimitBytes() const { return m_maxMemoryLimitBytes; } + + void prioritizeTextures(size_t renderSurfacesMemoryBytes); + void clearPriorities(); + + bool requestLate(CCPrioritizedTexture*); + + void reduceMemory(TextureAllocator*); + void clearAllMemory(TextureAllocator*); + void allBackingTexturesWereDeleted(); + + void acquireBackingTextureIfNeeded(CCPrioritizedTexture*, TextureAllocator*); + + void registerTexture(CCPrioritizedTexture*); + void unregisterTexture(CCPrioritizedTexture*); + void returnBackingTexture(CCPrioritizedTexture*); + +#if !ASSERT_DISABLED + void assertInvariants(); +#endif + +private: + // Compare textures. Highest priority first. + static inline bool compareTextures(CCPrioritizedTexture* a, CCPrioritizedTexture* b) + { + if (a->requestPriority() == b->requestPriority()) + return a < b; + return CCPriorityCalculator::priorityIsHigher(a->requestPriority(), b->requestPriority()); + } + // Compare backings. Lowest priority first. + static inline bool compareBackings(CCPrioritizedTexture::Backing* a, CCPrioritizedTexture::Backing* b) + { + int priorityA = a->currentTexture() ? a->currentTexture()->requestPriority() : CCPriorityCalculator::lowestPriority(); + int priorityB = b->currentTexture() ? b->currentTexture()->requestPriority() : CCPriorityCalculator::lowestPriority(); + if (priorityA == priorityB) + return a < b; + return CCPriorityCalculator::priorityIsLower(priorityA, priorityB); + } + + CCPrioritizedTextureManager(size_t maxMemoryLimitBytes, int maxTextureSize); + + void reduceMemory(size_t limit, TextureAllocator*); + + void link(CCPrioritizedTexture*, CCPrioritizedTexture::Backing*); + void unlink(CCPrioritizedTexture*, CCPrioritizedTexture::Backing*); + + CCPrioritizedTexture::Backing* createBacking(IntSize, GC3Denum format, TextureAllocator*); + void destroyBacking(CCPrioritizedTexture::Backing*, TextureAllocator*); + + size_t m_maxMemoryLimitBytes; + unsigned m_priorityCutoff; + size_t m_memoryUseBytes; + size_t m_memoryAboveCutoffBytes; + size_t m_memoryAvailableBytes; + + typedef HashSet<CCPrioritizedTexture*> TextureSet; + typedef ListHashSet<CCPrioritizedTexture::Backing*> BackingSet; + typedef Vector<CCPrioritizedTexture*> TextureVector; + typedef Vector<CCPrioritizedTexture::Backing*> BackingVector; + + TextureSet m_textures; + BackingSet m_backings; + + TextureVector m_tempTextureVector; + BackingVector m_tempBackingVector; +}; + +} // WebCore + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPriorityCalculator.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPriorityCalculator.cpp new file mode 100644 index 000000000..90084043d --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPriorityCalculator.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2012, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "CCPriorityCalculator.h" + +#include "LayerRendererChromium.h" + +using namespace std; + +namespace WebCore { + +// static +int CCPriorityCalculator::uiPriority(bool drawsToRootSurface) +{ + return drawsToRootSurface ? -1 : 2; +} + +// static +int CCPriorityCalculator::visiblePriority(bool drawsToRootSurface) +{ + return drawsToRootSurface ? 0 : 3; +} + +// static +int CCPriorityCalculator::renderSurfacePriority() +{ + return 1; +} + +// static +int CCPriorityCalculator::lingeringPriority(int previousPriority) +{ + // FIXME: We should remove this once we have priorities for all + // textures (we can't currently calculate distances for + // off-screen textures). + int lingeringPriority = 1000000; + return min(numeric_limits<int>::max() - 1, + max(lingeringPriority, previousPriority)) + 1; +} + +namespace { +unsigned manhattanDistance(const IntRect& a, const IntRect& b) +{ + IntRect c = unionRect(a, b); + int x = max(0, c.width() - a.width() - b.width() + 1); + int y = max(0, c.height() - a.height() - b.height() + 1); + return (x + y); +} +} + +int CCPriorityCalculator::priorityFromDistance(const IntRect& visibleRect, const IntRect& textureRect, bool drawsToRootSurface) const +{ + unsigned distance = manhattanDistance(visibleRect, textureRect); + if (!distance) + return visiblePriority(drawsToRootSurface); + return visiblePriority(false) + distance; +} + +int CCPriorityCalculator::priorityFromDistance(unsigned pixels, bool drawsToRootSurface) const +{ + if (!pixels) + return visiblePriority(drawsToRootSurface); + return visiblePriority(false) + pixels; +} + +int CCPriorityCalculator::priorityFromVisibility(bool visible, bool drawsToRootSurface) const +{ + return visible ? visiblePriority(drawsToRootSurface) : lowestPriority(); +} + +} // WebCore + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPriorityCalculator.h b/Source/WebCore/platform/graphics/chromium/cc/CCPriorityCalculator.h new file mode 100644 index 000000000..68a225be0 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPriorityCalculator.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCPriorityCalculator_h +#define CCPriorityCalculator_h + +#include "GraphicsContext3D.h" +#include "IntRect.h" +#include "IntSize.h" +#include "TextureManager.h" + +namespace WebCore { + +class CCPriorityCalculator { +public: + static int uiPriority(bool drawsToRootSurface); + static int visiblePriority(bool drawsToRootSurface); + static int renderSurfacePriority(); + static int lingeringPriority(int previousPriority); + int priorityFromDistance(const IntRect& visibleRect, const IntRect& textureRect, bool drawsToRootSurface) const; + int priorityFromDistance(unsigned pixels, bool drawsToRootSurface) const; + int priorityFromVisibility(bool visible, bool drawsToRootSurface) const; + + static inline int highestPriority() { return std::numeric_limits<int>::min(); } + static inline int lowestPriority() { return std::numeric_limits<int>::max(); } + static inline bool priorityIsLower(int a, int b) { return a > b; } + static inline bool priorityIsHigher(int a, int b) { return a < b; } +}; + +} + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp index 63b8fb8bf..da8980295 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp @@ -30,6 +30,7 @@ #include "cc/CCQuadCuller.h" #include "Region.h" +#include "SkColor.h" #include "cc/CCDebugBorderDrawQuad.h" #include "cc/CCLayerImpl.h" #include "cc/CCOverdrawMetrics.h" @@ -65,7 +66,7 @@ static inline bool appendQuadInternal(PassOwnPtr<CCDrawQuad> passDrawQuad, const if (keepQuad) { if (createDebugBorderQuads && !drawQuad->isDebugQuad() && drawQuad->quadVisibleRect() != drawQuad->quadRect()) { - Color borderColor = Color(debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue, debugTileBorderAlpha); + SkColor borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue); quadList.append(CCDebugBorderDrawQuad::create(drawQuad->sharedQuadState(), drawQuad->quadVisibleRect(), borderColor, debugTileBorderWidth)); } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp index a55feb85c..90a6ee60a 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp @@ -27,8 +27,8 @@ #include "cc/CCRenderPass.h" -#include "Color.h" #include "cc/CCLayerImpl.h" +#include "cc/CCMathUtil.h" #include "cc/CCQuadCuller.h" #include "cc/CCSharedQuadState.h" #include "cc/CCSolidColorDrawQuad.h" @@ -37,17 +37,19 @@ using WebKit::WebTransformationMatrix; namespace WebCore { -PassOwnPtr<CCRenderPass> CCRenderPass::create(CCRenderSurface* targetSurface) +PassOwnPtr<CCRenderPass> CCRenderPass::create(CCRenderSurface* targetSurface, int id) { - return adoptPtr(new CCRenderPass(targetSurface)); + return adoptPtr(new CCRenderPass(targetSurface, id)); } -CCRenderPass::CCRenderPass(CCRenderSurface* targetSurface) - : m_targetSurface(targetSurface) +CCRenderPass::CCRenderPass(CCRenderSurface* targetSurface, int id) + : m_id(id) + , m_targetSurface(targetSurface) , m_framebufferOutputRect(targetSurface->contentRect()) , m_hasTransparentBackground(true) { - ASSERT(m_targetSurface); + ASSERT(targetSurface); + ASSERT(id > 0); } void CCRenderPass::appendQuadsForLayer(CCLayerImpl* layer, CCOcclusionTrackerImpl* occlusionTracker, bool& hadMissingTiles) @@ -83,9 +85,9 @@ void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer, const CC m_sharedQuadStateList.append(replicaSharedQuadState.release()); } -void CCRenderPass::appendQuadsToFillScreen(CCLayerImpl* rootLayer, const Color& screenBackgroundColor, const CCOcclusionTrackerImpl& occlusionTracker) +void CCRenderPass::appendQuadsToFillScreen(CCLayerImpl* rootLayer, SkColor screenBackgroundColor, const CCOcclusionTrackerImpl& occlusionTracker) { - if (!rootLayer || !screenBackgroundColor.isValid()) + if (!rootLayer || !screenBackgroundColor) return; Region fillRegion = occlusionTracker.computeVisibleRegionInScreen(); @@ -96,7 +98,8 @@ void CCRenderPass::appendQuadsToFillScreen(CCLayerImpl* rootLayer, const Color& WebTransformationMatrix transformToLayerSpace = rootLayer->screenSpaceTransform().inverse(); Vector<IntRect> fillRects = fillRegion.rects(); for (size_t i = 0; i < fillRects.size(); ++i) { - IntRect layerRect = transformToLayerSpace.mapRect(fillRects[i]); + // The root layer transform is composed of translations and scales only, no perspective, so mapping is sufficient. + IntRect layerRect = CCMathUtil::mapClippedRect(transformToLayerSpace, fillRects[i]); m_quadList.append(CCSolidColorDrawQuad::create(sharedQuadState.get(), layerRect, screenBackgroundColor)); } m_sharedQuadStateList.append(sharedQuadState.release()); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h index 6ce35fe8a..47ae2f747 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h @@ -26,6 +26,7 @@ #ifndef CCRenderPass_h #define CCRenderPass_h +#include "SkColor.h" #include "cc/CCOcclusionTracker.h" #include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> @@ -36,7 +37,6 @@ class CCDrawQuad; class CCLayerImpl; class CCRenderSurface; class CCSharedQuadState; -class Color; // A list of CCDrawQuad objects, sorted internally in front-to-back order. class CCQuadList : public Vector<OwnPtr<CCDrawQuad> > { @@ -53,14 +53,17 @@ public: class CCRenderPass { WTF_MAKE_NONCOPYABLE(CCRenderPass); public: - static PassOwnPtr<CCRenderPass> create(CCRenderSurface*); + static PassOwnPtr<CCRenderPass> create(CCRenderSurface*, int id); void appendQuadsForLayer(CCLayerImpl*, CCOcclusionTrackerImpl*, bool& hadMissingTiles); void appendQuadsForRenderSurfaceLayer(CCLayerImpl*, const CCRenderPass* contributingRenderPass, CCOcclusionTrackerImpl*); - void appendQuadsToFillScreen(CCLayerImpl* rootLayer, const Color& screenBackgroundColor, const CCOcclusionTrackerImpl&); + void appendQuadsToFillScreen(CCLayerImpl* rootLayer, SkColor screenBackgroundColor, const CCOcclusionTrackerImpl&); const CCQuadList& quadList() const { return m_quadList; } + + int id() const { return m_id; } CCRenderSurface* targetSurface() const { return m_targetSurface; } + // This denotes the bounds in physical pixels of the output generated by this RenderPass. const IntRect& framebufferOutputRect() const { return m_framebufferOutputRect; } @@ -68,8 +71,9 @@ public: void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; } protected: - explicit CCRenderPass(CCRenderSurface*); + CCRenderPass(CCRenderSurface*, int id); + int m_id; CCRenderSurface* m_targetSurface; CCQuadList m_quadList; IntRect m_framebufferOutputRect; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPassDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPassDrawQuad.cpp index 8dc4ff66a..75bd761d1 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPassDrawQuad.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPassDrawQuad.cpp @@ -27,20 +27,24 @@ #include "cc/CCRenderPassDrawQuad.h" +#include "cc/CCRenderPass.h" + namespace WebCore { -PassOwnPtr<CCRenderPassDrawQuad> CCRenderPassDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const CCRenderPass* renderPass, bool isReplica, const WebKit::WebFilterOperations& filters, const WebKit::WebFilterOperations& backgroundFilters, unsigned maskTextureId) +PassOwnPtr<CCRenderPassDrawQuad> CCRenderPassDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const CCRenderPass* renderPass, bool isReplica, const WebKit::WebFilterOperations& filters, const WebKit::WebFilterOperations& backgroundFilters, unsigned maskTextureId, const IntRect& contentsChangedSinceLastFrame) { - return adoptPtr(new CCRenderPassDrawQuad(sharedQuadState, quadRect, renderPass, isReplica, filters, backgroundFilters, maskTextureId)); + return adoptPtr(new CCRenderPassDrawQuad(sharedQuadState, quadRect, renderPass, isReplica, filters, backgroundFilters, maskTextureId, contentsChangedSinceLastFrame)); } -CCRenderPassDrawQuad::CCRenderPassDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const CCRenderPass* renderPass, bool isReplica, const WebKit::WebFilterOperations& filters, const WebKit::WebFilterOperations& backgroundFilters, unsigned maskTextureId) +CCRenderPassDrawQuad::CCRenderPassDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const CCRenderPass* renderPass, bool isReplica, const WebKit::WebFilterOperations& filters, const WebKit::WebFilterOperations& backgroundFilters, unsigned maskTextureId, const IntRect& contentsChangedSinceLastFrame) : CCDrawQuad(sharedQuadState, CCDrawQuad::RenderPass, quadRect) , m_renderPass(renderPass) + , m_renderPassId(renderPass->id()) , m_isReplica(isReplica) , m_filters(filters) , m_backgroundFilters(backgroundFilters) , m_maskTextureId(maskTextureId) + , m_contentsChangedSinceLastFrame(contentsChangedSinceLastFrame) { ASSERT(m_renderPass); } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPassDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPassDrawQuad.h index 3cc6f2607..b63a76446 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPassDrawQuad.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPassDrawQuad.h @@ -37,23 +37,27 @@ class CCRenderPass; class CCRenderPassDrawQuad : public CCDrawQuad { WTF_MAKE_NONCOPYABLE(CCRenderPassDrawQuad); public: - static PassOwnPtr<CCRenderPassDrawQuad> create(const CCSharedQuadState*, const IntRect&, const CCRenderPass*, bool isReplica, const WebKit::WebFilterOperations& filters, const WebKit::WebFilterOperations& backgroundFilters, unsigned maskTextureId); + static PassOwnPtr<CCRenderPassDrawQuad> create(const CCSharedQuadState*, const IntRect&, const CCRenderPass*, bool isReplica, const WebKit::WebFilterOperations& filters, const WebKit::WebFilterOperations& backgroundFilters, unsigned maskTextureId, const IntRect& contentsChangedSinceLastFrame); const CCRenderPass* renderPass() const { return m_renderPass; } + int renderPassId() const { return m_renderPassId; } bool isReplica() const { return m_isReplica; } unsigned maskTextureId() const { return m_maskTextureId; } + const IntRect& contentsChangedSinceLastFrame() const { return m_contentsChangedSinceLastFrame; } const WebKit::WebFilterOperations& filters() const { return m_filters; } const WebKit::WebFilterOperations& backgroundFilters() const { return m_backgroundFilters; } private: - CCRenderPassDrawQuad(const CCSharedQuadState*, const IntRect&, const CCRenderPass*, bool isReplica, const WebKit::WebFilterOperations& filters, const WebKit::WebFilterOperations& backgroundFilters, unsigned maskTextureId); + CCRenderPassDrawQuad(const CCSharedQuadState*, const IntRect&, const CCRenderPass*, bool isReplica, const WebKit::WebFilterOperations& filters, const WebKit::WebFilterOperations& backgroundFilters, unsigned maskTextureId, const IntRect& contentsChangedSinceLastFrame); const CCRenderPass* m_renderPass; + int m_renderPassId; bool m_isReplica; WebKit::WebFilterOperations m_filters; WebKit::WebFilterOperations m_backgroundFilters; unsigned m_maskTextureId; + IntRect m_contentsChangedSinceLastFrame; }; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp index 1cdad22e4..d3a85d2da 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp @@ -31,7 +31,6 @@ #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" -#include "ManagedTexture.h" #include "TextStream.h" #include "cc/CCDamageTracker.h" #include "cc/CCDebugBorderDrawQuad.h" @@ -78,82 +77,13 @@ FloatRect CCRenderSurface::drawableContentRect() const { FloatRect localContentRect(-0.5 * m_contentRect.width(), -0.5 * m_contentRect.height(), m_contentRect.width(), m_contentRect.height()); - FloatRect drawableContentRect = m_drawTransform.mapRect(localContentRect); + FloatRect drawableContentRect = CCMathUtil::mapClippedRect(m_drawTransform, localContentRect); if (hasReplica()) - drawableContentRect.unite(m_replicaDrawTransform.mapRect(localContentRect)); + drawableContentRect.unite(CCMathUtil::mapClippedRect(m_replicaDrawTransform, localContentRect)); return drawableContentRect; } -bool CCRenderSurface::prepareContentsTexture(LayerRendererChromium* layerRenderer) -{ - // FIXME: This method should be separated into two: one to reserve an - // existing surface, and one to create a new one. That way we will not - // need to pass null layerRenderer. - if (layerRenderer) { - TextureManager* textureManager = layerRenderer->implTextureManager(); - - if (!m_contentsTexture) - m_contentsTexture = ManagedTexture::create(textureManager); - } - - if (!m_contentsTexture) - return false; - - if (m_contentsTexture->isReserved()) - return true; - - if (!m_contentsTexture->reserve(m_contentRect.size(), GraphicsContext3D::RGBA)) - return false; - - return true; -} - -void CCRenderSurface::releaseContentsTexture() -{ - if (!m_contentsTexture || !m_contentsTexture->isReserved()) - return; - m_contentsTexture->unreserve(); -} - -bool CCRenderSurface::hasValidContentsTexture() const -{ - return m_contentsTexture && m_contentsTexture->isReserved() && m_contentsTexture->isValid(m_contentRect.size(), GraphicsContext3D::RGBA); -} - -bool CCRenderSurface::hasCachedContentsTexture() const -{ - return m_contentsTexture && m_contentsTexture->isValid(m_contentRect.size(), GraphicsContext3D::RGBA); -} - -bool CCRenderSurface::prepareBackgroundTexture(LayerRendererChromium* layerRenderer) -{ - TextureManager* textureManager = layerRenderer->implTextureManager(); - - if (!m_backgroundTexture) - m_backgroundTexture = ManagedTexture::create(textureManager); - - if (m_backgroundTexture->isReserved()) - return true; - - if (!m_backgroundTexture->reserve(m_contentRect.size(), GraphicsContext3D::RGBA)) - return false; - - return true; -} - -void CCRenderSurface::releaseBackgroundTexture() -{ - if (!m_backgroundTexture || !m_backgroundTexture->isReserved()) - return; - m_backgroundTexture->unreserve(); -} - -bool CCRenderSurface::hasValidBackgroundTexture() const -{ - return m_backgroundTexture && m_backgroundTexture->isReserved() && m_backgroundTexture->isValid(m_contentRect.size(), GraphicsContext3D::RGBA); -} - String CCRenderSurface::name() const { return String::format("RenderSurface(id=%i,owner=%s)", m_owningLayer->id(), m_owningLayer->debugName().utf8().data()); @@ -281,7 +211,7 @@ void CCRenderSurface::appendQuads(CCQuadCuller& quadList, CCSharedQuadState* sha int red = forReplica ? debugReplicaBorderColorRed : debugSurfaceBorderColorRed; int green = forReplica ? debugReplicaBorderColorGreen : debugSurfaceBorderColorGreen; int blue = forReplica ? debugReplicaBorderColorBlue : debugSurfaceBorderColorBlue; - Color color(red, green, blue, debugSurfaceBorderAlpha); + SkColor color = SkColorSetARGB(debugSurfaceBorderAlpha, red, green, blue); quadList.appendSurface(CCDebugBorderDrawQuad::create(sharedQuadState, contentRect(), color, debugSurfaceBorderWidth)); } @@ -302,8 +232,9 @@ void CCRenderSurface::appendQuads(CCQuadCuller& quadList, CCSharedQuadState* sha } int maskTextureId = maskLayer ? maskLayer->contentsTextureId() : 0; + IntRect contentsChangedSinceLastFrame = contentsChanged() ? m_contentRect : IntRect(); - quadList.appendSurface(CCRenderPassDrawQuad::create(sharedQuadState, contentRect(), renderPass, forReplica, filters(), backgroundFilters(), maskTextureId)); + quadList.appendSurface(CCRenderPassDrawQuad::create(sharedQuadState, contentRect(), renderPass, forReplica, filters(), backgroundFilters(), maskTextureId, contentsChangedSinceLastFrame)); } } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h index cdd7a7b59..894ea5aea 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h @@ -31,10 +31,10 @@ #include "FloatRect.h" #include "IntRect.h" -#include "TextureManager.h" #include <public/WebFilterOperations.h> #include <public/WebTransformationMatrix.h> #include <wtf/Noncopyable.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -44,7 +44,7 @@ class CCRenderPass; class CCSharedQuadState; class CCLayerImpl; class LayerRendererChromium; -class ManagedTexture; +class TextStream; class CCRenderSurface { WTF_MAKE_NONCOPYABLE(CCRenderSurface); @@ -52,15 +52,6 @@ public: explicit CCRenderSurface(CCLayerImpl*); virtual ~CCRenderSurface(); - virtual bool prepareContentsTexture(LayerRendererChromium*); - void releaseContentsTexture(); - bool hasValidContentsTexture() const; - virtual bool hasCachedContentsTexture() const; - - bool prepareBackgroundTexture(LayerRendererChromium*); - void releaseBackgroundTexture(); - bool hasValidBackgroundTexture() const; - String name() const; void dumpSurface(TextStream&, int indent) const; @@ -114,7 +105,7 @@ public: void setScissorRect(const IntRect& scissorRect) { m_scissorRect = scissorRect; } const IntRect& scissorRect() const { return m_scissorRect; } - virtual bool contentsChanged() const; + bool contentsChanged() const; void setContentRect(const IntRect&); const IntRect& contentRect() const { return m_contentRect; } @@ -122,9 +113,6 @@ public: void clearLayerList() { m_layerList.clear(); } Vector<CCLayerImpl*>& layerList() { return m_layerList; } - ManagedTexture* contentsTexture() const { return m_contentsTexture.get(); } - ManagedTexture* backgroundTexture() const { return m_backgroundTexture.get(); } - int owningLayerId() const; CCRenderSurface* targetRenderSurface() const; @@ -153,9 +141,6 @@ private: IntRect m_contentRect; bool m_surfacePropertyChanged; - OwnPtr<ManagedTexture> m_contentsTexture; - OwnPtr<ManagedTexture> m_backgroundTexture; - float m_drawOpacity; bool m_drawOpacityIsAnimating; WebKit::WebTransformationMatrix m_drawTransform; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceFilters.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceFilters.cpp index 30e4bff9b..2f031bf21 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceFilters.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceFilters.cpp @@ -29,8 +29,8 @@ #include "cc/CCRenderSurfaceFilters.h" +#include "FloatSize.h" #include "GraphicsContext3D.h" -#include "LengthFunctions.h" #include "SkBlurImageFilter.h" #include "SkCanvas.h" #include "SkColorMatrixFilter.h" @@ -38,6 +38,7 @@ #include "SkGrTexturePixelRef.h" #include <public/WebFilterOperation.h> #include <public/WebFilterOperations.h> +#include <wtf/MathExtras.h> namespace { diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderer.h b/Source/WebCore/platform/graphics/chromium/cc/CCRenderer.h index abad02bb7..ded0efdc3 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderer.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderer.h @@ -35,6 +35,7 @@ namespace WebCore { +class CCScopedTexture; class TextureAllocator; class TextureCopier; class TextureManager; @@ -72,11 +73,13 @@ public: const WebKit::WebTransformationMatrix& windowMatrix() const { return m_windowMatrix; } virtual void decideRenderPassAllocationsForFrame(const CCRenderPassList&) = 0; + virtual bool haveCachedResourcesForRenderPassId(int) const = 0; + virtual void beginDrawingFrame(const CCRenderPass* defaultRenderPass) = 0; virtual void drawRenderPass(const CCRenderPass*, const FloatRect& rootScissorRectInCurrentPass) = 0; virtual void finishDrawingFrame() = 0; - virtual void drawHeadsUpDisplay(ManagedTexture*, const IntSize& hudSize) = 0; + virtual void drawHeadsUpDisplay(const CCScopedTexture*, const IntSize& hudSize) = 0; // waits for rendering to finish virtual void finish() = 0; @@ -87,7 +90,6 @@ public: virtual void getFramebufferPixels(void *pixels, const IntRect&) = 0; - virtual TextureManager* implTextureManager() const = 0; virtual TextureCopier* textureCopier() const = 0; virtual TextureUploader* textureUploader() const = 0; virtual TextureAllocator* implTextureAllocator() const = 0; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp index d8355bd36..6f865c9cd 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp @@ -159,6 +159,7 @@ void CCScheduler::processScheduledActions() do { action = nextAction(); m_stateMachine.updateState(action); + TRACE_EVENT1("cc", "CCScheduler::processScheduledActions()", "action", action); switch (action) { case CCSchedulerStateMachine::ACTION_NONE: diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScopedTexture.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCScopedTexture.cpp new file mode 100644 index 000000000..80f831541 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCScopedTexture.cpp @@ -0,0 +1,74 @@ +/* + * 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 "cc/CCScopedTexture.h" + +#include "TextureManager.h" // For TextureAllocator + +namespace WebCore { + +CCScopedTexture::CCScopedTexture(TextureAllocator* allocator) + : m_allocator(allocator) +{ + ASSERT(m_allocator); +} + +CCScopedTexture::~CCScopedTexture() +{ + free(); +} + +bool CCScopedTexture::allocate(const IntSize& size, GC3Denum format) +{ + ASSERT(!id()); + ASSERT(!size.isEmpty()); + + setDimensions(size, format); + setId(m_allocator->createTexture(size, format)); + +#if !ASSERT_DISABLED + m_allocateThreadIdentifier = WTF::currentThread(); +#endif + + return id(); +} + +void CCScopedTexture::free() +{ + if (id()) { + ASSERT(m_allocateThreadIdentifier == WTF::currentThread()); + m_allocator->deleteTexture(id(), size(), format()); + } + setId(0); +} + +void CCScopedTexture::leak() +{ + setId(0); +} + +} diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScopedTexture.h b/Source/WebCore/platform/graphics/chromium/cc/CCScopedTexture.h new file mode 100644 index 000000000..5a3c4e964 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCScopedTexture.h @@ -0,0 +1,67 @@ +/* + * 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 CCScopedTexture_h +#define CCScopedTexture_h + +#include "cc/CCTexture.h" + +#if !ASSERT_DISABLED +#include <wtf/MainThread.h> +#endif + +namespace WebCore { + +class TextureAllocator; + +class CCScopedTexture : protected CCTexture { + WTF_MAKE_NONCOPYABLE(CCScopedTexture); +public: + static PassOwnPtr<CCScopedTexture> create(TextureAllocator* allocator) { return adoptPtr(new CCScopedTexture(allocator)); } + virtual ~CCScopedTexture(); + + using CCTexture::id; + using CCTexture::size; + using CCTexture::format; + using CCTexture::bytes; + + bool allocate(const IntSize&, GC3Denum format); + void free(); + void leak(); + +protected: + explicit CCScopedTexture(TextureAllocator*); + +private: + TextureAllocator* m_allocator; + +#if !ASSERT_DISABLED + ThreadIdentifier m_allocateThreadIdentifier; +#endif +}; + +} + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp index a22ef5d26..f38fbda01 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp @@ -45,11 +45,23 @@ CCScrollbarLayerImpl::CCScrollbarLayerImpl(int id) : CCLayerImpl(id) , m_scrollLayer(0) , m_scrollbar(this) - , m_backgroundTextureId(0) + , m_backTrackTextureId(0) + , m_foreTrackTextureId(0) , m_thumbTextureId(0) { } +namespace { + +FloatRect toUVRect(const IntRect& r, const IntRect& bounds) +{ + ASSERT(bounds.contains(r)); + return FloatRect(static_cast<float>(r.x()) / bounds.width(), static_cast<float>(r.y()) / bounds.height(), + static_cast<float>(r.width()) / bounds.width(), static_cast<float>(r.height()) / bounds.height()); +} + +} + void CCScrollbarLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&) { ScrollbarThemeComposite* theme = static_cast<ScrollbarThemeComposite*>(ScrollbarTheme::theme()); @@ -57,24 +69,33 @@ void CCScrollbarLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQua return; bool premultipledAlpha = false; - FloatRect uvRect(0, 0, 1, 1); bool flipped = false; + FloatRect uvRect(0, 0, 1, 1); + IntRect boundsRect(IntPoint(), contentBounds()); + + IntRect thumbRect, backTrackRect, foreTrackRect; + theme->splitTrack(&m_scrollbar, theme->trackRect(&m_scrollbar), backTrackRect, thumbRect, foreTrackRect); - IntRect thumbRect = theme->thumbRect(&m_scrollbar); - thumbRect.move(-m_scrollbar.x(), -m_scrollbar.y()); if (m_thumbTextureId && theme->hasThumb(&m_scrollbar) && !thumbRect.isEmpty()) { OwnPtr<CCTextureDrawQuad> quad = CCTextureDrawQuad::create(sharedQuadState, thumbRect, m_thumbTextureId, premultipledAlpha, uvRect, flipped); quad->setNeedsBlending(); quadList.append(quad.release()); } - if (!m_backgroundTextureId) + if (!m_backTrackTextureId) return; - IntRect backgroundRect(IntPoint(), contentBounds()); - quadList.append(CCTextureDrawQuad::create(sharedQuadState, backgroundRect, m_backgroundTextureId, premultipledAlpha, uvRect, flipped)); + // We only paint the track in two parts if we were given a texture for the forward track part. + if (m_foreTrackTextureId && !foreTrackRect.isEmpty()) + quadList.append(CCTextureDrawQuad::create(sharedQuadState, foreTrackRect, m_foreTrackTextureId, premultipledAlpha, toUVRect(foreTrackRect, boundsRect), flipped)); + + // Order matters here: since the back track texture is being drawn to the entire contents rect, we must append it after the thumb and + // fore track quads. The back track texture contains (and displays) the buttons. + if (!boundsRect.isEmpty()) + quadList.append(CCTextureDrawQuad::create(sharedQuadState, boundsRect, m_backTrackTextureId, premultipledAlpha, uvRect, flipped)); } + int CCScrollbarLayerImpl::CCScrollbar::x() const { return frameRect().x(); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h index 98d553446..ece2b9571 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h @@ -33,7 +33,6 @@ namespace WebCore { -class GraphicsContext; class ScrollView; class CCScrollbarLayerImpl : public CCLayerImpl { @@ -54,7 +53,8 @@ public: void setEnabled(bool enabled) { m_enabled = enabled; } - void setBackgroundTextureId(unsigned id) { m_backgroundTextureId = id; } + void setBackTrackTextureId(unsigned id) { m_backTrackTextureId = id; } + void setForeTrackTextureId(unsigned id) { m_foreTrackTextureId = id; } void setThumbTextureId(unsigned id) { m_thumbTextureId = id; } CCLayerImpl* scrollLayer() const { return m_scrollLayer; } @@ -124,7 +124,8 @@ private: }; CCScrollbar m_scrollbar; - unsigned m_backgroundTextureId; + unsigned m_backTrackTextureId; + unsigned m_foreTrackTextureId; unsigned m_thumbTextureId; ScrollbarOverlayStyle m_scrollbarOverlayStyle; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.cpp index 536b39867..5e0681ff5 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.cpp @@ -27,6 +27,8 @@ #include "cc/CCSharedQuadState.h" +#include "cc/CCMathUtil.h" + using WebKit::WebTransformationMatrix; namespace WebCore { @@ -50,8 +52,9 @@ bool CCSharedQuadState::isLayerAxisAlignedIntRect() const { // Note: this doesn't consider window or projection matrices. // Assume that they're orthonormal and have integer scales and translations. - FloatQuad quad = quadTransform().mapQuad(FloatQuad(layerRect())); - return quad.isRectilinear() && quad.boundingBox().isExpressibleAsIntRect(); + bool clipped = false; + FloatQuad quad = CCMathUtil::mapQuad(quadTransform(), FloatQuad(layerRect()), clipped); + return !clipped && quad.isRectilinear() && quad.boundingBox().isExpressibleAsIntRect(); } } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp index d69e4bc45..678efdff0 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp @@ -52,7 +52,7 @@ CCSingleThreadProxy::CCSingleThreadProxy(CCLayerTreeHost* layerTreeHost) , m_layerRendererInitialized(false) , m_nextFrameIsNewlyCommittedFrame(false) { - TRACE_EVENT("CCSingleThreadProxy::CCSingleThreadProxy", this, 0); + TRACE_EVENT0("cc", "CCSingleThreadProxy::CCSingleThreadProxy"); ASSERT(CCProxy::isMainThread()); } @@ -64,14 +64,14 @@ void CCSingleThreadProxy::start() CCSingleThreadProxy::~CCSingleThreadProxy() { - TRACE_EVENT("CCSingleThreadProxy::~CCSingleThreadProxy", this, 0); + TRACE_EVENT0("cc", "CCSingleThreadProxy::~CCSingleThreadProxy"); ASSERT(CCProxy::isMainThread()); ASSERT(!m_layerTreeHostImpl && !m_layerTreeHost); // make sure stop() got called. } bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) { - TRACE_EVENT("CCSingleThreadProxy::compositeAndReadback", this, 0); + TRACE_EVENT0("cc", "CCSingleThreadProxy::compositeAndReadback"); ASSERT(CCProxy::isMainThread()); if (!commitAndComposite()) @@ -255,7 +255,7 @@ void CCSingleThreadProxy::didAddAnimation() void CCSingleThreadProxy::stop() { - TRACE_EVENT("CCSingleThreadProxy::stop", this, 0); + TRACE_EVENT0("cc", "CCSingleThreadProxy::stop"); ASSERT(CCProxy::isMainThread()); { DebugScopedSetMainThreadBlocked mainThreadBlocked; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.cpp index 7f6f98113..8668369b6 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.cpp @@ -29,16 +29,16 @@ namespace WebCore { -PassOwnPtr<CCSolidColorDrawQuad> CCSolidColorDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const Color& color) +PassOwnPtr<CCSolidColorDrawQuad> CCSolidColorDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color) { return adoptPtr(new CCSolidColorDrawQuad(sharedQuadState, quadRect, color)); } -CCSolidColorDrawQuad::CCSolidColorDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const Color& color) +CCSolidColorDrawQuad::CCSolidColorDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color) : CCDrawQuad(sharedQuadState, CCDrawQuad::SolidColor, quadRect) , m_color(color) { - if (m_color.hasAlpha()) + if (SkColorGetA(m_color) < 255) m_quadOpaque = false; else m_opaqueRect = quadRect; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.h index d020df684..83ea34066 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorDrawQuad.h @@ -26,7 +26,7 @@ #ifndef CCSolidColorDrawQuad_h #define CCSolidColorDrawQuad_h -#include "Color.h" +#include "SkColor.h" #include "cc/CCDrawQuad.h" #include <wtf/PassOwnPtr.h> @@ -35,14 +35,14 @@ namespace WebCore { class CCSolidColorDrawQuad : public CCDrawQuad { WTF_MAKE_NONCOPYABLE(CCSolidColorDrawQuad); public: - static PassOwnPtr<CCSolidColorDrawQuad> create(const CCSharedQuadState*, const IntRect&, const Color&); + static PassOwnPtr<CCSolidColorDrawQuad> create(const CCSharedQuadState*, const IntRect&, SkColor); - const Color& color() const { return m_color; }; + SkColor color() const { return m_color; }; private: - CCSolidColorDrawQuad(const CCSharedQuadState*, const IntRect&, const Color&); + CCSolidColorDrawQuad(const CCSharedQuadState*, const IntRect&, SkColor); - Color m_color; + SkColor m_color; }; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTexture.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTexture.cpp new file mode 100644 index 000000000..a48e2d0f9 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTexture.cpp @@ -0,0 +1,57 @@ +/* + * 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 "cc/CCTexture.h" + +namespace WebCore { + +void CCTexture::setDimensions(const IntSize& size, GC3Denum format) +{ + m_size = size; + m_format = format; +} + +size_t CCTexture::bytes() const +{ + if (m_size.isEmpty()) + return 0u; + + return memorySizeBytes(m_size, m_format); +} + +size_t CCTexture::memorySizeBytes(const IntSize& size, GC3Denum format) +{ + unsigned int componentsPerPixel; + unsigned int bytesPerComponent; + if (!GraphicsContext3D::computeFormatAndTypeParameters(format, GraphicsContext3D::UNSIGNED_BYTE, &componentsPerPixel, &bytesPerComponent)) { + ASSERT_NOT_REACHED(); + return 0u; + } + return componentsPerPixel * bytesPerComponent * size.width() * size.height(); +} + +} diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTexture.h b/Source/WebCore/platform/graphics/chromium/cc/CCTexture.h new file mode 100644 index 000000000..a29610469 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTexture.h @@ -0,0 +1,58 @@ +/* + * 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 CCTexture_h +#define CCTexture_h + +#include "GraphicsContext3D.h" +#include "IntSize.h" +#include "cc/CCTexture.h" + +namespace WebCore { + +class CCTexture { +public: + CCTexture() : m_id(0) { } + + unsigned id() const { return m_id; } + const IntSize& size() const { return m_size; } + GC3Denum format() const { return m_format; } + + void setId(unsigned id) { m_id = id; } + void setDimensions(const IntSize&, GC3Denum format); + + size_t bytes() const; + + static size_t memorySizeBytes(const IntSize&, GC3Denum format); + +private: + unsigned m_id; + IntSize m_size; + GC3Denum m_format; +}; + +} + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp index c3299939b..3190d82ff 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp @@ -29,6 +29,7 @@ #include "cc/CCTextureUpdater.h" +#include "CCPrioritizedTexture.h" #include "GraphicsContext3D.h" #include "LayerTextureUpdater.h" #include "TextureCopier.h" @@ -58,9 +59,9 @@ void CCTextureUpdater::appendUpdate(LayerTextureUpdater::Texture* texture, const entries.append(entry); } -void CCTextureUpdater::appendUpdate(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect) +void CCTextureUpdater::appendFullUpdate(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect) { - appendUpdate(texture, sourceRect, destRect, m_entries); + appendUpdate(texture, sourceRect, destRect, m_fullEntries); } void CCTextureUpdater::appendPartialUpdate(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect) @@ -79,26 +80,26 @@ void CCTextureUpdater::appendCopy(unsigned sourceTexture, unsigned destTexture, bool CCTextureUpdater::hasMoreUpdates() const { - return m_entries.size() || m_partialEntries.size() || m_copyEntries.size(); + return m_fullEntries.size() || m_partialEntries.size() || m_copyEntries.size(); } void CCTextureUpdater::update(CCGraphicsContext* context, TextureAllocator* allocator, TextureCopier* copier, TextureUploader* uploader, size_t count) { size_t index; - if (m_entries.size() || m_partialEntries.size()) { + if (m_fullEntries.size() || m_partialEntries.size()) { if (uploader->isBusy()) return; uploader->beginUploads(); - size_t maxIndex = min(m_entryIndex + count, m_entries.size()); + size_t maxIndex = min(m_entryIndex + count, m_fullEntries.size()); for (index = m_entryIndex; index < maxIndex; ++index) { - UpdateEntry& entry = m_entries[index]; + UpdateEntry& entry = m_fullEntries[index]; uploader->uploadTexture(context, entry.texture, allocator, entry.sourceRect, entry.destRect); } - bool moreUploads = maxIndex < m_entries.size(); + bool moreUploads = maxIndex < m_fullEntries.size(); ASSERT(m_partialEntries.size() <= count); // We need another update batch if the number of updates remaining @@ -142,7 +143,7 @@ void CCTextureUpdater::update(CCGraphicsContext* context, TextureAllocator* allo void CCTextureUpdater::clear() { m_entryIndex = 0; - m_entries.clear(); + m_fullEntries.clear(); m_partialEntries.clear(); m_copyEntries.clear(); } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h index 0f139f385..8a437942b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h @@ -41,7 +41,7 @@ public: CCTextureUpdater(); ~CCTextureUpdater(); - void appendUpdate(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect); + void appendFullUpdate(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect); void appendPartialUpdate(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect); void appendCopy(unsigned sourceTexture, unsigned destTexture, const IntSize&); @@ -68,7 +68,7 @@ private: static void appendUpdate(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect, Vector<UpdateEntry>&); size_t m_entryIndex; - Vector<UpdateEntry> m_entries; + Vector<UpdateEntry> m_fullEntries; Vector<UpdateEntry> m_partialEntries; Vector<CopyEntry> m_copyEntries; }; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp index 382274746..9973a974b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp @@ -89,25 +89,25 @@ CCThreadProxy::CCThreadProxy(CCLayerTreeHost* layerTreeHost) , m_textureAcquisitionCompletionEventOnImplThread(0) , m_nextFrameIsNewlyCommittedFrameOnImplThread(false) { - TRACE_EVENT("CCThreadProxy::CCThreadProxy", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::CCThreadProxy"); ASSERT(isMainThread()); } CCThreadProxy::~CCThreadProxy() { - TRACE_EVENT("CCThreadProxy::~CCThreadProxy", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::~CCThreadProxy"); ASSERT(isMainThread()); ASSERT(!m_started); } bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) { - TRACE_EVENT("CCThreadPRoxy::compositeAndReadback", this, 0); + TRACE_EVENT0("cc", "CCThreadPRoxy::compositeAndReadback"); ASSERT(isMainThread()); ASSERT(m_layerTreeHost); if (!m_layerTreeHost->initializeLayerRendererIfNeeded()) { - TRACE_EVENT("compositeAndReadback_EarlyOut_LR_Uninitialized", this, 0); + TRACE_EVENT0("cc", "compositeAndReadback_EarlyOut_LR_Uninitialized"); return false; } @@ -175,7 +175,7 @@ bool CCThreadProxy::isStarted() const bool CCThreadProxy::initializeContext() { - TRACE_EVENT("CCThreadProxy::initializeContext", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::initializeContext"); OwnPtr<CCGraphicsContext> context = m_layerTreeHost->createContext(); if (!context) return false; @@ -215,7 +215,7 @@ void CCThreadProxy::setVisibleOnImplThread(CCCompletionEvent* completion, bool v bool CCThreadProxy::initializeLayerRenderer() { - TRACE_EVENT("CCThreadProxy::initializeLayerRenderer", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::initializeLayerRenderer"); // Make a blocking call to initializeLayerRendererOnImplThread. The results of that call // are pushed into the initializeSucceeded and capabilities local variables. CCCompletionEvent completion; @@ -299,7 +299,7 @@ void CCThreadProxy::setNeedsAnimate() if (m_animateRequested) return; - TRACE_EVENT("CCThreadProxy::setNeedsAnimate", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsAnimate"); m_animateRequested = true; setNeedsCommit(); } @@ -310,7 +310,7 @@ void CCThreadProxy::setNeedsCommit() if (m_commitRequested) return; - TRACE_EVENT("CCThreadProxy::setNeedsCommit", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsCommit"); m_commitRequested = true; CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitOnImplThread)); } @@ -325,7 +325,7 @@ void CCThreadProxy::didLoseContextOnImplThread() void CCThreadProxy::onSwapBuffersCompleteOnImplThread() { ASSERT(isImplThread()); - TRACE_EVENT("CCThreadProxy::onSwapBuffersCompleteOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::onSwapBuffersCompleteOnImplThread"); m_schedulerOnImplThread->didSwapBuffersComplete(); m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCompleteSwapBuffers)); } @@ -333,14 +333,14 @@ void CCThreadProxy::onSwapBuffersCompleteOnImplThread() void CCThreadProxy::setNeedsCommitOnImplThread() { ASSERT(isImplThread()); - TRACE_EVENT("CCThreadProxy::setNeedsCommitOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsCommitOnImplThread"); m_schedulerOnImplThread->setNeedsCommit(); } void CCThreadProxy::setNeedsForcedCommitOnImplThread() { ASSERT(isImplThread()); - TRACE_EVENT("CCThreadProxy::setNeedsForcedCommitOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsForcedCommitOnImplThread"); m_schedulerOnImplThread->setNeedsCommit(); m_schedulerOnImplThread->setNeedsForcedCommit(); } @@ -348,14 +348,14 @@ void CCThreadProxy::setNeedsForcedCommitOnImplThread() void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime) { ASSERT(isImplThread()); - TRACE_EVENT("CCThreadProxy::postAnimationEventsToMainThreadOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::postAnimationEventsToMainThreadOnImplThread"); m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events, wallClockTime)); } void CCThreadProxy::setNeedsRedraw() { ASSERT(isMainThread()); - TRACE_EVENT("CCThreadProxy::setNeedsRedraw", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsRedraw"); CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setFullRootLayerDamageOnImplThread)); CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsRedrawOnImplThread)); } @@ -369,7 +369,7 @@ bool CCThreadProxy::commitRequested() const void CCThreadProxy::setNeedsRedrawOnImplThread() { ASSERT(isImplThread()); - TRACE_EVENT("CCThreadProxy::setNeedsRedrawOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsRedrawOnImplThread"); m_schedulerOnImplThread->setNeedsRedraw(); } @@ -387,7 +387,7 @@ void CCThreadProxy::start() void CCThreadProxy::stop() { - TRACE_EVENT("CCThreadProxy::stop", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::stop"); ASSERT(isMainThread()); ASSERT(m_started); @@ -424,7 +424,7 @@ void CCThreadProxy::forceSerializeOnSwapBuffersOnImplThread(CCCompletionEvent* c void CCThreadProxy::finishAllRenderingOnImplThread(CCCompletionEvent* completion) { - TRACE_EVENT("CCThreadProxy::finishAllRenderingOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::finishAllRenderingOnImplThread"); ASSERT(isImplThread()); m_layerTreeHostImpl->finishAllRendering(); completion->signal(); @@ -541,7 +541,7 @@ void CCThreadProxy::beginFrame() // point of view, but asynchronously performed on the impl thread, // coordinated by the CCScheduler. { - TRACE_EVENT("commit", this, 0); + TRACE_EVENT0("cc", "commit"); DebugScopedSetMainThreadBlocked mainThreadBlocked; CCCompletionEvent completion; @@ -555,7 +555,7 @@ void CCThreadProxy::beginFrame() void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion) { - TRACE_EVENT("CCThreadProxy::beginFrameCompleteOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::beginFrameCompleteOnImplThread"); ASSERT(!m_commitCompletionEventOnImplThread); ASSERT(isImplThread()); ASSERT(m_schedulerOnImplThread); @@ -598,14 +598,14 @@ bool CCThreadProxy::canDraw() void CCThreadProxy::scheduledActionUpdateMoreResources() { - TRACE_EVENT("CCThreadProxy::scheduledActionUpdateMoreResources", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionUpdateMoreResources"); ASSERT(m_currentTextureUpdaterOnImplThread); m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), m_layerTreeHostImpl->contentsTextureAllocator(), m_layerTreeHostImpl->layerRenderer()->textureCopier(), m_layerTreeHostImpl->layerRenderer()->textureUploader(), textureUpdatesPerFrame); } void CCThreadProxy::scheduledActionCommit() { - TRACE_EVENT("CCThreadProxy::scheduledActionCommit", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionCommit"); ASSERT(isImplThread()); ASSERT(m_currentTextureUpdaterOnImplThread); ASSERT(!m_currentTextureUpdaterOnImplThread->hasMoreUpdates()); @@ -637,7 +637,7 @@ void CCThreadProxy::scheduledActionBeginContextRecreation() CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapInternal(bool forcedDraw) { - TRACE_EVENT("CCThreadProxy::scheduledActionDrawAndSwap", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionDrawAndSwap"); CCScheduledActionDrawAndSwapResult result; result.didDraw = false; result.didSwap = false; @@ -707,7 +707,7 @@ void CCThreadProxy::acquireLayerTextures() if (m_texturesAcquired) return; - TRACE_EVENT("CCThreadProxy::acquireLayerTextures", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::acquireLayerTextures"); CCCompletionEvent completion; CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::acquireLayerTexturesForMainThreadOnImplThread, AllowCrossThreadAccess(&completion))); completion.wait(); // Block until it is safe to write to layer textures from the main thread. @@ -808,7 +808,7 @@ void CCThreadProxy::tryToRecreateContext() void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion) { - TRACE_EVENT("CCThreadProxy::initializeImplOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::initializeImplOnImplThread"); ASSERT(isImplThread()); m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this); const double displayRefreshInterval = 1.0 / 60.0; @@ -824,14 +824,14 @@ void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion) void CCThreadProxy::initializeContextOnImplThread(CCGraphicsContext* context) { - TRACE_EVENT("CCThreadProxy::initializeContextOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::initializeContextOnImplThread"); ASSERT(isImplThread()); m_contextBeforeInitializationOnImplThread = adoptPtr(context); } void CCThreadProxy::initializeLayerRendererOnImplThread(CCCompletionEvent* completion, bool* initializeSucceeded, LayerRendererCapabilities* capabilities) { - TRACE_EVENT("CCThreadProxy::initializeLayerRendererOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::initializeLayerRendererOnImplThread"); ASSERT(isImplThread()); ASSERT(m_contextBeforeInitializationOnImplThread); *initializeSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitializationOnImplThread.release(), textureUploader); @@ -846,7 +846,7 @@ void CCThreadProxy::initializeLayerRendererOnImplThread(CCCompletionEvent* compl void CCThreadProxy::layerTreeHostClosedOnImplThread(CCCompletionEvent* completion) { - TRACE_EVENT("CCThreadProxy::layerTreeHostClosedOnImplThread", this, 0); + TRACE_EVENT0("cc", "CCThreadProxy::layerTreeHostClosedOnImplThread"); ASSERT(isImplThread()); if (!m_layerTreeHostImpl->contentsTexturesWerePurgedSinceLastCommit()) m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator()); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp index 984c3b7be..564e3696b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp @@ -29,6 +29,8 @@ #include "cc/CCTiledLayerImpl.h" +#include "GraphicsContext3D.h" +#include "SkColor.h" #include "TextStream.h" #include "cc/CCCheckerboardDrawQuad.h" #include "cc/CCDebugBorderDrawQuad.h" @@ -153,12 +155,12 @@ void CCTiledLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadSta for (int i = left; i <= right; ++i) { DrawableTile* tile = tileAt(i, j); IntRect tileRect = m_tiler->tileBounds(i, j); - Color borderColor; + SkColor borderColor; if (m_skipsDraw || !tile || !tile->textureId()) - borderColor = Color(debugTileBorderMissingTileColorRed, debugTileBorderMissingTileColorGreen, debugTileBorderMissingTileColorBlue, debugTileBorderAlpha); + borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderMissingTileColorRed, debugTileBorderMissingTileColorGreen, debugTileBorderMissingTileColorBlue); else - borderColor = Color(debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue, debugTileBorderAlpha); + borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue); quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState, tileRect, borderColor, debugTileBorderWidth)); } } @@ -219,7 +221,7 @@ void CCTiledLayerImpl::setTilingData(const CCLayerTilingData& tiler) *m_tiler = tiler; } -void CCTiledLayerImpl::pushTileProperties(int i, int j, Platform3DObject textureId, const IntRect& opaqueRect) +void CCTiledLayerImpl::pushTileProperties(int i, int j, unsigned textureId, const IntRect& opaqueRect) { DrawableTile* tile = tileAt(i, j); if (!tile) diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h index 131a32fce..4c82cdc8c 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h @@ -50,7 +50,7 @@ public: void setSkipsDraw(bool skipsDraw) { m_skipsDraw = skipsDraw; } void setTilingData(const CCLayerTilingData& tiler); - void pushTileProperties(int, int, Platform3DObject textureId, const IntRect& opaqueRect); + void pushTileProperties(int, int, unsigned textureId, const IntRect& opaqueRect); void setContentsSwizzled(bool contentsSwizzled) { m_contentsSwizzled = contentsSwizzled; } bool contentsSwizzled() const { return m_contentsSwizzled; } diff --git a/Source/WebCore/platform/graphics/clutter/DrawingBufferClutter.cpp b/Source/WebCore/platform/graphics/clutter/DrawingBufferClutter.cpp index af99700c9..b52ab8dd2 100644 --- a/Source/WebCore/platform/graphics/clutter/DrawingBufferClutter.cpp +++ b/Source/WebCore/platform/graphics/clutter/DrawingBufferClutter.cpp @@ -31,7 +31,7 @@ #include "config.h" -#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(WEBGL) +#if ENABLE(ACCELERATED_2D_CANVAS) || USE(3D_GRAPHICS) #include "DrawingBuffer.h" diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp index ca0ffdc2b..4b4b0e39d 100644 --- a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp +++ b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp @@ -29,7 +29,7 @@ #include "config.h" #include "GraphicsContext3D.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "Extensions3DOpenGL.h" #include "GraphicsContext3DPrivate.h" @@ -56,6 +56,11 @@ GraphicsContext3D::~GraphicsContext3D() notImplemented(); } +void GraphicsContext3D::releaseShaderCompiler() +{ + notImplemented(); +} + bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) { notImplemented(); @@ -100,4 +105,4 @@ PlatformLayer* GraphicsContext3D::platformLayer() const } // namespace WebCore -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.cpp index cad170fb0..2aebb65e6 100644 --- a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.cpp +++ b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DPrivate.cpp @@ -20,7 +20,7 @@ #include "config.h" #include "GraphicsContext3DPrivate.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "HostWindow.h" #include "NotImplemented.h" @@ -61,4 +61,4 @@ void GraphicsContext3DPrivate::paintToGraphicsLayerActor(ClutterActor*, const Fl } // namespace WebCore -#endif // ENABLE_WEBGL +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp index 6a37ebc10..2f5c96ae9 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp @@ -19,7 +19,7 @@ #include "config.h" -#if ENABLE(WEBGL) || USE(ACCELERATED_COMPOSITING) +#if USE(3D_GRAPHICS) || USE(ACCELERATED_COMPOSITING) #include "GraphicsContext3DPrivate.h" @@ -857,4 +857,4 @@ bool GraphicsContext3D::isResourceSafe() } // namespace WebCore -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp index e51ddc1b4..345507fd3 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp @@ -19,7 +19,7 @@ #include "config.h" -#if ENABLE(WEBGL) || USE(ACCELERATED_COMPOSITING) +#if USE(3D_GRAPHICS) || USE(ACCELERATED_COMPOSITING) #include "GraphicsContext3DPrivate.h" @@ -1121,4 +1121,4 @@ Extensions3D* GraphicsContext3DPrivate::getExtensions() } // namespace WebCore -#endif // ENABLE(WEBGL) || USE(ACCELERATED_COMPOSITING) +#endif // USE(3D_GRAPHICS) || USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.cpp index c5771739d..9ab5e570d 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.cpp @@ -29,7 +29,7 @@ #include "config.h" -#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #include "CustomFilterCompiledProgram.h" #include "GraphicsContext3D.h" @@ -87,6 +87,8 @@ CustomFilterCompiledProgram::CustomFilterCompiledProgram(GraphicsContext3D* cont , m_contentSamplerLocation(-1) , m_isInitialized(false) { + m_context->makeContextCurrent(); + Platform3DObject vertexShader = compileShader(GraphicsContext3D::VERTEX_SHADER, m_vertexShaderString); if (!vertexShader) return; @@ -171,9 +173,11 @@ int CustomFilterCompiledProgram::uniformLocationByName(const String& name) CustomFilterCompiledProgram::~CustomFilterCompiledProgram() { - if (m_program) + if (m_program) { + m_context->makeContextCurrent(); m_context->deleteProgram(m_program); + } } } // namespace WebCore -#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.h b/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.h index b0c449c3b..6057efe24 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterCompiledProgram.h @@ -30,7 +30,7 @@ #ifndef CustomFilterCompiledProgram_h #define CustomFilterCompiledProgram_h -#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #include "GraphicsTypes3D.h" #include <wtf/RefCounted.h> @@ -104,6 +104,6 @@ private: } -#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #endif diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp index 0bf749f81..455ae40c9 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp @@ -29,7 +29,7 @@ #include "config.h" -#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #include "CustomFilterGlobalContext.h" #include "GraphicsContext3D.h" @@ -53,10 +53,12 @@ void CustomFilterGlobalContext::prepareContextIfNeeded(HostWindow* hostWindow) attributes.preserveDrawingBuffer = true; attributes.premultipliedAlpha = false; m_context = GraphicsContext3D::create(attributes, hostWindow, GraphicsContext3D::RenderOffscreen); - + if (!m_context) + return; + m_context->makeContextCurrent(); m_context->enable(GraphicsContext3D::DEPTH_TEST); } } // namespace WebCore -#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.h b/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.h index 3f38ba93d..aba003581 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.h @@ -30,7 +30,7 @@ #ifndef CustomFilterGlobalContext_h #define CustomFilterGlobalContext_h -#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #include <wtf/RefPtr.h> namespace WebCore { @@ -53,6 +53,6 @@ private: } // namespace WebCore -#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #endif // CustomFilterGlobalContext_h diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp index c3a986815..e014f0a06 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp @@ -29,7 +29,7 @@ #include "config.h" -#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #include "CustomFilterMesh.h" #include "GraphicsContext3D.h" @@ -245,6 +245,8 @@ CustomFilterMesh::CustomFilterMesh(GraphicsContext3D* context, unsigned columns, m_indicesCount = generator.indicesCount(); m_bytesPerVertex = generator.floatsPerVertex() * sizeof(float); + m_context->makeContextCurrent(); + m_verticesBufferObject = m_context->createBuffer(); m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_verticesBufferObject); m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, generator.vertices().size() * sizeof(float), generator.vertices().data(), GraphicsContext3D::STATIC_DRAW); @@ -256,11 +258,12 @@ CustomFilterMesh::CustomFilterMesh(GraphicsContext3D* context, unsigned columns, CustomFilterMesh::~CustomFilterMesh() { + m_context->makeContextCurrent(); m_context->deleteBuffer(m_verticesBufferObject); m_context->deleteBuffer(m_elementsBufferObject); } } // namespace WebCore -#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h index 46f37f361..e3c7a6bac 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h @@ -30,7 +30,7 @@ #ifndef CustomFilterMesh_h #define CustomFilterMesh_h -#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #include "CustomFilterOperation.h" #include "FloatRect.h" @@ -75,6 +75,6 @@ private: } // namespace WebCore -#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #endif // CustomFilterMesh_h diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp index fe43640c6..60cff22e7 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp @@ -35,7 +35,7 @@ #include "CustomFilterCompiledProgram.h" #include "CustomFilterProgramClient.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "GraphicsContext3D.h" #endif @@ -80,7 +80,7 @@ void CustomFilterProgram::notifyClients() iter->first->notifyCustomFilterProgramLoaded(this); } -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) PassRefPtr<CustomFilterCompiledProgram> CustomFilterProgram::compileProgramWithContext(GraphicsContext3D* context) { ASSERT(isLoaded()); diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h index 12292a100..221606676 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h @@ -53,7 +53,7 @@ public: void addClient(CustomFilterProgramClient*); void removeClient(CustomFilterProgramClient*); -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) PassRefPtr<CustomFilterCompiledProgram> compileProgramWithContext(GraphicsContext3D*); #endif diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp index ac05941cd..36d06d32b 100644 --- a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp +++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp @@ -29,7 +29,7 @@ #include "config.h" -#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #include "FECustomFilter.h" #include "CustomFilterCompiledProgram.h" @@ -103,6 +103,9 @@ FECustomFilter::~FECustomFilter() void FECustomFilter::deleteRenderBuffers() { + if (!m_context) + return; + m_context->makeContextCurrent(); if (m_frameBuffer) { m_context->deleteFramebuffer(m_frameBuffer); m_frameBuffer = 0; @@ -129,8 +132,9 @@ void FECustomFilter::platformApplySoftware() IntSize newContextSize(effectDrawingRect.size()); bool hadContext = m_context; - if (!m_context) - initializeContext(); + if (!m_context && !initializeContext()) + return; + m_context->makeContextCurrent(); if (!hadContext || m_contextSize != newContextSize) resizeContext(newContextSize); @@ -157,11 +161,13 @@ void FECustomFilter::platformApplySoftware() m_context->readPixels(0, 0, newContextSize.width(), newContextSize.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, dstPixelArray->data()); } -void FECustomFilter::initializeContext() +bool FECustomFilter::initializeContext() { ASSERT(!m_context.get()); - ASSERT(m_globalContext->context()); m_context = m_globalContext->context(); + if (!m_context) + return false; + m_context->makeContextCurrent(); // FIXME: The shader and the mesh can be shared across multiple elements when possible. // Sharing the shader means it's no need to analyze / compile and upload to GPU again. @@ -174,6 +180,7 @@ void FECustomFilter::initializeContext() m_mesh = CustomFilterMesh::create(m_context.get(), m_meshColumns, m_meshRows, FloatRect(0, 0, 1, 1), m_meshType); + return true; } void FECustomFilter::resizeContext(const IntSize& newContextSize) @@ -303,4 +310,4 @@ TextStream& FECustomFilter::externalRepresentation(TextStream& ts, int indent) c } // namespace WebCore -#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.h b/Source/WebCore/platform/graphics/filters/FECustomFilter.h index 3c731abcc..b7f93698e 100644 --- a/Source/WebCore/platform/graphics/filters/FECustomFilter.h +++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.h @@ -30,7 +30,7 @@ #ifndef FECustomFilter_h #define FECustomFilter_h -#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #include "CustomFilterOperation.h" #include "Filter.h" @@ -72,7 +72,7 @@ private: CustomFilterOperation::MeshType); ~FECustomFilter(); - void initializeContext(); + bool initializeContext(); void deleteRenderBuffers(); void resizeContext(const IntSize& newContextSize); void bindVertexAttribute(int attributeLocation, unsigned size, unsigned& offset); @@ -103,6 +103,6 @@ private: } // namespace WebCore -#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) #endif // FECustomFilter_h diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp index 6f2277681..1950ee9e3 100644 --- a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp +++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp @@ -120,13 +120,27 @@ inline void FEGaussianBlur::platformApplyGeneric(Uint8ClampedArray* srcPixelArra for (int i = 0; i < 3; ++i) { if (kernelSizeX) { kernelPosition(i, kernelSizeX, dxLeft, dxRight); +#if HAVE(ARM_NEON_INTRINSICS) + if (!isAlphaImage()) + boxBlurNEON(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height()); + else + boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), true); +#else boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), isAlphaImage()); +#endif swap(src, dst); } if (kernelSizeY) { kernelPosition(i, kernelSizeY, dyLeft, dyRight); +#if HAVE(ARM_NEON_INTRINSICS) + if (!isAlphaImage()) + boxBlurNEON(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width()); + else + boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), true); +#else boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), isAlphaImage()); +#endif swap(src, dst); } } @@ -142,13 +156,8 @@ inline void FEGaussianBlur::platformApplyGeneric(Uint8ClampedArray* srcPixelArra void FEGaussianBlur::platformApplyWorker(PlatformApplyParameters* parameters) { IntSize paintSize(parameters->width, parameters->height); -#if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC) - parameters->filter->platformApplyNeon(parameters->srcPixelArray.get(), parameters->dstPixelArray.get(), - parameters->kernelSizeX, parameters->kernelSizeY, paintSize); -#else parameters->filter->platformApplyGeneric(parameters->srcPixelArray.get(), parameters->dstPixelArray.get(), parameters->kernelSizeX, parameters->kernelSizeY, paintSize); -#endif } inline void FEGaussianBlur::platformApply(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize) @@ -221,11 +230,7 @@ inline void FEGaussianBlur::platformApply(Uint8ClampedArray* srcPixelArray, Uint } // The selection here eventually should happen dynamically on some platforms. -#if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC) - platformApplyNeon(srcPixelArray, tmpPixelArray, kernelSizeX, kernelSizeY, paintSize); -#else platformApplyGeneric(srcPixelArray, tmpPixelArray, kernelSizeX, kernelSizeY, paintSize); -#endif } void FEGaussianBlur::calculateUnscaledKernelSize(unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY) diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h index c3db1f150..7b3bdce29 100644 --- a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h +++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h @@ -73,7 +73,6 @@ private: inline void platformApply(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize); inline void platformApplyGeneric(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize); - inline void platformApplyNeon(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize); #if USE(SKIA) virtual bool platformApplySkia(); #endif diff --git a/Source/WebCore/platform/graphics/filters/FilterOperation.h b/Source/WebCore/platform/graphics/filters/FilterOperation.h index 255f64048..b8796e802 100644 --- a/Source/WebCore/platform/graphics/filters/FilterOperation.h +++ b/Source/WebCore/platform/graphics/filters/FilterOperation.h @@ -33,7 +33,7 @@ #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> #include <wtf/RefCounted.h> -#include <wtf/text/AtomicString.h> +#include <wtf/text/WTFString.h> // Annoyingly, wingdi.h #defines this. #ifdef PASSTHROUGH @@ -147,21 +147,25 @@ private: class ReferenceFilterOperation : public FilterOperation { public: - static PassRefPtr<ReferenceFilterOperation> create(const AtomicString& reference, OperationType type) + static PassRefPtr<ReferenceFilterOperation> create(const String& url, const String& fragment, OperationType type) { - return adoptRef(new ReferenceFilterOperation(reference, type)); + return adoptRef(new ReferenceFilterOperation(url, fragment, type)); } virtual PassRefPtr<FilterOperation> clone() const { - // AtomicString is thread-hostile, so we can't be cloned. + // Unimplemented return 0; } virtual bool affectsOpacity() const { return true; } virtual bool movesPixels() const { return true; } - const AtomicString& reference() const { return m_reference; } + 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; } private: @@ -170,16 +174,20 @@ private: if (!isSameType(o)) return false; const ReferenceFilterOperation* other = static_cast<const ReferenceFilterOperation*>(&o); - return m_reference == other->m_reference; + return m_url == other->m_url; } - ReferenceFilterOperation(const AtomicString& reference, OperationType type) + ReferenceFilterOperation(const String& url, const String& fragment, OperationType type) : FilterOperation(type) - , m_reference(reference) + , m_url(url) + , m_fragment(fragment) + , m_data(0) { } - AtomicString m_reference; + String m_url; + String m_fragment; + void* m_data; }; // 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 821bc6e67..c4b876593 100644 --- a/Source/WebCore/platform/graphics/filters/FilterOperations.cpp +++ b/Source/WebCore/platform/graphics/filters/FilterOperations.cpp @@ -98,6 +98,15 @@ bool FilterOperations::hasCustomFilter() const } #endif +bool FilterOperations::hasReferenceFilter() const +{ + for (size_t i = 0; i < m_operations.size(); ++i) { + if (m_operations.at(i)->getOperationType() == FilterOperation::REFERENCE) + return true; + } + return false; +} + bool FilterOperations::hasOutsets() const { for (size_t i = 0; i < m_operations.size(); ++i) { diff --git a/Source/WebCore/platform/graphics/filters/FilterOperations.h b/Source/WebCore/platform/graphics/filters/FilterOperations.h index be1b0a623..beb649b89 100644 --- a/Source/WebCore/platform/graphics/filters/FilterOperations.h +++ b/Source/WebCore/platform/graphics/filters/FilterOperations.h @@ -72,6 +72,7 @@ public: #if ENABLE(CSS_SHADERS) bool hasCustomFilter() const; #endif + bool hasReferenceFilter() const; private: Vector<RefPtr<FilterOperation> > m_operations; }; diff --git a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.cpp b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.cpp deleted file mode 100644 index 300369801..000000000 --- a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2011 University of Szeged - * Copyright (C) 2011 Zoltan Herczeg - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "FEGaussianBlurNEON.h" - -#if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC) - -#include <wtf/Alignment.h> - -namespace WebCore { - -static WTF_ALIGNED(unsigned char, s_FEGaussianBlurConstantsForNeon[], 16) = { - // Mapping from NEON to ARM registers. - 0, 4, 8, 12, 16, 16, 16, 16 -}; - -unsigned char* feGaussianBlurConstantsForNeon() -{ - return s_FEGaussianBlurConstantsForNeon; -} - -#define ASSTRING(str) #str -#define TOSTRING(value) ASSTRING(value) - -#define STRIDE_OFFSET TOSTRING(0) -#define STRIDE_WIDTH_OFFSET TOSTRING(4) -#define STRIDE_LINE_OFFSET TOSTRING(8) -#define STRIDE_LINE_WIDTH_OFFSET TOSTRING(12) -#define REMAINING_STRIDES_OFFSET TOSTRING(16) -#define DISTANCE_LEFT_OFFSET TOSTRING(20) -#define DISTANCE_RIGHT_OFFSET TOSTRING(24) -#define INVERTED_KERNEL_SIZE_OFFSET TOSTRING(28) -#define PAINTING_CONSTANTS_OFFSET TOSTRING(32) -#define NL "\n" - -// Register allocation. -#define SOURCE_R "r0" -#define DESTINATION_R "r1" -#define LEFT_R "r2" -#define RIGHT_R "r3" -#define SOURCE_END_R "r4" -#define DESTINATION_END_R "r5" -#define STRIDE_R "r6" -#define STRIDE_WIDTH_R "r7" -#define STRIDE_LINE_R "r8" -#define SOURCE_LINE_END_R "r10" -#define DISTANCE_LEFT_R "r11" -#define DISTANCE_RIGHT_R "r12" -#define MAX_KERNEL_SIZE_R "lr" - -// Alternate names. -#define INIT_INVERTED_KERNEL_SIZE_R SOURCE_END_R -#define INIT_PAINTING_CONSTANTS_R DESTINATION_END_R -#define INIT_SUM_R LEFT_R -#define REMAINING_STRIDES_R SOURCE_LINE_END_R - -#define INVERTED_KERNEL_SIZE_Q "q0" -#define SUM_Q "q1" -#define PIXEL_Q "q2" -#define PIXEL_D0 "d4" -#define PIXEL_D1 "d5" -#define PIXEL_D00 "d4[0]" -#define PIXEL_D01 "d4[1]" -#define PIXEL_S1 "s9" -#define PIXEL_D10 "d5[0]" -#define PIXEL_S2 "s10" -#define PIXEL_D11 "d5[1]" -#define REMAINING_STRIDES_S0 "s12" - -#define REMAP_NEON_ARM_Q "d16" - -asm ( // NOLINT -".globl " TOSTRING(neonDrawAllChannelGaussianBlur) NL -TOSTRING(neonDrawAllChannelGaussianBlur) ":" NL - "stmdb sp!, {r4-r8, r10, r11, lr}" NL - "ldr " STRIDE_R ", [r2, #" STRIDE_OFFSET "]" NL - "ldr " STRIDE_WIDTH_R ", [r2, #" STRIDE_WIDTH_OFFSET "]" NL - "ldr " DISTANCE_LEFT_R ", [r2, #" DISTANCE_LEFT_OFFSET "]" NL - "ldr " DISTANCE_RIGHT_R ", [r2, #" DISTANCE_RIGHT_OFFSET "]" NL - "ldr " STRIDE_LINE_R ", [r2, #" STRIDE_LINE_OFFSET "]" NL - "ldr " SOURCE_LINE_END_R ", [r2, #" STRIDE_LINE_WIDTH_OFFSET "]" NL - "ldr " INIT_INVERTED_KERNEL_SIZE_R ", [r2, #" INVERTED_KERNEL_SIZE_OFFSET "]" NL - "ldr " INIT_PAINTING_CONSTANTS_R ", [r2, #" PAINTING_CONSTANTS_OFFSET "]" NL - - // Initialize locals. - "mul " DISTANCE_LEFT_R ", " DISTANCE_LEFT_R ", " STRIDE_R NL - "mul " DISTANCE_RIGHT_R ", " DISTANCE_RIGHT_R ", " STRIDE_R NL - "mov " MAX_KERNEL_SIZE_R ", " DISTANCE_RIGHT_R NL - "cmp " MAX_KERNEL_SIZE_R ", " STRIDE_WIDTH_R NL - "movcs " MAX_KERNEL_SIZE_R ", " STRIDE_WIDTH_R NL - "add " SOURCE_LINE_END_R ", " SOURCE_LINE_END_R ", " SOURCE_R NL - "vdup.f32 " INVERTED_KERNEL_SIZE_Q ", " INIT_INVERTED_KERNEL_SIZE_R NL - "vld1.f32 { " REMAP_NEON_ARM_Q " }, [" INIT_PAINTING_CONSTANTS_R "]!" NL - -".allChannelMainLoop:" NL - - // Initialize the sum variable. - "vmov.u32 " SUM_Q ", #0" NL - "mov " INIT_SUM_R ", " SOURCE_R NL - "add " SOURCE_END_R ", " SOURCE_R ", " MAX_KERNEL_SIZE_R NL - "cmp " INIT_SUM_R ", " SOURCE_END_R NL - "bcs .allChannelInitSumDone" NL -".allChannelInitSum:" NL - "vld1.u32 " PIXEL_D00 ", [" INIT_SUM_R "], " STRIDE_R NL - "vmovl.u8 " PIXEL_Q ", " PIXEL_D0 NL - "vmovl.u16 " PIXEL_Q ", " PIXEL_D0 NL - "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL - "cmp " INIT_SUM_R ", " SOURCE_END_R NL - "bcc .allChannelInitSum" NL -".allChannelInitSumDone:" NL - - // Blurring. - "add " SOURCE_END_R ", " SOURCE_R ", " STRIDE_WIDTH_R NL - "add " DESTINATION_END_R ", " DESTINATION_R ", " STRIDE_WIDTH_R NL - "sub " LEFT_R ", " SOURCE_R ", " DISTANCE_LEFT_R NL - "add " RIGHT_R ", " SOURCE_R ", " DISTANCE_RIGHT_R NL - -".allChannelBlur:" NL - "vcvt.f32.u32 " PIXEL_Q ", " SUM_Q NL - "vmul.f32 " PIXEL_Q ", " PIXEL_Q ", " INVERTED_KERNEL_SIZE_Q NL - "vcvt.u32.f32 " PIXEL_Q ", " PIXEL_Q NL - "vtbl.8 " PIXEL_D0 ", {" PIXEL_D0 "-" PIXEL_D1 "}, " REMAP_NEON_ARM_Q NL - "vst1.u32 " PIXEL_D00 ", [" DESTINATION_R "], " STRIDE_R NL - - "cmp " LEFT_R ", " SOURCE_R NL - "bcc .allChannelSkipLeft" NL - "vld1.u32 " PIXEL_D00 ", [" LEFT_R "]" NL - "vmovl.u8 " PIXEL_Q ", " PIXEL_D0 NL - "vmovl.u16 " PIXEL_Q ", " PIXEL_D0 NL - "vsub.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL -".allChannelSkipLeft: " NL - - "cmp " RIGHT_R ", " SOURCE_END_R NL - "bcs .allChannelSkipRight" NL - "vld1.u32 " PIXEL_D00 ", [" RIGHT_R "]" NL - "vmovl.u8 " PIXEL_Q ", " PIXEL_D0 NL - "vmovl.u16 " PIXEL_Q ", " PIXEL_D0 NL - "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL -".allChannelSkipRight: " NL - - "add " LEFT_R ", " LEFT_R ", " STRIDE_R NL - "add " RIGHT_R ", " RIGHT_R ", " STRIDE_R NL - "cmp " DESTINATION_R ", " DESTINATION_END_R NL - "bcc .allChannelBlur" NL - "sub " DESTINATION_R ", " DESTINATION_R ", " STRIDE_WIDTH_R NL - - "add " SOURCE_R ", " SOURCE_R ", " STRIDE_LINE_R NL - "add " DESTINATION_R ", " DESTINATION_R ", " STRIDE_LINE_R NL - "cmp " SOURCE_R ", " SOURCE_LINE_END_R NL - "bcc .allChannelMainLoop" NL - - "ldmia sp!, {r4-r8, r10, r11, pc}" NL -); // NOLINT - -#define DATA_TRANSFER4(command, base) \ - command " " PIXEL_D00 ", [" base "], " STRIDE_LINE_R NL \ - command " " PIXEL_D01 ", [" base "], " STRIDE_LINE_R NL \ - command " " PIXEL_D10 ", [" base "], " STRIDE_LINE_R NL \ - command " " PIXEL_D11 ", [" base "], " STRIDE_LINE_R NL \ - "sub " base ", " base ", " STRIDE_LINE_R ", lsl #2" NL - -// The number of reads depend on REMAINING_STRIDES_R, but it is always >= 1 and <= 3 -#define CONDITIONAL_DATA_TRANSFER4(command1, command2, base) \ - command1 " " PIXEL_D00 ", [" base "], " STRIDE_LINE_R NL \ - "cmp " REMAINING_STRIDES_R ", #2" NL \ - command2 "cs " PIXEL_S1 ", [" base "]" NL \ - "add " base ", " base ", " STRIDE_LINE_R NL \ - "cmp " REMAINING_STRIDES_R ", #3" NL \ - command2 "cs " PIXEL_S2 ", [" base "]" NL \ - "sub " base ", " base ", " STRIDE_LINE_R ", lsl #1" NL - -asm ( // NOLINT -".globl " TOSTRING(neonDrawAlphaChannelGaussianBlur) NL -TOSTRING(neonDrawAlphaChannelGaussianBlur) ":" NL - "stmdb sp!, {r4-r8, r10, r11, lr}" NL - "ldr " STRIDE_R ", [r2, #" STRIDE_OFFSET "]" NL - "ldr " STRIDE_WIDTH_R ", [r2, #" STRIDE_WIDTH_OFFSET "]" NL - "ldr " DISTANCE_LEFT_R ", [r2, #" DISTANCE_LEFT_OFFSET "]" NL - "ldr " DISTANCE_RIGHT_R ", [r2, #" DISTANCE_RIGHT_OFFSET "]" NL - "ldr " STRIDE_LINE_R ", [r2, #" STRIDE_LINE_OFFSET "]" NL - "ldr " SOURCE_LINE_END_R ", [r2, #" STRIDE_LINE_WIDTH_OFFSET "]" NL - "ldr " INIT_INVERTED_KERNEL_SIZE_R ", [r2, #" INVERTED_KERNEL_SIZE_OFFSET "]" NL - "vldr.u32 " REMAINING_STRIDES_S0 ", [r2, #" REMAINING_STRIDES_OFFSET "]" NL - - // Initialize locals. - "mul " DISTANCE_LEFT_R ", " DISTANCE_LEFT_R ", " STRIDE_R NL - "mul " DISTANCE_RIGHT_R ", " DISTANCE_RIGHT_R ", " STRIDE_R NL - "mov " MAX_KERNEL_SIZE_R ", " DISTANCE_RIGHT_R NL - "cmp " MAX_KERNEL_SIZE_R ", " STRIDE_WIDTH_R NL - "movcs " MAX_KERNEL_SIZE_R ", " STRIDE_WIDTH_R NL - "add " SOURCE_LINE_END_R ", " SOURCE_LINE_END_R ", " SOURCE_R NL - "vdup.f32 " INVERTED_KERNEL_SIZE_Q ", " INIT_INVERTED_KERNEL_SIZE_R NL - "cmp " SOURCE_LINE_END_R ", " SOURCE_R NL - "beq .alphaChannelEarlyLeave" NL - - // Processing 4 strides parallelly. - -".alphaChannelMainLoop:" NL - - // Initialize the sum variable. - "vmov.u32 " SUM_Q ", #0" NL - "mov " INIT_SUM_R ", " SOURCE_R NL - "add " SOURCE_END_R ", " SOURCE_R ", " MAX_KERNEL_SIZE_R NL - "cmp " INIT_SUM_R ", " SOURCE_END_R NL - "bcs .alphaChannelInitSumDone" NL -".alphaChannelInitSum:" NL - DATA_TRANSFER4("vld1.u32", INIT_SUM_R) - "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL - "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL - "add " INIT_SUM_R ", " INIT_SUM_R ", " STRIDE_R NL - "cmp " INIT_SUM_R ", " SOURCE_END_R NL - "bcc .alphaChannelInitSum" NL -".alphaChannelInitSumDone:" NL - - // Blurring. - "add " SOURCE_END_R ", " SOURCE_R ", " STRIDE_WIDTH_R NL - "add " DESTINATION_END_R ", " DESTINATION_R ", " STRIDE_WIDTH_R NL - "sub " LEFT_R ", " SOURCE_R ", " DISTANCE_LEFT_R NL - "add " RIGHT_R ", " SOURCE_R ", " DISTANCE_RIGHT_R NL - -".alphaChannelBlur:" NL - "vcvt.f32.u32 " PIXEL_Q ", " SUM_Q NL - "vmul.f32 " PIXEL_Q ", " PIXEL_Q ", " INVERTED_KERNEL_SIZE_Q NL - "vcvt.u32.f32 " PIXEL_Q ", " PIXEL_Q NL - "vshl.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL - DATA_TRANSFER4("vst1.u32", DESTINATION_R) - - "cmp " LEFT_R ", " SOURCE_R NL - "bcc .alphaChannelSkipLeft" NL - DATA_TRANSFER4("vld1.u32", LEFT_R) - "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL - "vsub.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL -".alphaChannelSkipLeft: " NL - - "cmp " RIGHT_R ", " SOURCE_END_R NL - "bcs .alphaChannelSkipRight" NL - DATA_TRANSFER4("vld1.u32", RIGHT_R) - "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL - "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL -".alphaChannelSkipRight: " NL - - "add " DESTINATION_R ", " DESTINATION_R ", " STRIDE_R NL - "add " LEFT_R ", " LEFT_R ", " STRIDE_R NL - "add " RIGHT_R ", " RIGHT_R ", " STRIDE_R NL - "cmp " DESTINATION_R ", " DESTINATION_END_R NL - "bcc .alphaChannelBlur" NL - "sub " DESTINATION_R ", " DESTINATION_R ", " STRIDE_WIDTH_R NL - - "add " SOURCE_R ", " SOURCE_R ", " STRIDE_LINE_R ", lsl #2" NL - "add " DESTINATION_R ", " DESTINATION_R ", " STRIDE_LINE_R ", lsl #2" NL - "cmp " SOURCE_R ", " SOURCE_LINE_END_R NL - "bcc .alphaChannelMainLoop" NL - - // Processing the remaining strides (0 - 3). -".alphaChannelEarlyLeave:" NL - "vmov.u32 " REMAINING_STRIDES_R ", " REMAINING_STRIDES_S0 NL - // Early return for 0 strides. - "cmp " REMAINING_STRIDES_R ", #0" NL - "ldmeqia sp!, {r4-r8, r10, r11, pc}" NL - - // Initialize the sum variable. - "vmov.u32 " SUM_Q ", #0" NL - "mov " INIT_SUM_R ", " SOURCE_R NL - "add " SOURCE_END_R ", " SOURCE_R ", " MAX_KERNEL_SIZE_R NL - "cmp " INIT_SUM_R ", " SOURCE_END_R NL - "bcs .alphaChannelSecondInitSumDone" NL -".alphaChannelSecondInitSum:" NL - CONDITIONAL_DATA_TRANSFER4("vld1.u32", "vldr", INIT_SUM_R) - "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL - "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL - "add " INIT_SUM_R ", " INIT_SUM_R ", " STRIDE_R NL - "cmp " INIT_SUM_R ", " SOURCE_END_R NL - "bcc .alphaChannelSecondInitSum" NL -".alphaChannelSecondInitSumDone:" NL - - // Blurring. - "add " SOURCE_END_R ", " SOURCE_R ", " STRIDE_WIDTH_R NL - "add " DESTINATION_END_R ", " DESTINATION_R ", " STRIDE_WIDTH_R NL - "sub " LEFT_R ", " SOURCE_R ", " DISTANCE_LEFT_R NL - "add " RIGHT_R ", " SOURCE_R ", " DISTANCE_RIGHT_R NL - -".alphaChannelSecondBlur:" NL - "vcvt.f32.u32 " PIXEL_Q ", " SUM_Q NL - "vmul.f32 " PIXEL_Q ", " PIXEL_Q ", " INVERTED_KERNEL_SIZE_Q NL - "vcvt.u32.f32 " PIXEL_Q ", " PIXEL_Q NL - "vshl.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL - CONDITIONAL_DATA_TRANSFER4("vst1.u32", "vstr", DESTINATION_R) - - "cmp " LEFT_R ", " SOURCE_R NL - "bcc .alphaChannelSecondSkipLeft" NL - CONDITIONAL_DATA_TRANSFER4("vld1.u32", "vldr", LEFT_R) - "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL - "vsub.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL -".alphaChannelSecondSkipLeft: " NL - - "cmp " RIGHT_R ", " SOURCE_END_R NL - "bcs .alphaChannelSecondSkipRight" NL - CONDITIONAL_DATA_TRANSFER4("vld1.u32", "vldr", RIGHT_R) - "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL - "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL -".alphaChannelSecondSkipRight: " NL - - "add " DESTINATION_R ", " DESTINATION_R ", " STRIDE_R NL - "add " LEFT_R ", " LEFT_R ", " STRIDE_R NL - "add " RIGHT_R ", " RIGHT_R ", " STRIDE_R NL - "cmp " DESTINATION_R ", " DESTINATION_END_R NL - "bcc .alphaChannelSecondBlur" NL - - "ldmia sp!, {r4-r8, r10, r11, pc}" NL -); // NOLINT - -} // namespace WebCore - -#endif // CPU(ARM_NEON) && COMPILER(GCC) diff --git a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h index a2fb0bd44..93b46cfd3 100644 --- a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h +++ b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h @@ -29,88 +29,51 @@ #include <wtf/Platform.h> -#if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC) +#if ENABLE(FILTERS) && HAVE(ARM_NEON_INTRINSICS) #include "FEGaussianBlur.h" +#include "NEONHelpers.h" namespace WebCore { -struct FEGaussianBlurPaintingDataForNeon { - int stride; - int strideWidth; - int strideLine; - int strideLineWidth; - int remainingStrides; - int distanceLeft; - int distanceRight; - float invertedKernelSize; - unsigned char* paintingConstants; -}; - -unsigned char* feGaussianBlurConstantsForNeon(); - -extern "C" { -void neonDrawAllChannelGaussianBlur(unsigned char* source, unsigned char* destination, FEGaussianBlurPaintingDataForNeon*); -void neonDrawAlphaChannelGaussianBlur(unsigned char* source, unsigned char* destination, FEGaussianBlurPaintingDataForNeon*); -} - -inline void FEGaussianBlur::platformApplyNeon(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize) +inline void boxBlurNEON(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dstPixelArray, + unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight) { - const int widthMultipliedByFour = 4 * paintSize.width(); - FEGaussianBlurPaintingDataForNeon argumentsX = { - 4, - widthMultipliedByFour, - widthMultipliedByFour, - (isAlphaImage() ? ((paintSize.height() >> 2) << 2) : paintSize.height()) * widthMultipliedByFour, - isAlphaImage() ? (paintSize.height() & 0x3) : 0, - 0, - 0, - 0, - isAlphaImage() ? 0 : feGaussianBlurConstantsForNeon() - }; - FEGaussianBlurPaintingDataForNeon argumentsY = { - widthMultipliedByFour, - widthMultipliedByFour * paintSize.height(), - 4, - (isAlphaImage() ? ((paintSize.width() >> 2) << 2) : paintSize.width()) * 4, - isAlphaImage() ? (paintSize.width() & 0x3) : 0, - 0, - 0, - 0, - isAlphaImage() ? 0 : feGaussianBlurConstantsForNeon() - }; + uint32_t* sourcePixel = reinterpret_cast<uint32_t*>(srcPixelArray->data()); + uint32_t* destinationPixel = reinterpret_cast<uint32_t*>(dstPixelArray->data()); + + float32x4_t deltaX = vdupq_n_f32(1.0 / dx); + int pixelLine = strideLine / 4; - for (int i = 0; i < 3; ++i) { - if (kernelSizeX) { - kernelPosition(i, kernelSizeX, argumentsX.distanceLeft, argumentsX.distanceRight); - argumentsX.invertedKernelSize = 1 / static_cast<float>(kernelSizeX); - if (isAlphaImage()) - neonDrawAlphaChannelGaussianBlur(srcPixelArray->data(), tmpPixelArray->data(), &argumentsX); - else - neonDrawAllChannelGaussianBlur(srcPixelArray->data(), tmpPixelArray->data(), &argumentsX); - } else { - Uint8ClampedArray* auxPixelArray = tmpPixelArray; - tmpPixelArray = srcPixelArray; - srcPixelArray = auxPixelArray; + for (int y = 0; y < effectHeight; ++y) { + int line = y * pixelLine; + float32x4_t sum = vdupq_n_f32(0); + // Fill the kernel + int maxKernelSize = std::min(dxRight, effectWidth); + for (int i = 0; i < maxKernelSize; ++i) { + float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + line + i); + sum = vaddq_f32(sum, sourcePixelAsFloat); } - if (kernelSizeY) { - kernelPosition(i, kernelSizeY, argumentsY.distanceLeft, argumentsY.distanceRight); - argumentsY.invertedKernelSize = 1 / static_cast<float>(kernelSizeY); - if (isAlphaImage()) - neonDrawAlphaChannelGaussianBlur(tmpPixelArray->data(), srcPixelArray->data(), &argumentsY); - else - neonDrawAllChannelGaussianBlur(tmpPixelArray->data(), srcPixelArray->data(), &argumentsY); - } else { - Uint8ClampedArray* auxPixelArray = tmpPixelArray; - tmpPixelArray = srcPixelArray; - srcPixelArray = auxPixelArray; + // Blurring + for (int x = 0; x < effectWidth; ++x) { + int pixelOffset = line + x; + float32x4_t result = vmulq_f32(sum, deltaX); + storeFloatAsRGBA8(result, destinationPixel+pixelOffset); + if (x >= dxLeft) { + float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + pixelOffset - dxLeft); + sum = vsubq_f32(sum, sourcePixelAsFloat); + } + if (x + dxRight < effectWidth) { + float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + pixelOffset + dxRight); + sum = vaddq_f32(sum, sourcePixelAsFloat); + } } } } } // namespace WebCore -#endif // CPU(ARM_NEON) && COMPILER(GCC) +#endif // ENABLE(FILTERS) && HAVE(ARM_NEON_INTRINSICS) #endif // FEGaussianBlurNEON_h diff --git a/Source/WebCore/platform/graphics/filters/arm/NEONHelpers.h b/Source/WebCore/platform/graphics/filters/arm/NEONHelpers.h new file mode 100644 index 000000000..78a32418e --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/arm/NEONHelpers.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 University of Szeged + * Copyright (C) 2012 Gabor Rapcsanyi + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NEONHelpers_h +#define NEONHelpers_h + +#include <wtf/Platform.h> + +#if ENABLE(FILTERS) && HAVE(ARM_NEON_INTRINSICS) + +#include <arm_neon.h> + +namespace WebCore { + +inline float32x4_t loadRGBA8AsFloat(uint32_t* source) +{ + uint32x2_t temporary1 = vset_lane_u32(*source, temporary1, 0); + uint16x4_t temporary2 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(temporary1))); + return vcvtq_f32_u32(vmovl_u16(temporary2)); +} + +inline void storeFloatAsRGBA8(float32x4_t data, uint32_t* destination) +{ + uint16x4_t temporary1 = vmovn_u32(vcvtq_u32_f32(data)); + uint8x8_t temporary2 = vmovn_u16(vcombine_u16(temporary1, temporary1)); + *destination = vget_lane_u32(vreinterpret_u32_u8(temporary2), 0); +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) && HAVE(ARM_NEON_INTRINSICS) + +#endif // NEONHelpers_h diff --git a/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp b/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp index 194a5aae5..9496fc91a 100644 --- a/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp +++ b/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp @@ -311,7 +311,7 @@ void GLContextGLX::swapBuffers() glXSwapBuffers(sharedDisplay(), m_window); } -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) PlatformGraphicsContext3D GLContextGLX::platformContext() { return m_context; @@ -320,4 +320,4 @@ PlatformGraphicsContext3D GLContextGLX::platformContext() } // namespace WebCore -#endif // ENABLE(WEBGL) || && USE(TEXTURE_MAPPER_GL) +#endif // USE(GLX) diff --git a/Source/WebCore/platform/graphics/glx/GLContextGLX.h b/Source/WebCore/platform/graphics/glx/GLContextGLX.h index 118edd41d..5e8c61ce4 100644 --- a/Source/WebCore/platform/graphics/glx/GLContextGLX.h +++ b/Source/WebCore/platform/graphics/glx/GLContextGLX.h @@ -48,7 +48,7 @@ public: virtual bool canRenderToDefaultFramebuffer(); virtual IntSize defaultFrameBufferSize(); -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) virtual PlatformGraphicsContext3D platformContext(); #endif diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp index c58c3c6a7..fe51104f0 100644 --- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp +++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp @@ -30,7 +30,7 @@ #include "config.h" -#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(WEBGL) +#if ENABLE(ACCELERATED_2D_CANVAS) || USE(3D_GRAPHICS) #include "DrawingBuffer.h" diff --git a/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm b/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm index 5154fd715..40dc2a51e 100644 --- a/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm +++ b/Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm @@ -25,7 +25,7 @@ #include "config.h" -#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(WEBGL) +#if ENABLE(ACCELERATED_2D_CANVAS) || USE(3D_GRAPHICS) #include "DrawingBuffer.h" diff --git a/Source/WebCore/platform/graphics/gpu/qt/DrawingBufferQt.cpp b/Source/WebCore/platform/graphics/gpu/qt/DrawingBufferQt.cpp index 23d28b2fa..17a59a418 100644 --- a/Source/WebCore/platform/graphics/gpu/qt/DrawingBufferQt.cpp +++ b/Source/WebCore/platform/graphics/gpu/qt/DrawingBufferQt.cpp @@ -25,7 +25,7 @@ #include "config.h" -#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "DrawingBuffer.h" diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index e9d1bc119..f2b86b27e 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -495,6 +495,9 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const if (!hasVideo()) return IntSize(); + if (!m_videoSize.isEmpty()) + return m_videoSize; + GstCaps* caps = webkitGstGetPadCaps(m_videoSinkPad.get()); if (!caps) return IntSize(); @@ -542,7 +545,8 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const } LOG_VERBOSE(Media, "Natural size: %" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, width, height); - return IntSize(static_cast<int>(width), static_cast<int>(height)); + m_videoSize = IntSize(static_cast<int>(width), static_cast<int>(height)); + return m_videoSize; } void MediaPlayerPrivateGStreamer::videoChanged() @@ -561,6 +565,9 @@ void MediaPlayerPrivateGStreamer::notifyPlayerOfVideo() g_object_get(m_playBin, "n-video", &videoTracks, NULL); m_hasVideo = videoTracks > 0; + + m_videoSize = IntSize(); + m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player); } @@ -1719,9 +1726,13 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin() g_object_set(m_fpsSink, "silent", TRUE , NULL); // Turn off text overlay unless logging is enabled. +#if LOG_DISABLED + g_object_set(m_fpsSink, "text-overlay", FALSE , NULL); +#else WTFLogChannel* channel = getChannelFromName("Media"); if (channel->state != WTFLogChannelOn) g_object_set(m_fpsSink, "text-overlay", FALSE , NULL); +#endif // LOG_DISABLED if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_fpsSink), "video-sink")) { g_object_set(m_fpsSink, "video-sink", m_webkitVideoSink, NULL); diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h index 506942c2b..9e277ccf2 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h @@ -194,6 +194,7 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface { guint m_videoTimerHandler; GRefPtr<GstElement> m_webkitAudioSink; GRefPtr<GstPad> m_videoSinkPad; + mutable IntSize m_videoSize; }; } diff --git a/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp b/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp index ba46c7f02..9191d9df6 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp @@ -80,6 +80,11 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru m_item.string = m_normalizedBuffer.get(); m_item.stringLength = m_normalizedBufferLength; +#if OS(ANDROID) + // Kerning does not currently work on Android. + m_item.shaperFlags = HB_ShaperFlag_NoKerning; +#endif + reset(startingX); m_startingY = startingY; @@ -209,29 +214,41 @@ const FontPlatformData* ComplexTextController::getComplexFontPlatformData() case HB_Script_Arabic: fallbackScript = kArabic_FallbackScript; break; + case HB_Script_Armenian: + fallbackScript = kArmenian_FallbackScript; + break; + case HB_Script_Bengali: + fallbackScript = kBengali_FallbackScript; + break; + case HB_Script_Devanagari: + fallbackScript = kDevanagari_FallbackScript; + break; + case HB_Script_Georgian: + fallbackScript = kGeorgian_FallbackScript; + break; case HB_Script_Hebrew: if (m_font->fontDescription().weight() >= FontWeightBold) fallbackScript = kHebrewBold_FallbackScript; else fallbackScript = kHebrewRegular_FallbackScript; break; - case HB_Script_Thai: - fallbackScript = kThai_FallbackScript; - break; - case HB_Script_Armenian: - fallbackScript = kArmenian_FallbackScript; + case HB_Script_Kannada: + fallbackScript = kKannada_FallbackScript; break; - case HB_Script_Georgian: - fallbackScript = kGeorgian_FallbackScript; + case HB_Script_Malayalam: + fallbackScript = kMalayalam_FallbackScript; break; - case HB_Script_Devanagari: - fallbackScript = kDevanagari_FallbackScript; + case HB_Script_Tamil: + if (m_font->fontDescription().weight() >= FontWeightBold) + fallbackScript = kTamilBold_FallbackScript; + else + fallbackScript = kTamilRegular_FallbackScript; break; - case HB_Script_Bengali: - fallbackScript = kBengali_FallbackScript; + case HB_Script_Telugu: + fallbackScript = kTelugu_FallbackScript; break; - case HB_Script_Tamil: - fallbackScript = kTamil_FallbackScript; + case HB_Script_Thai: + fallbackScript = kThai_FallbackScript; break; default: return 0; diff --git a/Source/WebCore/platform/graphics/harfbuzz/FontHarfBuzz.cpp b/Source/WebCore/platform/graphics/harfbuzz/FontHarfBuzz.cpp index 9370f676b..cc8efeb43 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/FontHarfBuzz.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/FontHarfBuzz.cpp @@ -31,11 +31,16 @@ #include "config.h" #include "Font.h" +#if USE(HARFBUZZ_NG) +#include "HarfBuzzShaper.h" +#else #include "ComplexTextControllerHarfBuzz.h" +#include "HarfBuzzSkia.h" +#endif + #include "FloatRect.h" #include "GlyphBuffer.h" #include "GraphicsContext.h" -#include "HarfBuzzSkia.h" #include "NotImplemented.h" #include "PlatformContextSkia.h" #include "SimpleFontData.h" @@ -158,7 +163,6 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run, if (!run.length()) return; - SkCanvas* canvas = gc->platformContext()->canvas(); TextDrawingModeFlags textMode = gc->platformContext()->getTextDrawingMode(); bool fill = textMode & TextModeFill; bool stroke = (textMode & TextModeStroke) @@ -178,6 +182,14 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run, setupForTextPainting(&strokePaint, gc->strokeColor().rgb()); } +#if USE(HARFBUZZ_NG) + GlyphBuffer glyphBuffer; + HarfBuzzShaper shaper(this, run); + if (!shaper.shape(&glyphBuffer)) + return; + drawGlyphBuffer(gc, run, glyphBuffer, point); +#else + SkCanvas* canvas = gc->platformContext()->canvas(); ComplexTextController controller(this, run, point.x(), point.y()); if (run.rtl()) controller.setupForRTL(); @@ -201,6 +213,7 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run, canvas->drawPosText(controller.glyphs() + fromGlyph, glyphLength << 1, controller.positions() + fromGlyph, strokePaint); } } +#endif } void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const @@ -210,8 +223,15 @@ void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const { +#if USE(HARFBUZZ_NG) + HarfBuzzShaper shaper(this, run); + if (!shaper.shape()) + return 0; + return shaper.totalWidth(); +#else ComplexTextController controller(this, run, 0, 0); return controller.widthOfFullRun(); +#endif } // Return the code point index for the given |x| offset into the text run. @@ -222,12 +242,19 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem. int targetX = static_cast<int>(xFloat); +#if USE(HARFBUZZ_NG) + HarfBuzzShaper shaper(this, run); + if (!shaper.shape()) + return 0; + return shaper.offsetForPosition(targetX); +#else // (Mac code ignores includePartialGlyphs, and they don't know what it's // supposed to do, so we just ignore it as well.) ComplexTextController controller(this, run, 0, 0); if (run.rtl()) controller.setupForRTL(); return controller.offsetForPosition(targetX); +#endif } // Return the rectangle for selecting the given range of code-points in the TextRun. @@ -235,10 +262,17 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int height, int from, int to) const { +#if USE(HARFBUZZ_NG) + HarfBuzzShaper shaper(this, run); + if (!shaper.shape()) + return FloatRect(); + return shaper.selectionRect(point, height, from, to); +#else ComplexTextController controller(this, run, 0, 0); if (run.rtl()) controller.setupForRTL(); return controller.selectionRect(point, height, from, to); +#endif } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp b/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp index 54df77063..695531cc1 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp @@ -251,6 +251,15 @@ bool FontPlatformData::isFixedPitch() const return false; } +#if USE(HARFBUZZ_NG) +HarfBuzzFace* FontPlatformData::harfbuzzFace() const +{ + if (!m_harfbuzzFace) + m_harfbuzzFace = HarfBuzzFace::create(const_cast<FontPlatformData*>(this), uniqueID()); + + return m_harfbuzzFace.get(); +} +#else HarfbuzzFace* FontPlatformData::harfbuzzFace() const { if (!m_harfbuzzFace) @@ -258,21 +267,10 @@ HarfbuzzFace* FontPlatformData::harfbuzzFace() const return m_harfbuzzFace.get(); } +#endif void FontPlatformData::querySystemForRenderStyle() { - if (!m_family.length()) { - // We don't have a family for this, probably because it's a webfont. We - // set all the values to 'no preference' and take the system defaults. - m_style.useBitmaps = FontRenderStyle::NoPreference; - m_style.useAutoHint = FontRenderStyle::NoPreference; - m_style.useHinting = FontRenderStyle::NoPreference; - m_style.useAntiAlias = FontRenderStyle::NoPreference; - m_style.useSubpixelRendering = FontRenderStyle::NoPreference; - m_style.useSubpixelPositioning = FontRenderStyle::NoPreference; - return; - } - PlatformSupport::getRenderStyleForStrike(m_family.data(), (((int)m_textSize) << 2) | (m_typeface->style() & 3), &m_style); } diff --git a/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.h b/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.h index 246a7a49c..b4423f400 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.h +++ b/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.h @@ -33,7 +33,11 @@ #include "FontOrientation.h" #include "FontRenderStyle.h" +#if USE(HARFBUZZ_NG) +#include "HarfBuzzFace.h" +#else #include "HarfBuzzSkia.h" +#endif #include "SkPaint.h" #include "TextOrientation.h" #include <wtf/Forward.h> @@ -128,7 +132,12 @@ public: String description() const; #endif +#if USE(HARFBUZZ_NG) + // FIXME: Rename this like "harfbuzzNGFace()" because difference is too subtle. + HarfBuzzFace* harfbuzzFace() const; +#else HarfbuzzFace* harfbuzzFace() const; +#endif // ------------------------------------------------------------------------- // Global font preferences... @@ -153,7 +162,11 @@ private: FontOrientation m_orientation; TextOrientation m_textOrientation; FontRenderStyle m_style; +#if USE(HARFBUZZ_NG) + mutable RefPtr<HarfBuzzFace> m_harfbuzzFace; +#else mutable RefPtr<HarfbuzzFace> m_harfbuzzFace; +#endif SkTypeface* hashTableDeletedFontValue() const { return reinterpret_cast<SkTypeface*>(-1); } }; diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzFaceCoreText.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzFaceCoreText.cpp index 6209e704b..966589db9 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzFaceCoreText.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzFaceCoreText.cpp @@ -109,8 +109,10 @@ static void releaseTableData(void* userData) static hb_blob_t* harfbuzzCoreTextGetTable(hb_face_t* face, hb_tag_t tag, void* userData) { FontPlatformData* platformData = reinterpret_cast<FontPlatformData*>(userData); - CTFontRef ctFont = platformData->ctFont(); - CFDataRef cfData = CTFontCopyTable(ctFont, tag, kCTFontTableOptionNoOptions); + // It seems that CTFontCopyTable of MacOSX10.5 sdk doesn't work for + // OpenType layout tables(GDEF, GSUB, GPOS). Use CGFontCopyTableForTag instead. + CGFontRef cgFont = platformData->cgFont(); + CFDataRef cfData = CGFontCopyTableForTag(cgFont, tag); if (!cfData) return 0; diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzFaceSkia.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzFaceSkia.cpp new file mode 100644 index 000000000..f29bdb91d --- /dev/null +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzFaceSkia.cpp @@ -0,0 +1,187 @@ +/* + * 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HarfBuzzFace.h" + +#include "FontPlatformData.h" +#include "GlyphBuffer.h" +#include "HarfBuzzShaper.h" +#include "SimpleFontData.h" +#include "SkFontHost.h" +#include "SkPaint.h" +#include "SkPath.h" +#include "SkPoint.h" +#include "SkRect.h" +#include "SkUtils.h" + +#include "hb.h" + +namespace WebCore { + +// Our implementation of the callbacks which Harfbuzz requires by using Skia +// calls. See the Harfbuzz source for references about what these callbacks do. + +static hb_position_t SkiaScalarToHarfbuzzPosition(SkScalar value) +{ + return SkScalarToFixed(value); +} + +static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint, hb_position_t* width, hb_glyph_extents_t* extents) +{ + if (codepoint > 0xFFFF) + return; + paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); + + SkScalar skWidth; + SkRect skBounds; + uint16_t glyph = codepoint; + + paint->getTextWidths(&glyph, sizeof(glyph), &skWidth, &skBounds); + if (width) + *width = SkiaScalarToHarfbuzzPosition(skWidth); + if (extents) { + extents->x_bearing = SkiaScalarToHarfbuzzPosition(skBounds.fLeft); + // The extents are unused in harfbuzz now so we're unsure whether a negation is needed here. Revisit when we're sure. + extents->y_bearing = SkiaScalarToHarfbuzzPosition(skBounds.fTop); + extents->width = SkiaScalarToHarfbuzzPosition(skBounds.width()); + extents->height = SkiaScalarToHarfbuzzPosition(skBounds.height()); + } +} + +static hb_bool_t harfbuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoint_t unicode, hb_codepoint_t variationSelector, hb_codepoint_t* glyph, void* userData) +{ + SkPaint* paint = reinterpret_cast<SkPaint*>(fontData); + + paint->setTextEncoding(SkPaint::kUTF16_TextEncoding); + uint16_t text[4]; + size_t length = SkUTF16_FromUnichar(unicode, text); + uint16_t glyph16; + paint->textToGlyphs(text, length, &glyph16); + *glyph = glyph16; + return !!*glyph; +} + +static hb_position_t harfbuzzGetGlyphHorizontalAdvance(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, void* userData) +{ + SkPaint* paint = reinterpret_cast<SkPaint*>(fontData); + hb_position_t advance = 0; + + SkiaGetGlyphWidthAndExtents(paint, glyph, &advance, 0); + return advance; +} + +static hb_bool_t harfbuzzGetGlyphHorizontalOrigin(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, hb_position_t* x, hb_position_t* y, void* userData) +{ + // Just return true, following the way that Harfbuzz-FreeType + // implementation does. + return true; +} + +static hb_bool_t harfbuzzGetGlyphExtents(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, hb_glyph_extents_t* extents, void* userData) +{ + SkPaint* paint = reinterpret_cast<SkPaint*>(fontData); + + SkiaGetGlyphWidthAndExtents(paint, glyph, 0, extents); + return true; +} + +static hb_font_funcs_t* harfbuzzSkiaGetFontFuncs() +{ + static hb_font_funcs_t* harfbuzzSkiaFontFuncs = 0; + + // We don't set callback functions which we can't support. + // Harfbuzz will use the fallback implementation if they aren't set. + if (!harfbuzzSkiaFontFuncs) { + harfbuzzSkiaFontFuncs = hb_font_funcs_create(); + hb_font_funcs_set_glyph_func(harfbuzzSkiaFontFuncs, harfbuzzGetGlyph, 0, 0); + hb_font_funcs_set_glyph_h_advance_func(harfbuzzSkiaFontFuncs, harfbuzzGetGlyphHorizontalAdvance, 0, 0); + hb_font_funcs_set_glyph_h_origin_func(harfbuzzSkiaFontFuncs, harfbuzzGetGlyphHorizontalOrigin, 0, 0); + hb_font_funcs_set_glyph_extents_func(harfbuzzSkiaFontFuncs, harfbuzzGetGlyphExtents, 0, 0); + hb_font_funcs_make_immutable(harfbuzzSkiaFontFuncs); + } + return harfbuzzSkiaFontFuncs; +} + +static hb_blob_t* harfbuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* userData) +{ + FontPlatformData* font = reinterpret_cast<FontPlatformData*>(userData); + + const size_t tableSize = SkFontHost::GetTableSize(font->uniqueID(), tag); + if (!tableSize) + return 0; + + char* buffer = reinterpret_cast<char*>(fastMalloc(tableSize)); + if (!buffer) + return 0; + size_t actualSize = SkFontHost::GetTableData(font->uniqueID(), tag, 0, tableSize, buffer); + if (tableSize != actualSize) { + fastFree(buffer); + return 0; + } + + return hb_blob_create(const_cast<char*>(buffer), tableSize, + HB_MEMORY_MODE_WRITABLE, buffer, fastFree); +} + +static void destroyPaint(void* userData) +{ + SkPaint* paint = reinterpret_cast<SkPaint*>(userData); + delete paint; +} + +hb_face_t* HarfBuzzFace::createFace() +{ + hb_face_t* face = hb_face_create_for_tables(harfbuzzSkiaGetTable, m_platformData, 0); + ASSERT(face); + return face; +} + +hb_font_t* HarfBuzzFace::createFont() +{ + hb_font_t* font = hb_font_create(m_face); + SkPaint* paint = new SkPaint; + m_platformData->setupPaint(paint); + hb_font_set_funcs(font, harfbuzzSkiaGetFontFuncs(), paint, destroyPaint); + float size = m_platformData->size(); + if (floorf(size) == size) + hb_font_set_ppem(font, size, size); + int scale = SkiaScalarToHarfbuzzPosition(size); + hb_font_set_scale(font, scale, scale); + hb_font_make_immutable(font); + return font; +} + +GlyphBufferAdvance HarfBuzzShaper::createGlyphBufferAdvance(float width, float height) +{ + return GlyphBufferAdvance(width, height); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp index 6614adbde..a9324d37f 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -208,7 +208,7 @@ static bool advanceByCombiningCharacterSequence(const UChar*& iterator, const UC UChar32 nextCharacter; int markLength = 0; U16_NEXT(iterator, markLength, end - iterator, nextCharacter); - if (!(U_GET_GC_MASK(nextCharacter) & U_GC_M_MASK) && nextCharacter != zeroWidthJoiner && nextCharacter != zeroWidthNonJoiner) + if (!(U_GET_GC_MASK(nextCharacter) & U_GC_M_MASK)) break; markCount += markLength; iterator += markLength; @@ -284,13 +284,17 @@ void ComplexTextController::collectComplexTextRuns() } nextIsMissingGlyph = false; + if (baseCharacter == zeroWidthJoiner) + nextFontData = fontData; #if !PLATFORM(WX) - nextFontData = m_font.fontDataForCombiningCharacterSequence(cp + index, curr - cp - index, nextIsSmallCaps ? SmallCapsVariant : NormalVariant); - if (!nextFontData) { - if (markCount) - nextFontData = systemFallbackFontData(); - else - nextIsMissingGlyph = true; + else { + nextFontData = m_font.fontDataForCombiningCharacterSequence(cp + index, curr - cp - index, nextIsSmallCaps ? SmallCapsVariant : NormalVariant); + if (!nextFontData) { + if (markCount) + nextFontData = systemFallbackFontData(); + else + nextIsMissingGlyph = true; + } } #endif diff --git a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp index 98a53f9f1..45a6691b8 100644 --- a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp +++ b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp @@ -68,11 +68,14 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b } } else if (!fontData->platformData().isCompositeFontReference() && ((fontData->platformData().widthVariant() == RegularWidth) ? wkGetVerticalGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength) : CTFontGetGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength))) { + // When buffer consists of surrogate pairs, wkGetVerticalGlyphsForCharacters and CTFontGetGlyphsForCharacters + // place the glyphs at indices corresponding to the first character of each pair. + unsigned glyphStep = bufferLength / length; for (unsigned i = 0; i < length; ++i) { - if (!glyphs[i]) + if (!glyphs[i * glyphStep]) setGlyphDataForIndex(offset + i, 0, 0); else { - setGlyphDataForIndex(offset + i, glyphs[i], fontData); + setGlyphDataForIndex(offset + i, glyphs[i * glyphStep], fontData); haveGlyphs = true; } } diff --git a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index cd01522ef..d042c660c 100644 --- a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -25,7 +25,7 @@ #include "config.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "GraphicsContext3D.h" @@ -282,6 +282,12 @@ void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback> { } +void GraphicsContext3D::releaseShaderCompiler() +{ + makeContextCurrent(); + notImplemented(); +} + } -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm index b5ee110e2..9736e74dc 100644 --- a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm +++ b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm @@ -50,6 +50,11 @@ using namespace WebCore; return YES; } ++ (unsigned int)prefetchedTiles +{ + return 2; +} + // Disable default animations - (id<CAAction>)actionForKey:(NSString *)key { diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp index 4aa341c32..9319ff8d3 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp @@ -25,7 +25,7 @@ #include "config.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "Extensions3DOpenGL.h" @@ -42,8 +42,7 @@ namespace WebCore { Extensions3DOpenGL::Extensions3DOpenGL(GraphicsContext3D* context) - : m_initializedAvailableExtensions(false) - , m_context(context) + : Extensions3DOpenGLCommon(context) { } @@ -51,91 +50,6 @@ Extensions3DOpenGL::~Extensions3DOpenGL() { } -bool Extensions3DOpenGL::supports(const String& name) -{ - // Note on support for BGRA: - // - // For OpenGL ES2.0, requires checking for - // GL_EXT_texture_format_BGRA8888 and GL_EXT_read_format_bgra. - // For desktop GL, BGRA has been supported since OpenGL 1.2. - // - // However, note that the GL ES2 extension requires the - // internalFormat to glTexImage2D() be GL_BGRA, while desktop GL - // will not accept GL_BGRA (must be GL_RGBA), so this must be - // checked on each platform. Desktop GL offers neither - // GL_EXT_texture_format_BGRA8888 or GL_EXT_read_format_bgra, so - // treat them as unsupported here. - if (!m_initializedAvailableExtensions) { - String extensionsString(reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS))); - Vector<String> availableExtensions; - extensionsString.split(" ", availableExtensions); - for (size_t i = 0; i < availableExtensions.size(); ++i) - m_availableExtensions.add(availableExtensions[i]); - m_initializedAvailableExtensions = true; - } - - // GL_ANGLE_framebuffer_blit and GL_ANGLE_framebuffer_multisample are "fake". They are implemented using other - // extensions. In particular GL_EXT_framebuffer_blit and GL_EXT_framebuffer_multisample - if (name == "GL_ANGLE_framebuffer_blit") - return m_availableExtensions.contains("GL_EXT_framebuffer_blit"); - if (name == "GL_ANGLE_framebuffer_multisample") - return m_availableExtensions.contains("GL_EXT_framebuffer_multisample"); - - // Desktop GL always supports GL_OES_rgb8_rgba8. - if (name == "GL_OES_rgb8_rgba8") - return true; - - // If GL_ARB_texture_float is available then we report GL_OES_texture_float and - // GL_OES_texture_half_float as available. - if (name == "GL_OES_texture_float" || name == "GL_OES_texture_half_float") - return m_availableExtensions.contains("GL_ARB_texture_float"); - - // GL_OES_vertex_array_object - if (name == "GL_OES_vertex_array_object") - return m_availableExtensions.contains("GL_APPLE_vertex_array_object"); - - // Desktop GL always supports the standard derivative functions - if (name == "GL_OES_standard_derivatives") - return true; - - if (name == "GL_EXT_texture_filter_anisotropic") - return m_availableExtensions.contains("GL_EXT_texture_filter_anisotropic"); - - return m_availableExtensions.contains(name); -} - -void Extensions3DOpenGL::ensureEnabled(const String& name) -{ -#if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK) - if (name == "GL_OES_standard_derivatives") { - // Enable support in ANGLE (if not enabled already) - ANGLEWebKitBridge& compiler = m_context->m_compiler; - ShBuiltInResources ANGLEResources = compiler.getResources(); - if (!ANGLEResources.OES_standard_derivatives) { - ANGLEResources.OES_standard_derivatives = 1; - compiler.setResources(ANGLEResources); - } - } -#else - ASSERT_UNUSED(name, supports(name)); -#endif -} - -bool Extensions3DOpenGL::isEnabled(const String& name) -{ -#if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK) - if (name == "GL_OES_standard_derivatives") { - ANGLEWebKitBridge& compiler = m_context->m_compiler; - return compiler.getResources().OES_standard_derivatives; - } -#endif - return supports(name); -} - -int Extensions3DOpenGL::getGraphicsResetStatusARB() -{ - return GraphicsContext3D::NO_ERROR; -} void Extensions3DOpenGL::blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) { @@ -194,19 +108,49 @@ void Extensions3DOpenGL::bindVertexArrayOES(Platform3DObject array) #endif } -String Extensions3DOpenGL::getTranslatedShaderSourceANGLE(Platform3DObject shader) -{ - UNUSED_PARAM(shader); - return ""; - // FIXME: implement this function and add GL_ANGLE_translated_shader_source in supports(). -} - void Extensions3DOpenGL::copyTextureCHROMIUM(GC3Denum, Platform3DObject, Platform3DObject, GC3Dint, GC3Denum) { // FIXME: implement this function and add GL_CHROMIUM_copy_texture in supports(). return; } +bool Extensions3DOpenGL::supportsExtension(const String& name) +{ + // GL_ANGLE_framebuffer_blit and GL_ANGLE_framebuffer_multisample are "fake". They are implemented using other + // extensions. In particular GL_EXT_framebuffer_blit and GL_EXT_framebuffer_multisample + if (name == "GL_ANGLE_framebuffer_blit") + return m_availableExtensions.contains("GL_EXT_framebuffer_blit"); + if (name == "GL_ANGLE_framebuffer_multisample") + return m_availableExtensions.contains("GL_EXT_framebuffer_multisample"); + + // Desktop GL always supports GL_OES_rgb8_rgba8. + if (name == "GL_OES_rgb8_rgba8") + return true; + + // If GL_ARB_texture_float is available then we report GL_OES_texture_float and + // GL_OES_texture_half_float as available. + if (name == "GL_OES_texture_float" || name == "GL_OES_texture_half_float") + return m_availableExtensions.contains("GL_ARB_texture_float"); + + // GL_OES_vertex_array_object + if (name == "GL_OES_vertex_array_object") + return m_availableExtensions.contains("GL_APPLE_vertex_array_object"); + + // Desktop GL always supports the standard derivative functions + if (name == "GL_OES_standard_derivatives") + return true; + + if (name == "GL_EXT_texture_filter_anisotropic") + return m_availableExtensions.contains("GL_EXT_texture_filter_anisotropic"); + + return m_availableExtensions.contains(name); +} + +String Extensions3DOpenGL::getExtensions() +{ + return String(reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS))); +} + } // namespace WebCore -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h index 2b2d30a09..72eff9218 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h @@ -26,7 +26,7 @@ #ifndef Extensions3DOpenGL_h #define Extensions3DOpenGL_h -#include "Extensions3D.h" +#include "Extensions3DOpenGLCommon.h" #include "GraphicsContext3D.h" #include <wtf/HashSet.h> @@ -34,15 +34,11 @@ namespace WebCore { -class Extensions3DOpenGL : public Extensions3D { +class Extensions3DOpenGL : public Extensions3DOpenGLCommon { public: virtual ~Extensions3DOpenGL(); // Extensions3D methods. - virtual bool supports(const String&); - virtual void ensureEnabled(const String&); - virtual bool isEnabled(const String&); - virtual int getGraphicsResetStatusARB(); virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter); virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height); @@ -50,19 +46,15 @@ public: virtual void deleteVertexArrayOES(Platform3DObject); virtual GC3Dboolean isVertexArrayOES(Platform3DObject); virtual void bindVertexArrayOES(Platform3DObject); - virtual String getTranslatedShaderSourceANGLE(Platform3DObject); virtual void copyTextureCHROMIUM(GC3Denum, Platform3DObject, Platform3DObject, GC3Dint, GC3Denum); -private: +protected: // This class only needs to be instantiated by GraphicsContext3D implementations. friend class GraphicsContext3D; Extensions3DOpenGL(GraphicsContext3D*); - bool m_initializedAvailableExtensions; - HashSet<String> m_availableExtensions; - - // Weak pointer back to GraphicsContext3D - GraphicsContext3D* m_context; + virtual bool supportsExtension(const WTF::String&); + virtual String getExtensions(); }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp new file mode 100644 index 000000000..57723560c --- /dev/null +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2012 Research In Motion Limited. 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" + +#if ENABLE(WEBGL) +#include "Extensions3DOpenGLCommon.h" + +#include "ANGLEWebKitBridge.h" +#include "GraphicsContext3D.h" + +#if PLATFORM(BLACKBERRY) +#include <BlackBerryPlatformLog.h> +#endif + +#if USE(OPENGL_ES_2) +#include "OpenGLESShims.h" +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#elif PLATFORM(MAC) +#include <OpenGL/gl.h> +#elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(QT) +#include "OpenGLShims.h" +#endif + +#include <wtf/Vector.h> + +namespace WebCore { + +Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context) + : m_initializedAvailableExtensions(false) + , m_context(context) +{ +} + +Extensions3DOpenGLCommon::~Extensions3DOpenGLCommon() +{ +} + +bool Extensions3DOpenGLCommon::supports(const String& name) +{ + if (!m_initializedAvailableExtensions) + initializeAvailableExtensions(); + + return supportsExtension(name); +} + +void Extensions3DOpenGLCommon::ensureEnabled(const String& name) +{ + if (name == "GL_OES_standard_derivatives") { + // Enable support in ANGLE (if not enabled already) + ANGLEWebKitBridge& compiler = m_context->m_compiler; + ShBuiltInResources ANGLEResources = compiler.getResources(); + if (!ANGLEResources.OES_standard_derivatives) { + ANGLEResources.OES_standard_derivatives = 1; + compiler.setResources(ANGLEResources); + } + } +} + +bool Extensions3DOpenGLCommon::isEnabled(const String& name) +{ + if (name == "GL_OES_standard_derivatives") { + ANGLEWebKitBridge& compiler = m_context->m_compiler; + return compiler.getResources().OES_standard_derivatives; + } + return supports(name); +} + +int Extensions3DOpenGLCommon::getGraphicsResetStatusARB() +{ + return GraphicsContext3D::NO_ERROR; +} + +String Extensions3DOpenGLCommon::getTranslatedShaderSourceANGLE(Platform3DObject shader) +{ + ASSERT(shader); + int GLshaderType; + ANGLEShaderType shaderType; + + ANGLEWebKitBridge& compiler = m_context->m_compiler; + + m_context->getShaderiv(shader, GraphicsContext3D::SHADER_TYPE, &GLshaderType); + + if (GLshaderType == GraphicsContext3D::VERTEX_SHADER) + shaderType = SHADER_TYPE_VERTEX; + else if (GLshaderType == GraphicsContext3D::FRAGMENT_SHADER) + shaderType = SHADER_TYPE_FRAGMENT; + else + return ""; // Invalid shader type. + + HashMap<Platform3DObject, GraphicsContext3D::ShaderSourceEntry>::iterator result = m_context->m_shaderSourceMap.find(shader); + + if (result == m_context->m_shaderSourceMap.end()) + return ""; + + GraphicsContext3D::ShaderSourceEntry& entry = result->second; + + String translatedShaderSource; + String shaderInfoLog; + + bool isValid = compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog); + + entry.log = shaderInfoLog; + entry.isValid = isValid; + + if (!isValid) + return ""; + + return translatedShaderSource; +} + +void Extensions3DOpenGLCommon::initializeAvailableExtensions() +{ + String extensionsString = getExtensions(); + Vector<String> availableExtensions; + extensionsString.split(" ", availableExtensions); + for (size_t i = 0; i < availableExtensions.size(); ++i) + m_availableExtensions.add(availableExtensions[i]); + m_initializedAvailableExtensions = true; +} + +} // namespace WebCore + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/platform/graphics/qt/Extensions3DQt.h b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h index d9bd748bf..2796d6fc9 100644 --- a/Source/WebCore/platform/graphics/qt/Extensions3DQt.h +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,37 +24,49 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Extensions3DQt_h -#define Extensions3DQt_h +#ifndef Extensions3DOpenGLCommon_h +#define Extensions3DOpenGLCommon_h #include "Extensions3D.h" +#include "GraphicsContext3D.h" +#include <wtf/HashSet.h> +#include <wtf/text/StringHash.h> + namespace WebCore { -class Extensions3DQt : public Extensions3D { +class Extensions3DOpenGLCommon : public Extensions3D { public: - virtual ~Extensions3DQt(); + virtual ~Extensions3DOpenGLCommon(); // Extensions3D methods. virtual bool supports(const String&); virtual void ensureEnabled(const String&); virtual bool isEnabled(const String&); virtual int getGraphicsResetStatusARB(); - virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter); - virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height); - virtual Platform3DObject createVertexArrayOES(); - virtual void deleteVertexArrayOES(Platform3DObject); - virtual GC3Dboolean isVertexArrayOES(Platform3DObject); - virtual void bindVertexArrayOES(Platform3DObject); + + virtual Platform3DObject createVertexArrayOES() = 0; + virtual void deleteVertexArrayOES(Platform3DObject) = 0; + virtual GC3Dboolean isVertexArrayOES(Platform3DObject) = 0; + virtual void bindVertexArrayOES(Platform3DObject) = 0; + virtual String getTranslatedShaderSourceANGLE(Platform3DObject); - virtual void copyTextureCHROMIUM(GC3Denum, Platform3DObject, Platform3DObject, GC3Dint, GC3Denum); -private: - // This class only needs to be instantiated by GraphicsContext3D implementations. - friend class GraphicsContext3D; - Extensions3DQt(); +protected: + Extensions3DOpenGLCommon(GraphicsContext3D*); + + virtual bool supportsExtension(const String&) = 0; + virtual String getExtensions() = 0; + + virtual void initializeAvailableExtensions(); + + bool m_initializedAvailableExtensions; + HashSet<String> m_availableExtensions; + + // Weak pointer back to GraphicsContext3D + GraphicsContext3D* m_context; }; } // namespace WebCore -#endif // Extensions3DQt_h +#endif // Extensions3DOpenGLCommon_h diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp new file mode 100644 index 000000000..e21f559ad --- /dev/null +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2012 Research In Motion Limited. 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" +#if ENABLE(WEBGL) +#include "Extensions3DOpenGLES.h" + +#include "GraphicsContext3D.h" +#include <EGL/egl.h> +#include <wtf/Vector.h> + + +namespace WebCore { + +Extensions3DOpenGLES::Extensions3DOpenGLES(GraphicsContext3D* context) + : Extensions3DOpenGLCommon(context) + , m_supportsOESvertexArrayObject(false) + , m_supportsIMGMultisampledRenderToTexture(false) + , m_glFramebufferTexture2DMultisampleIMG(0) + , m_glRenderbufferStorageMultisampleIMG(0) + , m_glBindVertexArrayOES(0) + , m_glDeleteVertexArraysOES(0) + , m_glGenVertexArraysOES(0) + , m_glIsVertexArrayOES(0) +{ +} + +Extensions3DOpenGLES::~Extensions3DOpenGLES() +{ +} + +void Extensions3DOpenGLES::framebufferTexture2DMultisampleIMG(unsigned long target, unsigned long attachment, unsigned long textarget, unsigned int texture, int level, unsigned long samples) +{ + if (m_glFramebufferTexture2DMultisampleIMG) + m_glFramebufferTexture2DMultisampleIMG(target, attachment, textarget, texture, level, samples); + else + m_context->synthesizeGLError(GL_INVALID_OPERATION); +} + +void Extensions3DOpenGLES::renderbufferStorageMultisampleIMG(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height) +{ + if (m_glRenderbufferStorageMultisampleIMG) + m_glRenderbufferStorageMultisampleIMG(target, samples, internalformat, width, height); + else + m_context->synthesizeGLError(GL_INVALID_OPERATION); +} + +Platform3DObject Extensions3DOpenGLES::createVertexArrayOES() +{ + m_context->makeContextCurrent(); + if (m_glGenVertexArraysOES) { + GLuint array = 0; + m_glGenVertexArraysOES(1, &array); + return array; + } + + m_context->synthesizeGLError(GL_INVALID_OPERATION); + return 0; +} + +void Extensions3DOpenGLES::deleteVertexArrayOES(Platform3DObject array) +{ + if (!array) + return; + + m_context->makeContextCurrent(); + if (m_glDeleteVertexArraysOES) + m_glDeleteVertexArraysOES(1, &array); + else + m_context->synthesizeGLError(GL_INVALID_OPERATION); +} + +GC3Dboolean Extensions3DOpenGLES::isVertexArrayOES(Platform3DObject array) +{ + if (!array) + return GL_FALSE; + + m_context->makeContextCurrent(); + if (m_glIsVertexArrayOES) + return m_glIsVertexArrayOES(array); + + m_context->synthesizeGLError(GL_INVALID_OPERATION); + return false; +} + +void Extensions3DOpenGLES::bindVertexArrayOES(Platform3DObject array) +{ + if (!array) + return; + + m_context->makeContextCurrent(); + if (m_glBindVertexArrayOES) + m_glBindVertexArrayOES(array); + else + m_context->synthesizeGLError(GL_INVALID_OPERATION); +} + + +bool Extensions3DOpenGLES::supportsExtension(const String& name) +{ + if (m_availableExtensions.contains(name)) { + if (name == "GL_OES_vertex_array_object" && !m_supportsOESvertexArrayObject) { + m_glBindVertexArrayOES = reinterpret_cast<PFNGLBINDVERTEXARRAYOESPROC>(eglGetProcAddress("glBindVertexArrayOES")); + m_glGenVertexArraysOES = reinterpret_cast<PFNGLGENVERTEXARRAYSOESPROC>(eglGetProcAddress("glGenVertexArraysOES")); + m_glDeleteVertexArraysOES = reinterpret_cast<PFNGLDELETEVERTEXARRAYSOESPROC>(eglGetProcAddress("glDeleteVertexArraysOES")); + m_glIsVertexArrayOES = reinterpret_cast<PFNGLISVERTEXARRAYOESPROC>(eglGetProcAddress("glIsVertexArrayOES")); + m_supportsOESvertexArrayObject = true; + } else if (name == "GL_IMG_multisampled_render_to_texture" && !m_supportsIMGMultisampledRenderToTexture) { + m_glFramebufferTexture2DMultisampleIMG = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC>(eglGetProcAddress("glFramebufferTexture2DMultisampleIMG")); + m_glRenderbufferStorageMultisampleIMG = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC>(eglGetProcAddress("glRenderbufferStorageMultisampleIMG")); + m_supportsIMGMultisampledRenderToTexture = true; + } + return true; + } + + return false; +} + +String Extensions3DOpenGLES::getExtensions() +{ + return String(reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS))); +} + +} // namespace WebCore + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h new file mode 100644 index 000000000..3c460f9e2 --- /dev/null +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2012 Research In Motion Limited. 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 Extensions3DOpenGLES_h +#define Extensions3DOpenGLES_h + +#include "Extensions3DOpenGLCommon.h" + +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +namespace WebCore { + +class Extensions3DOpenGLES : public Extensions3DOpenGLCommon { +public: + virtual ~Extensions3DOpenGLES(); + + virtual void framebufferTexture2DMultisampleIMG(unsigned long target, unsigned long attachment, unsigned long textarget, unsigned int texture, int level, unsigned long samples); + virtual void renderbufferStorageMultisampleIMG(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height); + + virtual Platform3DObject createVertexArrayOES(); + virtual void deleteVertexArrayOES(Platform3DObject); + virtual GC3Dboolean isVertexArrayOES(Platform3DObject); + virtual void bindVertexArrayOES(Platform3DObject); + +protected: + // This class only needs to be instantiated by GraphicsContext3D implementations. + friend class GraphicsContext3D; + Extensions3DOpenGLES(GraphicsContext3D*); + + virtual bool supportsExtension(const String&); + virtual String getExtensions(); + + bool m_supportsOESvertexArrayObject; + bool m_supportsIMGMultisampledRenderToTexture; + + PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC m_glFramebufferTexture2DMultisampleIMG; + PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC m_glRenderbufferStorageMultisampleIMG; + PFNGLBINDVERTEXARRAYOESPROC m_glBindVertexArrayOES; + PFNGLDELETEVERTEXARRAYSOESPROC m_glDeleteVertexArraysOES; + PFNGLGENVERTEXARRAYSOESPROC m_glGenVertexArraysOES; + PFNGLISVERTEXARRAYOESPROC m_glIsVertexArrayOES; +}; + +} // namespace WebCore + +#endif // Extensions3DOpenGLES_h diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp index 3f47b6e21..6753444f8 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,7 +26,7 @@ #include "config.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "GraphicsContext3D.h" @@ -34,6 +35,12 @@ #include "IntSize.h" #include "NotImplemented.h" +#include <algorithm> +#include <cstring> +#include <wtf/MainThread.h> +#include <wtf/UnusedParam.h> +#include <wtf/text/CString.h> + #if PLATFORM(MAC) #include <OpenGL/gl.h> #elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(QT) @@ -47,6 +54,24 @@ void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int ::glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels); } +void GraphicsContext3D::validateAttributes() +{ + Extensions3D* extensions = getExtensions(); + validateDepthStencil("GL_EXT_packed_depth_stencil"); + if (m_attrs.antialias) { + bool isValidVendor = true; + // Currently in Mac we only turn on antialias if vendor is NVIDIA, + // or if ATI and on 10.7.2 and above. + const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); + if (!vendor || (!std::strstr(vendor, "NVIDIA") && !(std::strstr(vendor, "ATI") && systemAllowsMultisamplingOnATICards()))) + isValidVendor = false; + if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) + m_attrs.antialias = false; + else + extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); + } +} + bool GraphicsContext3D::reshapeFBOs(const IntSize& size) { const int width = size.width(); @@ -256,6 +281,49 @@ void GraphicsContext3D::clearDepth(GC3Dclampf depth) ::glClearDepth(depth); } +bool GraphicsContext3D::systemAllowsMultisamplingOnATICards() const +{ +#if PLATFORM(MAC) +#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) + return true; +#else + ASSERT(isMainThread()); + static SInt32 version; + if (!version) { + if (Gestalt(gestaltSystemVersion, &version) != noErr) + return false; + } + // See https://bugs.webkit.org/show_bug.cgi?id=77922 for more details + return version >= 0x1072; +#endif // SNOW_LEOPARD and LION +#else + return false; +#endif // PLATFORM(MAC) +} + +Extensions3D* GraphicsContext3D::getExtensions() +{ + if (!m_extensions) + m_extensions = adoptPtr(new Extensions3DOpenGL(this)); + return m_extensions.get(); +} + +void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) +{ + // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., + // all previous rendering calls should be done before reading pixels. + makeContextCurrent(); + ::glFlush(); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { + resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); + ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); + ::glFlush(); + } + ::glReadPixels(x, y, width, height, format, type, data); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); +} + } -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp index 429fc51c9..9a7f4250d 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp @@ -1,6 +1,8 @@ /* * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. All rights reserved. * Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.com> + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,11 +28,16 @@ #include "config.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "GraphicsContext3D.h" +#include "CanvasRenderingContext.h" +#if USE(OPENGL_ES_2) +#include "Extensions3DOpenGLES.h" +#else #include "Extensions3DOpenGL.h" +#endif #include "GraphicsContext.h" #include "ImageBuffer.h" #include "ImageData.h" @@ -49,39 +56,24 @@ #include <wtf/UnusedParam.h> #include <wtf/text/CString.h> -#if PLATFORM(MAC) +#if USE(OPENGL_ES_2) +#include "OpenGLESShims.h" +#elif PLATFORM(MAC) #include <OpenGL/gl.h> #elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(QT) #include "OpenGLShims.h" #endif -namespace WebCore { +#if PLATFORM(BLACKBERRY) +#include <BlackBerryPlatformLog.h> +#endif -static bool systemAllowsMultisamplingOnATICards() -{ -#if PLATFORM(MAC) -#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) - return true; -#else - ASSERT(isMainThread()); - static SInt32 version; - if (!version) { - if (Gestalt(gestaltSystemVersion, &version) != noErr) - return false; - } - // See https://bugs.webkit.org/show_bug.cgi?id=77922 for more details - return version >= 0x1072; -#endif // SNOW_LEOPARD and LION -#else - return false; -#endif // PLATFORM(MAC) -} +namespace WebCore { -void GraphicsContext3D::validateAttributes() +void GraphicsContext3D::validateDepthStencil(const char* packedDepthStencilExtension) { Extensions3D* extensions = getExtensions(); if (m_attrs.stencil) { - const char* packedDepthStencilExtension = isGLES2Compliant() ? "GL_OES_packed_depth_stencil" : "GL_EXT_packed_depth_stencil"; if (extensions->supports(packedDepthStencilExtension)) { extensions->ensureEnabled(packedDepthStencilExtension); // Force depth if stencil is true. @@ -439,36 +431,11 @@ void GraphicsContext3D::compileShader(Platform3DObject shader) ASSERT(shader); makeContextCurrent(); - int GLshaderType; - ANGLEShaderType shaderType; - - glGetShaderiv(shader, SHADER_TYPE, &GLshaderType); - - if (GLshaderType == VERTEX_SHADER) - shaderType = SHADER_TYPE_VERTEX; - else if (GLshaderType == FRAGMENT_SHADER) - shaderType = SHADER_TYPE_FRAGMENT; - else - return; // Invalid shader type. - - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + String translatedShaderSource = m_extensions->getTranslatedShaderSourceANGLE(shader); - if (result == m_shaderSourceMap.end()) + if (!translatedShaderSource.length()) return; - ShaderSourceEntry& entry = result->second; - - String translatedShaderSource; - String shaderInfoLog; - - bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog); - - entry.log = shaderInfoLog; - entry.isValid = isValid; - - if (!isValid) - return; // Shader didn't validate, don't move forward with compiling translated source. - int translatedShaderLength = translatedShaderSource.length(); const CString& translatedShaderCString = translatedShaderSource.utf8(); @@ -790,29 +757,6 @@ void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units) ::glPolygonOffset(factor, units); } -void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) -{ - // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., - // all previous rendering calls should be done before reading pixels. - makeContextCurrent(); - ::glFlush(); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { - resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); - ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); - ::glFlush(); - } - ::glReadPixels(x, y, width, height, format, type, data); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) - ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); -} - -void GraphicsContext3D::releaseShaderCompiler() -{ - // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants. - makeContextCurrent(); - notImplemented(); -} - void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert) { makeContextCurrent(); @@ -1386,13 +1330,6 @@ bool GraphicsContext3D::layerComposited() const return m_layerComposited; } -Extensions3D* GraphicsContext3D::getExtensions() -{ - if (!m_extensions) - m_extensions = adoptPtr(new Extensions3DOpenGL(this)); - return m_extensions.get(); -} - } -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp index b1bd1dc56..e4ac6876e 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp @@ -1,6 +1,8 @@ /* * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. All rights reserved. * Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.com> + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,96 +28,89 @@ #include "config.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "GraphicsContext3D.h" - -#include "Extensions3DOpenGL.h" +#include "Extensions3DOpenGLES.h" #include "IntRect.h" #include "IntSize.h" +#include "LayerWebKitThread.h" #include "NotImplemented.h" - -#if PLATFORM(GTK) || PLATFORM(QT) -#include "OpenGLShims.h" -#endif +#include "OpenGLESShims.h" namespace WebCore { -void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels) +void GraphicsContext3D::releaseShaderCompiler() { - const int totalBytes = m_currentWidth * m_currentHeight * 4; - ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - for (int i = 0; i < totalBytes; i += 4) - std::swap(pixels[i], pixels[i + 2]); // Convert to BGRA. + makeContextCurrent(); + ::glReleaseShaderCompiler(); } -bool GraphicsContext3D::reshapeFBOs(const IntSize& size) +void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) { - const int width = size.width(); - const int height = size.height(); - GLuint colorFormat = 0, pixelDataType = 0; - if (m_attrs.alpha) { - m_internalColorFormat = GL_RGBA; - colorFormat = GL_RGBA; - pixelDataType = GL_UNSIGNED_BYTE; - } else { - m_internalColorFormat = GL_RGB; - colorFormat = GL_RGB; - pixelDataType = GL_UNSIGNED_SHORT_5_6_5; + // Currently only format=RGBA, type=UNSIGNED_BYTE is supported by the specification: http://www.khronos.org/registry/webgl/specs/latest/ + // If this ever changes, this code will need to be updated. + + // Calculate the strides of our data and canvas + unsigned int formatSize = 4; // RGBA UNSIGNED_BYTE + unsigned int dataStride = width * formatSize; + unsigned int canvasStride = m_currentWidth * formatSize; + + // If we are using a pack alignment of 8, then we need to align our strides to 8 byte boundaries + // See: http://en.wikipedia.org/wiki/Data_structure_alignment (computing padding) + int packAlignment; + glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); + if (8 == packAlignment) { + dataStride = (dataStride + 7) & ~7; + canvasStride = (canvasStride + 7) & ~7; } - // We don't allow the logic where stencil is required and depth is not. - // See GraphicsContext3D::validateAttributes. - bool supportPackedDepthStencilBuffer = (m_attrs.stencil || m_attrs.depth) && getExtensions()->supports("GL_OES_packed_depth_stencil"); + unsigned char* canvasData = new unsigned char[canvasStride * m_currentHeight]; + ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, format, type, canvasData); - // Resize regular FBO. - bool mustRestoreFBO = false; - if (m_boundFBO != m_fbo) { - mustRestoreFBO = true; - ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); + // If we failed to read our canvas data due to a GL error, don't continue + int error = glGetError(); + if (GL_NO_ERROR != error) { + synthesizeGLError(error); + return; } - ::glBindTexture(GL_TEXTURE_2D, m_texture); - ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, pixelDataType, 0); - ::glFramebufferTexture2DEXT(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); - - ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); - ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); - ::glBindTexture(GL_TEXTURE_2D, 0); - - // We don't support antialiasing yet. See GraphicsContext3D::validateAttributes. - ASSERT(!m_attrs.antialias); - - if (m_attrs.stencil || m_attrs.depth) { - // Use a 24 bit depth buffer where we know we have it. - if (supportPackedDepthStencilBuffer) { - ::glBindTexture(GL_TEXTURE_2D, m_depthStencilBuffer); - ::glTexImage2D(GL_TEXTURE_2D, 0, GraphicsContext3D::DEPTH_STENCIL, width, height, 0, GraphicsContext3D::DEPTH_STENCIL, GraphicsContext3D::UNSIGNED_INT_24_8, 0); - if (m_attrs.stencil) - ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0); - if (m_attrs.depth) - ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0); - ::glBindTexture(GL_TEXTURE_2D, 0); - } else { - if (m_attrs.stencil) { - ::glBindRenderbufferEXT(GraphicsContext3D::RENDERBUFFER, m_stencilBuffer); - ::glRenderbufferStorageEXT(GraphicsContext3D::RENDERBUFFER, GL_STENCIL_INDEX8, width, height); - ::glFramebufferRenderbufferEXT(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_stencilBuffer); - } - if (m_attrs.depth) { - ::glBindRenderbufferEXT(GraphicsContext3D::RENDERBUFFER, m_depthBuffer); - ::glRenderbufferStorageEXT(GraphicsContext3D::RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); - ::glFramebufferRenderbufferEXT(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer); - } - ::glBindRenderbufferEXT(GraphicsContext3D::RENDERBUFFER, 0); - } - } - if (glCheckFramebufferStatusEXT(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { - // FIXME: cleanup - notImplemented(); + // Clear our data in case some of it lies outside the bounds of our canvas + // TODO: don't do this if all of the data lies inside the bounds of the canvas + memset(data, 0, dataStride * height); + + // Calculate the intersection of our canvas and data bounds + IntRect dataRect(x, y, width, height); + IntRect canvasRect(0, 0, m_currentWidth, m_currentHeight); + IntRect nonZeroDataRect = intersection(dataRect, canvasRect); + + unsigned int xDataOffset = x < 0 ? -x * formatSize : 0; + unsigned int yDataOffset = y < 0 ? -y * dataStride : 0; + unsigned int xCanvasOffset = nonZeroDataRect.x() * formatSize; + unsigned int yCanvasOffset = nonZeroDataRect.y() * canvasStride; + unsigned char* dst = static_cast<unsigned char*>(data) + xDataOffset + yDataOffset; + unsigned char* src = canvasData + xCanvasOffset + yCanvasOffset; + for (int row = 0; row < nonZeroDataRect.height(); row++) { + memcpy(dst, src, nonZeroDataRect.width() * formatSize); + dst += dataStride; + src += canvasStride; } - return mustRestoreFBO; + delete [] canvasData; + ::glReadPixels(x, y, width, height, format, type, data); + + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); +} + +void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels) +{ + ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + int totalBytes = width * height * 4; + if (isGLES2Compliant()) { + for (int i = 0; i < totalBytes; i += 4) + std::swap(pixels[i], pixels[i + 2]); // Convert to BGRA. + } } void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect) @@ -156,6 +151,17 @@ bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum inte return true; } +void GraphicsContext3D::validateAttributes() +{ + validateDepthStencil("GL_OES_packed_depth_stencil"); + + if (m_attrs.antialias) { + Extensions3D* extensions = getExtensions(); + if (!extensions->supports("GL_IMG_multisampled_render_to_texture")) + m_attrs.antialias = false; + } +} + void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar) { makeContextCurrent(); @@ -168,6 +174,19 @@ void GraphicsContext3D::clearDepth(GC3Dclampf depth) ::glClearDepthf(depth); } -} // namespace WebCore -#endif // ENABLE(WEBGL) +Extensions3D* GraphicsContext3D::getExtensions() +{ + if (!m_extensions) + m_extensions = adoptPtr(new Extensions3DOpenGLES(this)); + return m_extensions.get(); +} + +bool GraphicsContext3D::systemAllowsMultisamplingOnATICards() const +{ + return false; // not applicable +} + +} + +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp b/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp deleted file mode 100644 index 593e63e9a..000000000 --- a/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(WEBGL) - -#include "Extensions3DQt.h" - -#include "GraphicsContext3D.h" -#include "OpenGLShims.h" - -namespace WebCore { - -Extensions3DQt::Extensions3DQt() -{ -} - -Extensions3DQt::~Extensions3DQt() -{ -} - -bool Extensions3DQt::supports(const String&) -{ - return false; -} - -void Extensions3DQt::ensureEnabled(const String& name) -{ - ASSERT(supports(name)); -} - -bool Extensions3DQt::isEnabled(const String& name) -{ - return supports(name); -} - -int Extensions3DQt::getGraphicsResetStatusARB() -{ - return GraphicsContext3D::NO_ERROR; -} - -void Extensions3DQt::blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) -{ -} - -void Extensions3DQt::renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height) -{ -} - -Platform3DObject Extensions3DQt::createVertexArrayOES() -{ - return 0; -} - -void Extensions3DQt::deleteVertexArrayOES(Platform3DObject) -{ -} - -GC3Dboolean Extensions3DQt::isVertexArrayOES(Platform3DObject) -{ - return GL_FALSE; -} - -void Extensions3DQt::bindVertexArrayOES(Platform3DObject) -{ -} - -String Extensions3DQt::getTranslatedShaderSourceANGLE(Platform3DObject shader) -{ - return ""; -} - -void Extensions3DQt::copyTextureCHROMIUM(GC3Denum, Platform3DObject, Platform3DObject, GC3Dint, GC3Denum) -{ - return; -} - -} // namespace WebCore - -#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/platform/graphics/qt/FontQt.cpp b/Source/WebCore/platform/graphics/qt/FontQt.cpp index b55f0b7b1..ef9902271 100644 --- a/Source/WebCore/platform/graphics/qt/FontQt.cpp +++ b/Source/WebCore/platform/graphics/qt/FontQt.cpp @@ -81,8 +81,7 @@ static QPen fillPenForContext(GraphicsContext* ctx) } if (ctx->fillPattern()) { - AffineTransform affine; - return QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0); + return QPen(QBrush(ctx->fillPattern()->createPlatformPattern()), 0); } return QPen(QColor(ctx->fillColor()), 0); @@ -97,8 +96,7 @@ static QPen strokePenForContext(GraphicsContext* ctx) } if (ctx->strokePattern()) { - AffineTransform affine; - QBrush brush(ctx->strokePattern()->createPlatformPattern(affine)); + QBrush brush(ctx->strokePattern()->createPlatformPattern()); return QPen(brush, ctx->strokeThickness()); } diff --git a/Source/WebCore/platform/graphics/qt/FontQt4.cpp b/Source/WebCore/platform/graphics/qt/FontQt4.cpp index b021f9c64..232b8ffb4 100644 --- a/Source/WebCore/platform/graphics/qt/FontQt4.cpp +++ b/Source/WebCore/platform/graphics/qt/FontQt4.cpp @@ -83,8 +83,7 @@ static QPen fillPenForContext(GraphicsContext* ctx) } if (ctx->fillPattern()) { - AffineTransform affine; - return QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0); + return QPen(QBrush(ctx->fillPattern()->createPlatformPattern()), 0); } return QPen(QColor(ctx->fillColor())); @@ -99,8 +98,7 @@ static QPen strokePenForContext(GraphicsContext* ctx) } if (ctx->strokePattern()) { - AffineTransform affine; - QBrush brush(ctx->strokePattern()->createPlatformPattern(affine)); + QBrush brush(ctx->strokePattern()->createPlatformPattern()); return QPen(brush, ctx->strokeThickness()); } diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index 7be2c5e05..c7191e35b 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -17,15 +17,11 @@ */ #include "config.h" - #include "GraphicsContext3D.h" -#include "WebGLObject.h" -#include "CanvasRenderingContext.h" #include "Extensions3DOpenGL.h" #include "GraphicsContext.h" #include "GraphicsSurface.h" -#include "HTMLCanvasElement.h" #include "HostWindow.h" #include "ImageBuffer.h" #include "ImageData.h" @@ -40,11 +36,11 @@ #include <wtf/UnusedParam.h> #include <wtf/text/CString.h> -#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) && USE(TEXTURE_MAPPER_GL) +#if USE(TEXTURE_MAPPER_GL) #include <texmap/TextureMapperGL.h> #endif -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) namespace WebCore { @@ -57,7 +53,7 @@ typedef char GLchar; #endif class GraphicsContext3DPrivate -#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +#if USE(ACCELERATED_COMPOSITING) : public TextureMapperPlatformLayer #endif { @@ -65,7 +61,7 @@ public: GraphicsContext3DPrivate(GraphicsContext3D*, HostWindow*); ~GraphicsContext3DPrivate(); -#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +#if USE(ACCELERATED_COMPOSITING) virtual void paintToTextureMapper(TextureMapper*, const FloatRect& target, const TransformationMatrix&, float opacity, BitmapTexture* mask); #endif #if USE(GRAPHICS_SURFACE) @@ -98,6 +94,13 @@ bool GraphicsContext3D::isGLES2Compliant() const #endif } +#if !USE(OPENGL_ES_2) +void GraphicsContext3D::releaseShaderCompiler() +{ + notImplemented(); +} +#endif + GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, HostWindow* hostWindow) : m_context(context) , m_hostWindow(hostWindow) @@ -153,7 +156,7 @@ static inline quint32 swapBgrToRgb(quint32 pixel) return ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); } -#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +#if USE(ACCELERATED_COMPOSITING) void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, BitmapTexture* mask) { blitMultisampleFramebufferAndRestoreContext(); @@ -505,6 +508,9 @@ bool GraphicsContext3D::getImageData(Image* image, AlphaOp alphaOp = AlphaDoNothing; switch (qtImage.format()) { + case QImage::Format_RGB32: + // For opaque images, we should not premultiply or unmultiply alpha. + break; case QImage::Format_ARGB32: if (premultiplyAlpha) alphaOp = AlphaDoPremultiply; @@ -526,7 +532,7 @@ bool GraphicsContext3D::getImageData(Image* image, outputVector.resize(packedSize); - return packPixels(qtImage.bits(), SourceFormatBGRA8, image->width(), image->height(), 0, format, type, alphaOp, outputVector.data()); + return packPixels(qtImage.constBits(), SourceFormatBGRA8, image->width(), image->height(), 0, format, type, alphaOp, outputVector.data()); } void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>) @@ -539,4 +545,4 @@ void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback> } -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 074e7dffd..c034f64b3 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -507,8 +507,7 @@ void GraphicsContext::fillPath(const Path& path) if (shadowContext) { QPainter* shadowPainter = shadowContext->platformContext(); if (m_state.fillPattern) { - AffineTransform affine; - shadowPainter->fillPath(platformPath, QBrush(m_state.fillPattern->createPlatformPattern(affine))); + shadowPainter->fillPath(platformPath, QBrush(m_state.fillPattern->createPlatformPattern())); } else if (m_state.fillGradient) { QBrush brush(*m_state.fillGradient->platformGradient()); brush.setTransform(m_state.fillGradient->gradientSpaceTransform()); @@ -528,8 +527,7 @@ void GraphicsContext::fillPath(const Path& path) } } if (m_state.fillPattern) { - AffineTransform affine; - p->fillPath(platformPath, QBrush(m_state.fillPattern->createPlatformPattern(affine))); + p->fillPath(platformPath, QBrush(m_state.fillPattern->createPlatformPattern())); } else if (m_state.fillGradient) { QBrush brush(*m_state.fillGradient->platformGradient()); brush.setTransform(m_state.fillGradient->gradientSpaceTransform()); @@ -590,8 +588,7 @@ void GraphicsContext::strokePath(const Path& path) } if (m_state.strokePattern) { - AffineTransform affine; - QBrush brush = m_state.strokePattern->createPlatformPattern(affine); + QBrush brush = m_state.strokePattern->createPlatformPattern(); fillPathStroke(p, pathStroker, platformPath, brush); } else if (m_state.strokeGradient) { QBrush brush(*m_state.strokeGradient->platformGradient()); @@ -605,8 +602,7 @@ static inline void drawRepeatPattern(QPainter* p, PassRefPtr<Pattern> pattern, c { ASSERT(pattern); - AffineTransform affine; - const QBrush brush = pattern->createPlatformPattern(affine); + const QBrush brush = pattern->createPlatformPattern(); if (brush.style() != Qt::TexturePattern) return; @@ -703,28 +699,19 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS if (paintingDisabled() || !color.isValid()) return; - m_data->solidColor.setColor(color); + QRectF platformRect(rect); QPainter* p = m_data->p(); - QRectF normalizedRect = rect.normalized(); - if (hasShadow()) { ShadowBlur* shadow = shadowBlur(); if (shadow->mustUseShadowBlur(this)) { - GraphicsContext* shadowContext = shadow->beginShadowLayer(this, normalizedRect); - if (shadowContext) { - QPainter* shadowPainter = shadowContext->platformContext(); - shadowPainter->setCompositionMode(QPainter::CompositionMode_Source); - shadowPainter->fillRect(normalizedRect, m_state.shadowColor); - shadow->endShadowLayer(this); - } + shadow->drawRectShadow(this, platformRect, RoundedRect::Radii()); } else { QColor shadowColor = m_state.shadowColor; shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF()); - p->fillRect(normalizedRect.translated(QPointF(m_state.shadowOffset.width(), m_state.shadowOffset.height())), shadowColor); + p->fillRect(platformRect.translated(QPointF(m_state.shadowOffset.width(), m_state.shadowOffset.height())), shadowColor); } } - - p->fillRect(normalizedRect, m_data->solidColor); + p->fillRect(platformRect, QColor(color)); } void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace) @@ -738,13 +725,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef if (hasShadow()) { ShadowBlur* shadow = shadowBlur(); if (shadow->mustUseShadowBlur(this)) { - GraphicsContext* shadowContext = shadow->beginShadowLayer(this, rect); - if (shadowContext) { - QPainter* shadowPainter = shadowContext->platformContext(); - shadowPainter->setCompositionMode(QPainter::CompositionMode_Source); - shadowPainter->fillPath(path.platformPath(), QColor(m_state.shadowColor)); - shadow->endShadowLayer(this); - } + shadow->drawRectShadow(this, rect, RoundedRect::Radii(topLeft, topRight, bottomLeft, bottomRight)); } else { const QPointF shadowOffset(m_state.shadowOffset.width(), m_state.shadowOffset.height()); p->translate(shadowOffset); @@ -1045,7 +1026,10 @@ void GraphicsContext::pushTransparencyLayerInternal(const QRect &rect, qreal opa { QPainter* p = m_data->p(); - QRect deviceClip = p->transform().mapRect(rect); + QTransform deviceTransform = p->transform(); + QRect deviceClip = deviceTransform.mapRect(rect); + + alphaMask = alphaMask.transformed(deviceTransform); if (alphaMask.width() != deviceClip.width() || alphaMask.height() != deviceClip.height()) alphaMask = alphaMask.scaled(deviceClip.width(), deviceClip.height()); @@ -1334,7 +1318,7 @@ void GraphicsContext::setCTM(const AffineTransform& transform) m_data->p()->setWorldTransform(transform); } -#if ENABLE(3D_RENDERING) && USE(TEXTURE_MAPPER) +#if ENABLE(3D_RENDERING) TransformationMatrix GraphicsContext::get3DTransform() const { if (paintingDisabled()) diff --git a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp deleted file mode 100644 index effaaf096..000000000 --- a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ /dev/null @@ -1,1786 +0,0 @@ -/* - Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) - - 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 "GraphicsLayerQt.h" - -#if !defined(QT_NO_GRAPHICSVIEW) - -#include "FloatRect.h" -#include "GraphicsContext.h" -#include "Image.h" -#include "TranslateTransformOperation.h" -#include "UnitBezier.h" -#include <qgraphicseffect.h> -#include <qgraphicsitem.h> -#include <qgraphicsscene.h> -#include <qgraphicsview.h> -#include <qgraphicswidget.h> -#include <qstyleoption.h> -#include <QtCore/qabstractanimation.h> -#include <QtCore/qdatetime.h> -#include <QtCore/qdebug.h> -#include <QtCore/qmetaobject.h> -#include <QtCore/qset.h> -#include <QtCore/qtimer.h> -#include <QtGui/qcolor.h> -#include <QtGui/qpainter.h> -#include <QtGui/qpixmap.h> -#include <QtGui/qpixmapcache.h> -#include <wtf/CurrentTime.h> -#include <wtf/RefCounted.h> - -#if USE(TILED_BACKING_STORE) -#include "TiledBackingStore.h" -#include "TiledBackingStoreClient.h" - -// The minimum width/height for tiling. We use the same value as the Windows implementation. -#define GRAPHICS_LAYER_TILING_THRESHOLD 2000 -#endif - -#define QT_DEBUG_RECACHE 0 -#define QT_DEBUG_CACHEDUMP 0 - -#define QT_DEBUG_FPS 0 - -namespace WebCore { - -static const int gMinimumPixmapCacheLimit = 2048; - -#ifndef QT_NO_GRAPHICSEFFECT -class MaskEffectQt : public QGraphicsEffect { -public: - MaskEffectQt(QObject* parent, QGraphicsItem* maskLayer) - : QGraphicsEffect(parent) - , m_maskLayer(maskLayer) - { - } - - void draw(QPainter* painter) - { - // This is a modified clone of QGraphicsOpacityEffect. - // It's more efficient to do it this way because: - // (a) We don't need the QBrush abstraction - we always end up using QGraphicsItem::paint - // from the mask layer. - // (b) QGraphicsOpacityEffect detaches the pixmap, which is inefficient on OpenGL. - const QSize maskSize = sourceBoundingRect().toAlignedRect().size(); - if (!maskSize.isValid() || maskSize.isEmpty()) { - drawSource(painter); - return; - } - QPixmap maskPixmap(maskSize); - - // We need to do this so the pixmap would have hasAlpha(). - maskPixmap.fill(Qt::transparent); - QPainter maskPainter(&maskPixmap); - QStyleOptionGraphicsItem option; - option.exposedRect = option.rect = maskPixmap.rect(); - maskPainter.setRenderHints(painter->renderHints(), true); - m_maskLayer->paint(&maskPainter, &option, 0); - maskPainter.end(); - - QPoint offset; - QPixmap srcPixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, QGraphicsEffect::NoPad); - - // We have to use another intermediate pixmap, to make sure the mask applies only to this item - // and doesn't modify pixels already painted into this paint-device. - QPixmap pixmap(srcPixmap.size()); - pixmap.fill(Qt::transparent); - - if (pixmap.isNull()) - return; - - QPainter pixmapPainter(&pixmap); - - pixmapPainter.setRenderHints(painter->renderHints()); - pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source); - - // We use drawPixmap rather than detaching, because it's more efficient on OpenGL. - pixmapPainter.drawPixmap(0, 0, srcPixmap); - pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); - pixmapPainter.drawPixmap(0, 0, maskPixmap); - - pixmapPainter.end(); - painter->drawPixmap(offset, pixmap); - } - - QGraphicsItem* m_maskLayer; -}; -#endif // QT_NO_GRAPHICSEFFECT - -class GraphicsLayerQtImpl : public QGraphicsObject -#if USE(TILED_BACKING_STORE) - , public virtual TiledBackingStoreClient -#endif -{ - Q_OBJECT - -public: - // This set of flags help us defer which properties of the layer have been - // modified by the compositor, so we can know what to look for in the next flush. - enum ChangeMask { - NoChanges = 0, - - ParentChange = (1L << 0), - ChildrenChange = (1L << 1), - MaskLayerChange = (1L << 2), - PositionChange = (1L << 3), - - AnchorPointChange = (1L << 4), - SizeChange = (1L << 5), - TransformChange = (1L << 6), - ContentChange = (1L << 7), - - ContentsOrientationChange = (1L << 8), - OpacityChange = (1L << 9), - ContentsRectChange = (1L << 10), - - Preserves3DChange = (1L << 11), - MasksToBoundsChange = (1L << 12), - DrawsContentChange = (1L << 13), - ContentsOpaqueChange = (1L << 14), - - BackfaceVisibilityChange = (1L << 15), - ChildrenTransformChange = (1L << 16), - DisplayChange = (1L << 17), - BackgroundColorChange = (1L << 18), - - DistributesOpacityChange = (1L << 19) - }; - - // The compositor lets us special-case images and colors, so we try to do so. - enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType, MediaContentType, Canvas3DContentType}; - - const GraphicsLayerQtImpl* rootLayer() const; - - GraphicsLayerQtImpl(GraphicsLayerQt* newLayer); - virtual ~GraphicsLayerQtImpl(); - - // reimps from QGraphicsItem - virtual QPainterPath opaqueArea() const; - virtual QRectF boundingRect() const; - virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); - - // We manage transforms ourselves because transform-origin acts differently in webkit and in Qt, - // and we need it as a fallback in case we encounter an un-invertible matrix. - void setBaseTransform(const TransformationMatrix&); - void updateTransform(); - - // let the compositor-API tell us which properties were changed - void notifyChange(ChangeMask); - - // Actual rendering of the web-content into a QPixmap: - // We prefer to use our own caching because it gives us a higher level of granularity than - // QGraphicsItem cache modes - Sometimes we need to cache the contents even though the item - // needs to be updated, e.g. when the background-color is changed. - // TODO: investigate if QGraphicsItem caching can be improved to support that out of the box. - QPixmap recache(const QRegion&); - - // Called when the compositor is ready for us to show the changes on screen. - // This is called indirectly from ChromeClientQt::setNeedsOneShotDrawingSynchronization - // (meaning the sync would happen together with the next draw) or - // ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP) - void flushChanges(bool recursive = true, bool forceTransformUpdate = false); - -#if USE(TILED_BACKING_STORE) - // reimplementations from TiledBackingStoreClient - virtual void tiledBackingStorePaintBegin(); - virtual void tiledBackingStorePaint(GraphicsContext*, const IntRect&); - virtual void tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea); - virtual IntRect tiledBackingStoreContentsRect(); - virtual IntRect tiledBackingStoreVisibleRect(); - virtual Color tiledBackingStoreBackgroundColor() const; -#endif - - static bool allowAcceleratedCompositingCache() { return QPixmapCache::cacheLimit() > gMinimumPixmapCacheLimit; } - - void drawLayerContent(QPainter*, const QRect&); - -public slots: - // We need to notify the client (ie. the layer compositor) when the animation actually starts. - void notifyAnimationStarted(); - - // We notify WebCore of a layer changed asynchronously; otherwise we end up calling flushChanges too often. - void notifySyncRequired(); - -signals: - // Optimization: Avoid using QTimer::singleShot(). - void notifyAnimationStartedAsync(); - -public: - GraphicsLayerQt* m_layer; - - TransformationMatrix m_baseTransform; - TransformationMatrix m_transformRelativeToRootLayer; - bool m_transformAnimationRunning; - bool m_opacityAnimationRunning; - bool m_blockNotifySyncRequired; -#ifndef QT_NO_GRAPHICSEFFECT - QWeakPointer<MaskEffectQt> m_maskEffect; -#endif - - struct ContentData { - QPixmap pixmap; - QRegion regionToUpdate; - bool updateAll; - - QColor contentsBackgroundColor; - QColor backgroundColor; - - QWeakPointer<QGraphicsObject> mediaLayer; - StaticContentType contentType; - - float opacity; - - ContentData() - : updateAll(false) - , contentType(HTMLContentType) - , opacity(1.f) - { - } - - }; - - ContentData m_pendingContent; - ContentData m_currentContent; - - int m_changeMask; - -#if USE(TILED_BACKING_STORE) - TiledBackingStore* m_tiledBackingStore; -#endif - - QSizeF m_size; - struct { - QPixmapCache::Key key; - QSizeF size; - } m_backingStore; -#ifndef QT_NO_ANIMATION - QList<QWeakPointer<QAbstractAnimation> > m_animations; -#endif - QTimer m_suspendTimer; - - struct State { - GraphicsLayer* maskLayer; - FloatPoint pos; - FloatPoint3D anchorPoint; - FloatSize size; - TransformationMatrix transform; - TransformationMatrix childrenTransform; - Color backgroundColor; - Color currentColor; - GraphicsLayer::CompositingCoordinatesOrientation contentsOrientation; - float opacity; - QRect contentsRect; - - bool preserves3D: 1; - bool masksToBounds: 1; - bool drawsContent: 1; - bool contentsOpaque: 1; - bool backfaceVisibility: 1; - bool distributeOpacity: 1; - bool align: 2; - - State() - : maskLayer(0) - , contentsOrientation(GraphicsLayer::CompositingCoordinatesTopDown) - , opacity(1.f) - , preserves3D(false) - , masksToBounds(false) - , drawsContent(false) - , contentsOpaque(false) - , backfaceVisibility(true) - , distributeOpacity(false) - { - } - } m_state; - -#ifndef QT_NO_ANIMATION - friend class AnimationQtBase; -#endif -}; - -inline GraphicsLayerQtImpl* toGraphicsLayerQtImpl(QGraphicsItem* item) -{ - ASSERT(item); - return qobject_cast<GraphicsLayerQtImpl*>(item->toGraphicsObject()); -} - -inline GraphicsLayerQtImpl* toGraphicsLayerQtImpl(QGraphicsObject* item) -{ - return qobject_cast<GraphicsLayerQtImpl*>(item); -} - -GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) - : QGraphicsObject(0) - , m_layer(newLayer) - , m_transformAnimationRunning(false) - , m_opacityAnimationRunning(false) - , m_blockNotifySyncRequired(false) - , m_changeMask(NoChanges) -#if USE(TILED_BACKING_STORE) - , m_tiledBackingStore(0) -#endif -{ - // We use graphics-view for compositing-only, not for interactivity. - setAcceptedMouseButtons(Qt::NoButton); - - // We need to have the item enabled, or else wheel events are not passed to the parent class - // implementation of wheelEvent, where they are ignored and passed to the item below. - setEnabled(true); - - connect(this, SIGNAL(notifyAnimationStartedAsync()), this, SLOT(notifyAnimationStarted()), Qt::QueuedConnection); -} - -GraphicsLayerQtImpl::~GraphicsLayerQtImpl() -{ - // The compositor manages lifecycle of item, so we do not want the graphicsview system to delete - // our items automatically. - const QList<QGraphicsItem*> children = childItems(); - QList<QGraphicsItem*>::const_iterator cit; - for (cit = children.constBegin(); cit != children.constEnd(); ++cit) { - if (QGraphicsItem* item = *cit) { - if (scene()) - scene()->removeItem(item); - item->setParentItem(0); - } - } -#if USE(TILED_BACKING_STORE) - delete m_tiledBackingStore; -#endif -#ifndef QT_NO_ANIMATION - // We do, however, own the animations. - QList<QWeakPointer<QAbstractAnimation> >::iterator it; - for (it = m_animations.begin(); it != m_animations.end(); ++it) - if (QAbstractAnimation* anim = it->data()) - delete anim; -#endif -} - -const GraphicsLayerQtImpl* GraphicsLayerQtImpl::rootLayer() const -{ - if (const GraphicsLayerQtImpl* parent = toGraphicsLayerQtImpl(parentObject())) - return parent->rootLayer(); - return this; -} - - -void GraphicsLayerQtImpl::drawLayerContent(QPainter* painter, const QRect& clipRect) -{ - painter->setClipRect(clipRect, Qt::IntersectClip); - painter->setCompositionMode(QPainter::CompositionMode_SourceOver); - GraphicsContext gc(painter); - m_layer->paintGraphicsLayerContents(gc, clipRect); -} - -QPixmap GraphicsLayerQtImpl::recache(const QRegion& regionToUpdate) -{ - if (!m_layer->drawsContent() || m_size.isEmpty() || !m_size.isValid()) - return QPixmap(); - -#if USE(TILED_BACKING_STORE) - const bool requiresTiling = (m_state.drawsContent && m_currentContent.contentType == HTMLContentType) && (m_size.width() > GRAPHICS_LAYER_TILING_THRESHOLD || m_size.height() > GRAPHICS_LAYER_TILING_THRESHOLD); - if (requiresTiling && !m_tiledBackingStore) { - m_tiledBackingStore = new TiledBackingStore(this); - m_tiledBackingStore->setTileCreationDelay(0); - setFlag(ItemUsesExtendedStyleOption, true); - } else if (!requiresTiling && m_tiledBackingStore) { - delete m_tiledBackingStore; - m_tiledBackingStore = 0; - setFlag(ItemUsesExtendedStyleOption, false); - } - - if (m_tiledBackingStore) { - m_tiledBackingStore->adjustVisibleRect(); - const QVector<QRect> rects = regionToUpdate.rects(); - for (int i = 0; i < rects.size(); ++i) - m_tiledBackingStore->invalidate(rects[i]); - return QPixmap(); - } -#endif - - QPixmap pixmap; - QRegion region = regionToUpdate; - if (QPixmapCache::find(m_backingStore.key, &pixmap)) { - if (region.isEmpty()) - return pixmap; - QPixmapCache::remove(m_backingStore.key); // Remove the reference to the pixmap in the cache to avoid a detach. - } - - { - bool erased = false; - - // If the pixmap is not in the cache or the view has grown since last cached. - if (pixmap.isNull() || m_size != m_backingStore.size) { -#if QT_DEBUG_RECACHE - if (pixmap.isNull()) - qDebug() << "CacheMiss" << this << m_size; -#endif - bool fill = true; - QRegion newRegion; - QPixmap oldPixmap = pixmap; - - // If the pixmap is two small to hold the view contents we enlarge, otherwise just use the old (large) pixmap. - if (pixmap.width() < m_size.width() || pixmap.height() < m_size.height()) { -#if QT_DEBUG_RECACHE - qDebug() << "CacheGrow" << this << m_size; -#endif - pixmap = QPixmap(m_size.toSize()); - pixmap.fill(Qt::transparent); - newRegion = QRegion(0, 0, m_size.width(), m_size.height()); - } - -#if 1 - // Blit the contents of oldPixmap back into the cached pixmap as we are just adding new pixels. - if (!oldPixmap.isNull()) { - const QRegion cleanRegion = (QRegion(0, 0, m_size.width(), m_size.height()) - & QRegion(0, 0, m_backingStore.size.width(), m_backingStore.size.height())) - regionToUpdate; - if (!cleanRegion.isEmpty()) { -#if QT_DEBUG_RECACHE - qDebug() << "CacheBlit" << this << cleanRegion; -#endif - const QRect cleanBounds(cleanRegion.boundingRect()); - QPainter painter(&pixmap); - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.drawPixmap(cleanBounds.topLeft(), oldPixmap, cleanBounds); - newRegion -= cleanRegion; - fill = false; // We cannot just fill the pixmap. - } - oldPixmap = QPixmap(); - } -#endif - region += newRegion; - if (fill && !region.isEmpty()) { // Clear the entire pixmap with the background. -#if QT_DEBUG_RECACHE - qDebug() << "CacheErase" << this << m_size << background; -#endif - erased = true; - pixmap.fill(Qt::transparent); - } - } - region &= QRegion(0, 0, m_size.width(), m_size.height()); - - // If we have something to draw its time to erase it and render the contents. - if (!region.isEmpty()) { -#if QT_DEBUG_CACHEDUMP - static int recacheCount = 0; - ++recacheCount; - qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size; - pixmap.save(QString().sprintf("/tmp/%05d_A.png", recacheCount), "PNG"); -#endif - - QPainter painter(&pixmap); - GraphicsContext gc(&painter); - - painter.setClipRegion(region); - - if (!erased) { // Erase the area in cache that we're drawing into. - painter.setCompositionMode(QPainter::CompositionMode_Clear); - painter.fillRect(region.boundingRect(), Qt::transparent); - -#if QT_DEBUG_CACHEDUMP - qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size; - pixmap.save(QString().sprintf("/tmp/%05d_B.png", recacheCount), "PNG"); -#endif - } - - // Render the actual contents into the cache. - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - m_layer->paintGraphicsLayerContents(gc, region.boundingRect()); - painter.end(); - -#if QT_DEBUG_CACHEDUMP - qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size; - pixmap.save(QString().sprintf("/tmp/%05d_C.png", recacheCount), "PNG"); -#endif - } - m_backingStore.size = m_size; // Store the used size of the pixmap. - } - - // Finally insert into the cache and allow a reference there. - m_backingStore.key = QPixmapCache::insert(pixmap); - return pixmap; -} - -void GraphicsLayerQtImpl::updateTransform() -{ - if (!m_transformAnimationRunning) - m_baseTransform = m_layer->transform(); - - TransformationMatrix localTransform; - - GraphicsLayerQtImpl* parent = toGraphicsLayerQtImpl(parentObject()); - - // WebCore has relative-to-size originPoint, where as the QGraphicsView has a pixel originPoint. - // Thus, we need to convert here as we have to manage this outselves due to the fact that the - // transformOrigin of the graphicsview is imcompatible. - const qreal originX = m_state.anchorPoint.x() * m_size.width(); - const qreal originY = m_state.anchorPoint.y() * m_size.height(); - - // We ignore QGraphicsItem::pos completely, and use transforms only, due to the fact that we - // have to maintain that ourselves for 3D. - localTransform - .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z()) - .multiply(m_baseTransform) - .translate3d(-originX, -originY, -m_state.anchorPoint.z()); - - // This is the actual 3D transform of this item, with the ancestors' transform baked in. - m_transformRelativeToRootLayer = TransformationMatrix(parent ? parent->m_transformRelativeToRootLayer : TransformationMatrix()) - .multiply(localTransform); - - // Now we have enough information to determine if the layer is facing backwards. - if (!m_state.backfaceVisibility && m_transformRelativeToRootLayer.inverse().m33() < 0) { - setVisible(false); - // No point in making extra calculations for invisible elements. - return; - } - - // The item is front-facing or backface-visibility is on. - setVisible(true); - - // Flatten to 2D-space of this item if it doesn't preserve 3D. - if (!m_state.preserves3D) { - m_transformRelativeToRootLayer.setM13(0); - m_transformRelativeToRootLayer.setM23(0); - m_transformRelativeToRootLayer.setM31(0); - m_transformRelativeToRootLayer.setM32(0); - m_transformRelativeToRootLayer.setM33(1); - m_transformRelativeToRootLayer.setM34(0); - m_transformRelativeToRootLayer.setM43(0); - } - - // Apply perspective for the use of this item's children. Perspective is always applied from the item's - // center. - if (!m_state.childrenTransform.isIdentity()) { - m_transformRelativeToRootLayer - .translate(m_size.width() / 2, m_size.height() /2) - .multiply(m_state.childrenTransform) - .translate(-m_size.width() / 2, -m_size.height() /2); - } - - bool inverseOk = true; - // Use QTransform::inverse to extrapolate the relative transform of this item, based on the parent's - // transform relative to the root layer and the desired transform for this item relative to the root layer. - const QTransform parentTransform = parent ? parent->itemTransform(rootLayer()) : QTransform(); - const QTransform transform2D = QTransform(m_transformRelativeToRootLayer) * parentTransform.inverted(&inverseOk); - - // In rare cases the transformation cannot be inversed - in that case we don't apply the transformation at - // all, otherwise we'd flicker. FIXME: This should be amended when Qt moves to a real 3D scene-graph. - if (!inverseOk) - return; - - setTransform(transform2D); - - const QList<QGraphicsItem*> children = childItems(); - QList<QGraphicsItem*>::const_iterator it; - for (it = children.constBegin(); it != children.constEnd(); ++it) - if (GraphicsLayerQtImpl* layer= toGraphicsLayerQtImpl(*it)) - layer->updateTransform(); -} - -void GraphicsLayerQtImpl::setBaseTransform(const TransformationMatrix& baseTransform) -{ - m_baseTransform = baseTransform; - updateTransform(); -} - -QPainterPath GraphicsLayerQtImpl::opaqueArea() const -{ - QPainterPath painterPath; - - // We try out best to return the opaque area, maybe it will help graphics-view render less items. - if (m_currentContent.backgroundColor.isValid() && m_currentContent.backgroundColor.alpha() == 0xff) - painterPath.addRect(boundingRect()); - else { - if (m_state.contentsOpaque - || (m_currentContent.contentType == ColorContentType && m_currentContent.contentsBackgroundColor.alpha() == 0xff) - || (m_currentContent.contentType == MediaContentType) - || (m_currentContent.contentType == PixmapContentType && !m_currentContent.pixmap.hasAlpha())) { - painterPath.addRect(m_state.contentsRect); - } - } - return painterPath; -} - -QRectF GraphicsLayerQtImpl::boundingRect() const -{ - return QRectF(QPointF(0, 0), QSizeF(m_size)); -} - -void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) -{ -#if USE(TILED_BACKING_STORE) - // FIXME: There's currently no Qt API to know if a new region of an item is exposed outside of the paint event. - // Suggested for Qt: http://bugreports.qt.nokia.com/browse/QTBUG-14877. - if (m_tiledBackingStore) - m_tiledBackingStore->adjustVisibleRect(); -#endif - - if (m_currentContent.backgroundColor.isValid()) - painter->fillRect(option->exposedRect, QColor(m_currentContent.backgroundColor)); - - switch (m_currentContent.contentType) { - case HTMLContentType: - if (m_state.drawsContent) { - if (!allowAcceleratedCompositingCache()) - drawLayerContent(painter, option->exposedRect.toRect()); - else { - QPixmap backingStore; - // We might need to recache, in case we try to paint and the cache was purged (e.g. if it was full). - if (!QPixmapCache::find(m_backingStore.key, &backingStore) || backingStore.size() != m_size.toSize()) - backingStore = recache(QRegion(m_state.contentsRect)); - painter->drawPixmap(0, 0, backingStore); - } - } - break; - case PixmapContentType: - painter->drawPixmap(m_state.contentsRect, m_currentContent.pixmap); - break; - case ColorContentType: - painter->fillRect(m_state.contentsRect, m_currentContent.contentsBackgroundColor); - break; - case MediaContentType: - // we don't need to paint anything: we have a QGraphicsItem from the media element - break; - } -} - -void GraphicsLayerQtImpl::notifySyncRequired() -{ - m_blockNotifySyncRequired = false; - - if (m_layer->client()) - m_layer->client()->notifySyncRequired(m_layer); -} - -void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask) -{ - m_changeMask |= changeMask; - - if (m_blockNotifySyncRequired) - return; - - static QMetaMethod syncMethod = staticMetaObject.method(staticMetaObject.indexOfMethod("notifySyncRequired()")); - syncMethod.invoke(this, Qt::QueuedConnection); - - m_blockNotifySyncRequired = true; -} - -void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform) -{ - // This is the bulk of the work. understanding what the compositor is trying to achieve, what - // graphicsview can do, and trying to find a sane common-ground. - if (!m_layer || m_changeMask == NoChanges) - goto afterLayerChanges; - - if (m_changeMask & ParentChange) { - // The WebCore compositor manages item ownership. We have to make sure graphicsview doesn't - // try to snatch that ownership. - if (!m_layer->parent() && !parentItem()) - setParentItem(0); - else if (m_layer && m_layer->parent() && m_layer->parent()->platformLayer() != parentItem()) - setParentItem(m_layer->parent()->platformLayer()); - } - - if (m_changeMask & ChildrenChange) { - // We basically do an XOR operation on the list of current children and the list of wanted - // children, and remove/add. - QSet<QGraphicsItem*> newChildren; - const Vector<GraphicsLayer*> newChildrenVector = (m_layer->children()); - newChildren.reserve(newChildrenVector.size()); - - for (size_t i = 0; i < newChildrenVector.size(); ++i) - newChildren.insert(newChildrenVector[i]->platformLayer()); - - const QSet<QGraphicsItem*> currentChildren = childItems().toSet(); - const QSet<QGraphicsItem*> childrenToAdd = newChildren - currentChildren; - const QSet<QGraphicsItem*> childrenToRemove = currentChildren - newChildren; - - QSet<QGraphicsItem*>::const_iterator it; - for (it = childrenToAdd.constBegin(); it != childrenToAdd.constEnd(); ++it) { - if (QGraphicsItem* w = *it) - w->setParentItem(this); - } - - QSet<QGraphicsItem*>::const_iterator rit; - for (rit = childrenToRemove.constBegin(); rit != childrenToRemove.constEnd(); ++rit) { - if (GraphicsLayerQtImpl* w = toGraphicsLayerQtImpl(*rit)) - w->setParentItem(0); - } - - // Children are ordered by z-value, let graphicsview know. - for (size_t i = 0; i < newChildrenVector.size(); ++i) { - if (newChildrenVector[i]->platformLayer()) - newChildrenVector[i]->platformLayer()->setZValue(i); - } - } - - if (m_changeMask & MaskLayerChange) { - // We can't paint here, because we don't know if the mask layer itself is ready... we'll have - // to wait till this layer tries to paint. - setFlag(ItemClipsChildrenToShape, m_layer->maskLayer() || m_layer->masksToBounds()); -#ifndef QT_NO_GRAPHICSEFFECT - setGraphicsEffect(0); - if (m_layer->maskLayer()) { - if (GraphicsLayerQtImpl* mask = toGraphicsLayerQtImpl(m_layer->maskLayer()->platformLayer())) { - mask->m_maskEffect = new MaskEffectQt(this, mask); - setGraphicsEffect(mask->m_maskEffect.data()); - } - } -#endif - } - - if (m_changeMask & SizeChange) { - if (m_layer->size() != m_state.size) { - prepareGeometryChange(); - m_size = QSizeF(m_layer->size().width(), m_layer->size().height()); - } - } - - // FIXME: This is a hack, due to a probable QGraphicsScene bug when rapidly modifying the perspective - // but without this line we get graphic artifacts. - if ((m_changeMask & ChildrenTransformChange) && m_state.childrenTransform != m_layer->childrenTransform()) - if (scene()) - scene()->update(); - - if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | BackfaceVisibilityChange | PositionChange | ParentChange)) { - // Due to the differences between the way WebCore handles transforms and the way Qt handles transforms, - // all these elements affect the transforms of all the descendants. - forceUpdateTransform = true; - } - - if (m_changeMask & (ContentChange | DrawsContentChange | MaskLayerChange)) { - switch (m_pendingContent.contentType) { - case PixmapContentType: - update(); - setFlag(ItemHasNoContents, false); - break; - - case MediaContentType: - setFlag(ItemHasNoContents, true); - m_pendingContent.mediaLayer.data()->setParentItem(this); - break; - - case ColorContentType: - if (m_pendingContent.contentType != m_currentContent.contentType - || m_pendingContent.contentsBackgroundColor != m_currentContent.contentsBackgroundColor) - update(); - m_state.drawsContent = false; - setFlag(ItemHasNoContents, false); - - // Only use ItemUsesExtendedStyleOption for HTML content as colors don't gain much from that. - setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false); - break; - - case HTMLContentType: - if (m_pendingContent.contentType != m_currentContent.contentType) - update(); - else if (!m_state.drawsContent && m_layer->drawsContent()) - update(); - - setFlag(ItemHasNoContents, !m_layer->drawsContent()); - break; - } - } - - if ((m_changeMask & OpacityChange) && m_state.opacity != m_layer->opacity() && !m_opacityAnimationRunning) - setOpacity(m_layer->opacity()); - - if (m_changeMask & ContentsRectChange) { - const QRect rect(m_layer->contentsRect()); - if (m_state.contentsRect != rect) { - m_state.contentsRect = rect; - if (m_pendingContent.mediaLayer) { - QGraphicsWidget* widget = qobject_cast<QGraphicsWidget*>(m_pendingContent.mediaLayer.data()); - if (widget) - widget->setGeometry(rect); - } - update(); - } - } - - if ((m_changeMask & MasksToBoundsChange) && m_state.masksToBounds != m_layer->masksToBounds()) { - setFlag(QGraphicsItem::ItemClipsToShape, m_layer->masksToBounds()); - setFlag(QGraphicsItem::ItemClipsChildrenToShape, m_layer->masksToBounds()); - } - - if ((m_changeMask & ContentsOpaqueChange) && m_state.contentsOpaque != m_layer->contentsOpaque()) - prepareGeometryChange(); - -#ifndef QT_NO_GRAPHICSEFFECT - if (m_maskEffect) - m_maskEffect.data()->update(); - else -#endif - if (m_changeMask & DisplayChange) { -#ifndef QT_GRAPHICS_LAYER_NO_RECACHE_ON_DISPLAY_CHANGE - // Recache now: all the content is ready and we don't want to wait until the paint event. - // We only need to do this for HTML content, there's no point in caching directly composited - // content like images or solid rectangles. - if (m_pendingContent.contentType == HTMLContentType && allowAcceleratedCompositingCache()) - recache(m_pendingContent.regionToUpdate); -#endif - update(m_pendingContent.regionToUpdate.boundingRect()); - m_pendingContent.regionToUpdate = QRegion(); - } - - if ((m_changeMask & BackgroundColorChange) - && (m_pendingContent.backgroundColor != m_currentContent.backgroundColor)) - update(); - - m_state.maskLayer = m_layer->maskLayer(); - m_state.pos = m_layer->position(); - m_state.anchorPoint = m_layer->anchorPoint(); - m_state.size = m_layer->size(); - m_state.transform = m_layer->transform(); - m_state.contentsOrientation =m_layer->contentsOrientation(); - m_state.opacity = m_layer->opacity(); - m_state.contentsRect = m_layer->contentsRect(); - m_state.preserves3D = m_layer->preserves3D(); - m_state.masksToBounds = m_layer->masksToBounds(); - m_state.drawsContent = m_layer->drawsContent(); - m_state.contentsOpaque = m_layer->contentsOpaque(); - m_state.backfaceVisibility = m_layer->backfaceVisibility(); - m_state.childrenTransform = m_layer->childrenTransform(); - m_currentContent.pixmap = m_pendingContent.pixmap; - m_currentContent.contentType = m_pendingContent.contentType; - m_currentContent.mediaLayer = m_pendingContent.mediaLayer; - m_currentContent.backgroundColor = m_pendingContent.backgroundColor; - m_currentContent.contentsBackgroundColor = m_pendingContent.contentsBackgroundColor; - m_pendingContent.regionToUpdate = QRegion(); - m_changeMask = NoChanges; - -afterLayerChanges: - if (forceUpdateTransform) - updateTransform(); - - if (!recursive) - return; - - QList<QGraphicsItem*> children = childItems(); - if (m_state.maskLayer) - children.append(m_state.maskLayer->platformLayer()); - - QList<QGraphicsItem*>::const_iterator it; - for (it = children.constBegin(); it != children.constEnd(); ++it) { - if (QGraphicsItem* item = *it) { - if (GraphicsLayerQtImpl* layer = toGraphicsLayerQtImpl(item)) - layer->flushChanges(true, forceUpdateTransform); - } - } -} - -#if USE(TILED_BACKING_STORE) -/* \reimp (TiledBackingStoreClient.h) -*/ -void GraphicsLayerQtImpl::tiledBackingStorePaintBegin() -{ -} - -/* \reimp (TiledBackingStoreClient.h) -*/ -void GraphicsLayerQtImpl::tiledBackingStorePaint(GraphicsContext* gc, const IntRect& rect) -{ - m_layer->paintGraphicsLayerContents(*gc, rect); -} - -/* \reimp (TiledBackingStoreClient.h) -*/ -void GraphicsLayerQtImpl::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea) -{ - for (int i = 0; i < paintedArea.size(); ++i) - update(QRectF(paintedArea[i])); -} - -/* \reimp (TiledBackingStoreClient.h) -*/ -IntRect GraphicsLayerQtImpl::tiledBackingStoreContentsRect() -{ - return m_layer->contentsRect(); -} - -/* \reimp (TiledBackingStoreClient.h) -*/ -Color GraphicsLayerQtImpl::tiledBackingStoreBackgroundColor() const -{ - if (m_currentContent.contentType == PixmapContentType && !m_currentContent.pixmap.hasAlphaChannel()) - return Color(0, 0, 0); - // We return a transparent color so that the tiles initialize with alpha. - return Color(0, 0, 0, 0); -} - -IntRect GraphicsLayerQtImpl::tiledBackingStoreVisibleRect() -{ - const QGraphicsView* view = scene()->views().isEmpty() ? 0 : scene()->views().first(); - if (!view) - return mapFromScene(scene()->sceneRect()).boundingRect().toAlignedRect(); - - // All we get is the viewport's visible region. We have to map it to the scene and then to item coordinates. - return mapFromScene(view->mapToScene(view->viewport()->visibleRegion().boundingRect()).boundingRect()).boundingRect().toAlignedRect(); -} -#endif - -void GraphicsLayerQtImpl::notifyAnimationStarted() -{ - // WebCore notifies javascript when the animation starts. Here we're letting it know. - m_layer->client()->notifyAnimationStarted(m_layer, /* DOM time */ WTF::currentTime()); -} - -GraphicsLayerQt::GraphicsLayerQt(GraphicsLayerClient* client) - : GraphicsLayer(client) - , m_impl(adoptPtr(new GraphicsLayerQtImpl(this))) -{ -} - -GraphicsLayerQt::~GraphicsLayerQt() -{ - // Do cleanup while we can still safely call methods on the derived class. - willBeDestroyed(); -} - -void GraphicsLayerQt::willBeDestroyed() -{ - m_impl = nullptr; - GraphicsLayer::willBeDestroyed(); -} - -// This is the hook for WebCore compositor to know that Qt implements compositing with GraphicsLayerQt. -PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) -{ - return adoptPtr(new GraphicsLayerQt(client)); -} - -/* \reimp (GraphicsLayer.h): The current size might change, thus we need to update the whole display. -*/ -void GraphicsLayerQt::setNeedsDisplay() -{ - m_impl->m_pendingContent.regionToUpdate = QRegion(QRect(QPoint(0, 0), QSize(size().width(), size().height()))); - m_impl->notifyChange(GraphicsLayerQtImpl::DisplayChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setNeedsDisplayInRect(const FloatRect& rect) -{ - m_impl->m_pendingContent.regionToUpdate |= QRectF(rect).toAlignedRect(); - m_impl->notifyChange(GraphicsLayerQtImpl::DisplayChange); -} - -void GraphicsLayerQt::setContentsNeedsDisplay() -{ - switch (m_impl->m_pendingContent.contentType) { - case GraphicsLayerQtImpl::MediaContentType: - if (!m_impl->m_pendingContent.mediaLayer) - return; - m_impl->m_pendingContent.mediaLayer.data()->update(); - break; - default: - setNeedsDisplay(); - break; - } -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setName(const String& name) -{ - m_impl->setObjectName(name); - GraphicsLayer::setName(name); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setParent(GraphicsLayer* layer) -{ - m_impl->notifyChange(GraphicsLayerQtImpl::ParentChange); - GraphicsLayer::setParent(layer); -} - -/* \reimp (GraphicsLayer.h) -*/ -bool GraphicsLayerQt::setChildren(const Vector<GraphicsLayer*>& children) -{ - m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); - return GraphicsLayer::setChildren(children); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::addChild(GraphicsLayer* layer) -{ - m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); - GraphicsLayer::addChild(layer); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::addChildAtIndex(GraphicsLayer* layer, int index) -{ - GraphicsLayer::addChildAtIndex(layer, index); - m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling) -{ - GraphicsLayer::addChildAbove(layer, sibling); - m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling) -{ - - GraphicsLayer::addChildBelow(layer, sibling); - m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -bool GraphicsLayerQt::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) -{ - if (GraphicsLayer::replaceChild(oldChild, newChild)) { - m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); - return true; - } - - return false; -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::removeFromParent() -{ - if (parent()) - m_impl->notifyChange(GraphicsLayerQtImpl::ParentChange); - GraphicsLayer::removeFromParent(); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setMaskLayer(GraphicsLayer* value) -{ - if (value == maskLayer()) - return; - GraphicsLayer::setMaskLayer(value); - m_impl->notifyChange(GraphicsLayerQtImpl::MaskLayerChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setPosition(const FloatPoint& value) -{ - if (value == position()) - return; - GraphicsLayer::setPosition(value); - m_impl->notifyChange(GraphicsLayerQtImpl::PositionChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setAnchorPoint(const FloatPoint3D& value) -{ - if (value == anchorPoint()) - return; - GraphicsLayer::setAnchorPoint(value); - m_impl->notifyChange(GraphicsLayerQtImpl::AnchorPointChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setSize(const FloatSize& value) -{ - if (value == size()) - return; - GraphicsLayer::setSize(value); - m_impl->notifyChange(GraphicsLayerQtImpl::SizeChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setTransform(const TransformationMatrix& value) -{ - if (value == transform()) - return; - GraphicsLayer::setTransform(value); - m_impl->notifyChange(GraphicsLayerQtImpl::TransformChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setChildrenTransform(const TransformationMatrix& value) -{ - if (value == childrenTransform()) - return; - GraphicsLayer::setChildrenTransform(value); - m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenTransformChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setPreserves3D(bool value) -{ - if (value == preserves3D()) - return; - GraphicsLayer::setPreserves3D(value); - m_impl->notifyChange(GraphicsLayerQtImpl::Preserves3DChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setMasksToBounds(bool value) -{ - if (value == masksToBounds()) - return; - GraphicsLayer::setMasksToBounds(value); - m_impl->notifyChange(GraphicsLayerQtImpl::MasksToBoundsChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setDrawsContent(bool value) -{ - if (value == drawsContent()) - return; - m_impl->notifyChange(GraphicsLayerQtImpl::DrawsContentChange); - GraphicsLayer::setDrawsContent(value); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setBackgroundColor(const Color& value) -{ - if (value == m_impl->m_pendingContent.backgroundColor) - return; - m_impl->m_pendingContent.backgroundColor = value; - GraphicsLayer::setBackgroundColor(value); - m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::clearBackgroundColor() -{ - if (!m_impl->m_pendingContent.backgroundColor.isValid()) - return; - m_impl->m_pendingContent.backgroundColor = QColor(); - GraphicsLayer::clearBackgroundColor(); - m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setContentsOpaque(bool value) -{ - if (value == contentsOpaque()) - return; - m_impl->notifyChange(GraphicsLayerQtImpl::ContentsOpaqueChange); - GraphicsLayer::setContentsOpaque(value); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setBackfaceVisibility(bool value) -{ - if (value == backfaceVisibility()) - return; - GraphicsLayer::setBackfaceVisibility(value); - m_impl->notifyChange(GraphicsLayerQtImpl::BackfaceVisibilityChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setOpacity(float value) -{ - if (value == opacity()) - return; - GraphicsLayer::setOpacity(value); - m_impl->notifyChange(GraphicsLayerQtImpl::OpacityChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setContentsRect(const IntRect& value) -{ - if (value == contentsRect()) - return; - GraphicsLayer::setContentsRect(value); - m_impl->notifyChange(GraphicsLayerQtImpl::ContentsRectChange); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setContentsToImage(Image* image) -{ - m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange); - m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::HTMLContentType; - GraphicsLayer::setContentsToImage(image); - if (image) { - QPixmap* pxm = image->nativeImageForCurrentFrame(); - if (pxm) { - m_impl->m_pendingContent.pixmap = *pxm; - m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::PixmapContentType; - return; - } - } - m_impl->m_pendingContent.pixmap = QPixmap(); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setContentsToBackgroundColor(const Color& color) -{ - m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange); - m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::ColorContentType; - m_impl->m_pendingContent.contentsBackgroundColor = QColor(color); - GraphicsLayer::setContentsToBackgroundColor(color); -} - -void GraphicsLayerQt::setContentsToMedia(PlatformLayer* media) -{ - if (media) { - m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::MediaContentType; - m_impl->m_pendingContent.mediaLayer = media->toGraphicsObject(); - } else - m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::HTMLContentType; - - m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange); - GraphicsLayer::setContentsToMedia(media); -} - -void GraphicsLayerQt::setContentsToCanvas(PlatformLayer* canvas) -{ - setContentsToMedia(canvas); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::setContentsOrientation(CompositingCoordinatesOrientation orientation) -{ - m_impl->notifyChange(GraphicsLayerQtImpl::ContentsOrientationChange); - GraphicsLayer::setContentsOrientation(orientation); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::distributeOpacity(float o) -{ - m_impl->notifyChange(GraphicsLayerQtImpl::OpacityChange); - m_impl->m_state.distributeOpacity = true; -} - -/* \reimp (GraphicsLayer.h) -*/ -float GraphicsLayerQt::accumulatedOpacity() const -{ - return m_impl->effectiveOpacity(); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::syncCompositingState(const FloatRect&) -{ - m_impl->flushChanges(); - GraphicsLayer::syncCompositingState(); -} - -/* \reimp (GraphicsLayer.h) -*/ -void GraphicsLayerQt::syncCompositingStateForThisLayerOnly() -{ - // We can't call flushChanges recursively here - m_impl->flushChanges(false); - GraphicsLayer::syncCompositingStateForThisLayerOnly(); -} - -/* \reimp (GraphicsLayer.h) -*/ -PlatformLayer* GraphicsLayerQt::platformLayer() const -{ - return m_impl.get(); -} - -// Now we start dealing with WebCore animations translated to Qt animations - -template <typename T> -struct KeyframeValueQt { - const TimingFunction* timingFunction; - T value; -}; - -/* Copied from AnimationBase.cpp -*/ -static inline double solveEpsilon(double duration) -{ - return 1.0 / (200.0 * duration); -} - -static inline double solveCubicBezierFunction(qreal p1x, qreal p1y, qreal p2x, qreal p2y, double t, double duration) -{ - UnitBezier bezier(p1x, p1y, p2x, p2y); - return bezier.solve(t, solveEpsilon(duration)); -} - -static inline double solveStepsFunction(int numSteps, bool stepAtStart, double t) -{ - if (stepAtStart) - return qMin(1.0, (floor(numSteps * t) + 1) / numSteps); - return floor(numSteps * t) / numSteps; -} - -static inline qreal applyTimingFunction(const TimingFunction* timingFunction, qreal progress, double duration) -{ - // We want the timing function to be as close as possible to what the web-developer intended, so - // we're using the same function used by WebCore when compositing is disabled. Using easing-curves - // would probably work for some of the cases, but wouldn't really buy us anything as we'd have to - // convert the bezier function back to an easing curve. - - if (timingFunction->isCubicBezierTimingFunction()) { - const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction); - return solveCubicBezierFunction(ctf->x1(), - ctf->y1(), - ctf->x2(), - ctf->y2(), - double(progress), double(duration) / 1000); - } else if (timingFunction->isStepsTimingFunction()) { - const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(timingFunction); - return solveStepsFunction(stf->numberOfSteps(), stf->stepAtStart(), double(progress)); - } else - return progress; -} - -// Helper functions to safely get a value out of WebCore's AnimationValue*. - -#ifndef QT_NO_ANIMATION -static void webkitAnimationToQtAnimationValue(const AnimationValue* animationValue, TransformOperations& transformOperations) -{ - transformOperations = TransformOperations(); - if (!animationValue) - return; - - if (const TransformOperations* ops = static_cast<const TransformAnimationValue*>(animationValue)->value()) - transformOperations = *ops; -} - -static void webkitAnimationToQtAnimationValue(const AnimationValue* animationValue, qreal& realValue) -{ - realValue = animationValue ? static_cast<const FloatAnimationValue*>(animationValue)->value() : 0; -} - -// We put a bit of the functionality in a base class to allow casting and to save some code size. - -class AnimationQtBase : public QAbstractAnimation { -public: - AnimationQtBase(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name) - : QAbstractAnimation(0) - , m_layer(layer) - , m_boxSize(boxSize) - , m_duration(anim->duration() * 1000) - , m_isAlternate(anim->direction() == Animation::AnimationDirectionAlternate) - , m_webkitPropertyID(values.property()) - , m_webkitAnimation(anim) - , m_keyframesName(name) - , m_fillsForwards(false) - { - } - - - virtual AnimatedPropertyID animatedProperty() const = 0; - - virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) - { - QAbstractAnimation::updateState(newState, oldState); - - // For some reason we have do this asynchronously - or the animation won't work. - if (newState == Running && oldState == Stopped && m_layer.data()) - m_layer.data()->notifyAnimationStartedAsync(); - } - - virtual int duration() const { return m_duration; } - - QWeakPointer<GraphicsLayerQtImpl> m_layer; - IntSize m_boxSize; - int m_duration; - bool m_isAlternate; - AnimatedPropertyID m_webkitPropertyID; - - // We might need this in case the same animation is added again (i.e. resumed by WebCore). - const Animation* m_webkitAnimation; - QString m_keyframesName; - bool m_fillsForwards; -}; - -// We'd rather have a templatized QAbstractAnimation than QPropertyAnimation / QVariantAnimation; -// Since we know the types that we're dealing with, the QObject/QProperty/QVariant abstraction -// buys us very little in this case, for too much overhead. -template <typename T> -class AnimationQt : public AnimationQtBase { - -public: - AnimationQt(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name) - : AnimationQtBase(layer, values, boxSize, anim, name) - { - // Copying those WebCore structures is not trivial, we have to do it like this. - for (size_t i = 0; i < values.size(); ++i) { - const AnimationValue* animationValue = values.at(i); - KeyframeValueQt<T> keyframeValue; - if (animationValue->timingFunction()) - keyframeValue.timingFunction = animationValue->timingFunction(); - else - keyframeValue.timingFunction = anim->timingFunction().get(); - webkitAnimationToQtAnimationValue(animationValue, keyframeValue.value); - m_keyframeValues[animationValue->keyTime()] = keyframeValue; - } - } - -protected: - - // This is the part that differs between animated properties. - virtual void applyFrame(const T& fromValue, const T& toValue, qreal progress) = 0; - - virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) - { -#if QT_DEBUG_FPS - if (newState == Running && oldState == Stopped) { - qDebug("Animation Started!"); - m_fps.frames = 0; - m_fps.duration.start(); - } else if (newState == Stopped && oldState == Running) { - const int duration = m_fps.duration.elapsed(); - qDebug("Animation Ended! %dms [%f FPS]", duration, - (1000 / (((float)duration) / m_fps.frames))); - } -#endif - AnimationQtBase::updateState(newState, oldState); - } - - virtual void updateCurrentTime(int currentTime) - { - if (!m_layer) - return; - - qreal progress = qreal(currentLoopTime()) / duration(); - - if (m_isAlternate && currentLoop()%2) - progress = 1-progress; - - if (m_keyframeValues.isEmpty()) - return; - - // Find the current from-to keyframes in our little map. - typename QMap<qreal, KeyframeValueQt<T> >::iterator it = m_keyframeValues.find(progress); - - // We didn't find an exact match, we try the closest match (lower bound). - if (it == m_keyframeValues.end()) - it = m_keyframeValues.lowerBound(progress)-1; - - // We didn't find any match; use the first keyframe. - if (it == m_keyframeValues.end()) - it = m_keyframeValues.begin(); - - typename QMap<qreal, KeyframeValueQt<T> >::iterator it2 = it + 1; - if (it2 == m_keyframeValues.end()) - it2 = it; - const KeyframeValueQt<T>& fromKeyframe = it.value(); - const KeyframeValueQt<T>& toKeyframe = it2.value(); - - const TimingFunction* timingFunc = fromKeyframe.timingFunction; - const T& fromValue = fromKeyframe.value; - const T& toValue = toKeyframe.value; - - // Now we have a source keyframe, origin keyframe and a timing function. - // We can now process the progress and apply the frame. - progress = (!progress || progress == 1 || it.key() == it2.key()) ? - progress : applyTimingFunction(timingFunc, (progress - it.key()) / (it2.key() - it.key()), duration()); - applyFrame(fromValue, toValue, progress); -#if QT_DEBUG_FPS - ++m_fps.frames; -#endif - } - - QMap<qreal, KeyframeValueQt<T> > m_keyframeValues; -#if QT_DEBUG_FPS - struct { - QTime duration; - int frames; - } m_fps; -#endif -}; - -class TransformAnimationQt : public AnimationQt<TransformOperations> { -public: - TransformAnimationQt(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name) - : AnimationQt<TransformOperations>(layer, values, boxSize, anim, name) - { - } - - ~TransformAnimationQt() - { - if (m_fillsForwards) - setCurrentTime(1); - } - - virtual AnimatedPropertyID animatedProperty() const { return AnimatedPropertyWebkitTransform; } - - // The idea is that we let WebCore manage the transform operations and Qt just manage the - // animation heartbeat and the bottom-line QTransform. We gain performance, not by using - // Transform instead of TransformationMatrix, but by proper caching of items that are - // expensive for WebCore to render. We want the rest to be as close to WebCore's idea as possible. - virtual void applyFrame(const TransformOperations& sourceOperations, const TransformOperations& targetOperations, qreal progress) - { - TransformationMatrix transformMatrix; - - bool validTransformLists = true; - const int sourceOperationCount = sourceOperations.size(); - if (sourceOperationCount) { - if (targetOperations.size() != sourceOperationCount) - validTransformLists = false; - else { - for (size_t j = 0; j < sourceOperationCount && validTransformLists; ++j) { - if (!sourceOperations.operations()[j]->isSameType(*targetOperations.operations()[j])) - validTransformLists = false; - } - } - } - - if (validTransformLists) { - for (size_t i = 0; i < targetOperations.size(); ++i) - targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize); - } else { - targetOperations.apply(m_boxSize, transformMatrix); - transformMatrix.blend(m_sourceMatrix, progress); - } - - m_layer.data()->m_layer->setTransform(transformMatrix); - // We force the actual opacity change, otherwise it would be ignored because of the animation. - m_layer.data()->setBaseTransform(transformMatrix); - } - - virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) - { - AnimationQt<TransformOperations>::updateState(newState, oldState); - if (!m_layer) - return; - - m_layer.data()->flushChanges(true); - - // To increase FPS, we use a less accurate caching mechanism while animation is going on - // this is a UX choice that should probably be customizable. - if (newState == QAbstractAnimation::Running) { - m_sourceMatrix = m_layer.data()->m_layer->transform(); - m_layer.data()->m_transformAnimationRunning = true; - } else if (newState == QAbstractAnimation::Stopped) { - // We update the transform back to the default. This already takes fill-modes into account. - m_layer.data()->m_transformAnimationRunning = false; - if (m_layer && m_layer.data()->m_layer) - m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform()); - } - } - - TransformationMatrix m_sourceMatrix; -}; - -class OpacityAnimationQt : public AnimationQt<qreal> { -public: - OpacityAnimationQt(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString& name) - : AnimationQt<qreal>(layer, values, boxSize, anim, name) - { - } - - ~OpacityAnimationQt() - { - if (m_fillsForwards) - setCurrentTime(1); - } - - virtual AnimatedPropertyID animatedProperty() const { return AnimatedPropertyOpacity; } - - virtual void applyFrame(const qreal& fromValue, const qreal& toValue, qreal progress) - { - qreal opacity = qBound(qreal(0), fromValue + (toValue - fromValue) * progress, qreal(1)); - - // FIXME: This is a hack, due to a probable QGraphicsScene bug. - // Without this the opacity change doesn't always have immediate effect. - if (m_layer.data()->scene() && !m_layer.data()->opacity() && opacity) - m_layer.data()->scene()->update(); - - m_layer.data()->m_layer->setOpacity(opacity); - // We force the actual opacity change, otherwise it would be ignored because of the animation. - m_layer.data()->setOpacity(opacity); - } - - virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) - { - AnimationQt<qreal>::updateState(newState, oldState); - - if (m_layer) - m_layer.data()->m_opacityAnimationRunning = (newState == QAbstractAnimation::Running); - - // If stopped, we update the opacity back to the default. This already takes fill-modes into account. - if (newState == Stopped) - if (m_layer && m_layer.data()->m_layer) - m_layer.data()->setOpacity(m_layer.data()->m_layer->opacity()); - - } -}; - -bool GraphicsLayerQt::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset) -{ - if (!anim->duration() || !anim->iterationCount()) - return false; - - AnimationQtBase* newAnim = 0; - - // Fixed: we might already have the Qt animation object associated with this WebCore::Animation object. - QList<QWeakPointer<QAbstractAnimation> >::iterator it; - for (it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { - if (*it) { - AnimationQtBase* curAnimation = static_cast<AnimationQtBase*>(it->data()); - if (curAnimation && curAnimation->m_webkitAnimation == anim - && values.property() == curAnimation->animatedProperty()) { - newAnim = curAnimation; - break; - } - } - } - - if (!newAnim) { - switch (values.property()) { - case AnimatedPropertyOpacity: - newAnim = new OpacityAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName); - break; - case AnimatedPropertyWebkitTransform: - newAnim = new TransformAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName); - break; - default: - return false; - } - - // We make sure WebCore::Animation and QAnimation are on the same terms. - newAnim->setLoopCount(anim->iterationCount()); - newAnim->m_fillsForwards = anim->fillsForwards(); - m_impl->m_animations.append(QWeakPointer<QAbstractAnimation>(newAnim)); - QObject::connect(&m_impl->m_suspendTimer, SIGNAL(timeout()), newAnim, SLOT(resume())); - } - - // Flush now to avoid flicker. - m_impl->flushChanges(false); - - // Qhen fill-mode is backwards/both, we set the value to 0 before the delay takes place. - if (anim->fillsBackwards()) - newAnim->setCurrentTime(0); - - newAnim->start(); - - // We synchronize the animation's clock to WebCore's timeOffset. - newAnim->setCurrentTime(timeOffset * 1000); - - // We don't need to manage the animation object's lifecycle: - // WebCore would call removeAnimations when it's time to delete. - - return true; -} - -void GraphicsLayerQt::removeAnimationsForProperty(AnimatedPropertyID id) -{ - QList<QWeakPointer<QAbstractAnimation> >::iterator it; - for (it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { - if (!(*it)) - continue; - - AnimationQtBase* anim = static_cast<AnimationQtBase*>(it->data()); - if (anim && anim->m_webkitPropertyID == id) { - // We need to stop the animation right away, or it might flicker before it's deleted. - anim->stop(); - anim->deleteLater(); - it = m_impl->m_animations.erase(it); - --it; - } - } -} - -void GraphicsLayerQt::removeAnimationsForKeyframes(const String& name) -{ - QList<QWeakPointer<QAbstractAnimation> >::iterator it; - for (it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { - if (!(*it)) - continue; - - AnimationQtBase* anim = static_cast<AnimationQtBase*>(it->data()); - if (anim && anim->m_keyframesName == QString(name)) { - // We need to stop the animation right away, or it might flicker before it's deleted. - anim->stop(); - anim->deleteLater(); - it = m_impl->m_animations.erase(it); - --it; - } - } -} - -void GraphicsLayerQt::pauseAnimation(const String& name, double timeOffset) -{ - QList<QWeakPointer<QAbstractAnimation> >::iterator it; - for (it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { - if (!(*it)) - continue; - - AnimationQtBase* anim = static_cast<AnimationQtBase*>(it->data()); - if (anim && anim->m_keyframesName == QString(name)) { - // we synchronize the animation's clock to WebCore's timeOffset - anim->setCurrentTime(timeOffset * 1000); - anim->pause(); - } - } -} - -void GraphicsLayerQt::suspendAnimations(double time) -{ - if (m_impl->m_suspendTimer.isActive()) { - m_impl->m_suspendTimer.stop(); - m_impl->m_suspendTimer.start(time * 1000); - } else { - QList<QWeakPointer<QAbstractAnimation> >::iterator it; - for (it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { - if (QAbstractAnimation* anim = it->data()) - anim->pause(); - } - } -} - -void GraphicsLayerQt::resumeAnimations() -{ - if (m_impl->m_suspendTimer.isActive()) { - m_impl->m_suspendTimer.stop(); - QList<QWeakPointer<QAbstractAnimation> >::iterator it; - for (it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { - if (QAbstractAnimation* anim = it->data()) - anim->resume(); - } - } -} - -#endif // QT_NO_ANIMATION -} - -#include <GraphicsLayerQt.moc> - - -#endif // QT_NO_GRAPHICSVIEW diff --git a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h deleted file mode 100644 index ea2bdae68..000000000 --- a/Source/WebCore/platform/graphics/qt/GraphicsLayerQt.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef GraphicsLayerQt_h -#define GraphicsLayerQt_h - -#include "GraphicsLayer.h" -#include "GraphicsLayerClient.h" - -#if !defined(QT_NO_GRAPHICSVIEW) - -namespace WebCore { - -class GraphicsLayerQtImpl; - -class GraphicsLayerQt : public GraphicsLayer { - friend class GraphicsLayerQtImpl; - -public: - GraphicsLayerQt(GraphicsLayerClient*); - virtual ~GraphicsLayerQt(); - - // reimps from GraphicsLayer.h - virtual PlatformLayer* platformLayer() const; - virtual void setNeedsDisplay(); - virtual void setNeedsDisplayInRect(const FloatRect&); - virtual void setParent(GraphicsLayer* layer); - virtual void setName(const String& name); - virtual bool setChildren(const Vector<GraphicsLayer*>&); - virtual void addChild(GraphicsLayer*); - virtual void addChildAtIndex(GraphicsLayer*, int index); - virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling); - virtual void addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling); - virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild); - virtual void removeFromParent(); - virtual void setMaskLayer(GraphicsLayer* layer); - virtual void setPosition(const FloatPoint& p); - virtual void setAnchorPoint(const FloatPoint3D& p); - virtual void setSize(const FloatSize& size); - virtual void setTransform(const TransformationMatrix& t); - virtual void setChildrenTransform(const TransformationMatrix& t); - virtual void setPreserves3D(bool b); - virtual void setMasksToBounds(bool b); - virtual void setDrawsContent(bool b); - virtual void setBackgroundColor(const Color&); - virtual void clearBackgroundColor(); - virtual void setContentsOpaque(bool b); - virtual void setBackfaceVisibility(bool b); - virtual void setOpacity(float opacity); - virtual void setContentsRect(const IntRect& r); -#ifndef QT_NO_ANIMATION - virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, const String& keyframesName, double timeOffset); - virtual void removeAnimationsForProperty(AnimatedPropertyID); - virtual void removeAnimationsForKeyframes(const String& keyframesName); - virtual void pauseAnimation(const String& keyframesName, double timeOffset); - virtual void suspendAnimations(double time); - virtual void resumeAnimations(); -#endif // QT_NO_ANIMATION - virtual void setContentsToImage(Image*); - virtual void setContentsNeedsDisplay(); - virtual void setContentsToMedia(PlatformLayer*); - virtual void setContentsToCanvas(PlatformLayer*); - virtual void setContentsToBackgroundColor(const Color&); - virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation); - virtual void distributeOpacity(float); - virtual float accumulatedOpacity() const; - virtual void syncCompositingState(const FloatRect&); - virtual void syncCompositingStateForThisLayerOnly(); - -private: - virtual void willBeDestroyed(); - - OwnPtr<GraphicsLayerQtImpl> m_impl; -}; - -} -#endif -#endif // GraphicsLayerQt_h diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 794bc1036..5ad418c23 100644 --- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -52,7 +52,7 @@ #include <wtf/HashSet.h> #include <wtf/text/CString.h> -#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +#if USE(ACCELERATED_COMPOSITING) #include "texmap/TextureMapper.h" #endif @@ -613,7 +613,7 @@ void MediaPlayerPrivateQt::repaint() } -#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +#if USE(ACCELERATED_COMPOSITING) void MediaPlayerPrivateQt::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, BitmapTexture*) const { GraphicsContext* context = textureMapper->graphicsContext(); diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h index a129e5de5..0e2cf0b92 100644 --- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h +++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h @@ -31,14 +31,14 @@ class QGraphicsVideoItem; class QGraphicsScene; QT_END_NAMESPACE -#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +#if USE(ACCELERATED_COMPOSITING) #include "TextureMapper.h" #endif namespace WebCore { class MediaPlayerPrivateQt : public QObject, public MediaPlayerPrivateInterface -#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +#if USE(ACCELERATED_COMPOSITING) , public TextureMapperPlatformLayer #endif { @@ -101,7 +101,6 @@ public: bool supportsFullscreen() const { return true; } #if USE(ACCELERATED_COMPOSITING) -#if USE(TEXTURE_MAPPER) // whether accelerated rendering is supported by the media engine for the current media. virtual bool supportsAcceleratedRendering() const { return false; } // called when the rendering system flips the into or out of accelerated rendering mode. @@ -109,11 +108,6 @@ public: // Const-casting here is safe, since all of TextureMapperPlatformLayer's functions are const.g virtual PlatformLayer* platformLayer() const { return 0; } virtual void paintToTextureMapper(TextureMapper*, const FloatRect& targetRect, const TransformationMatrix&, float opacity, BitmapTexture* mask) const; -#else - virtual bool supportsAcceleratedRendering() const { return false; } - virtual void acceleratedRenderingStateChanged() { } - virtual PlatformLayer* platformLayer() const { return 0; } -#endif #endif virtual PlatformMedia platformMedia() const; diff --git a/Source/WebCore/platform/graphics/qt/PatternQt.cpp b/Source/WebCore/platform/graphics/qt/PatternQt.cpp index af7b12858..7aae62599 100644 --- a/Source/WebCore/platform/graphics/qt/PatternQt.cpp +++ b/Source/WebCore/platform/graphics/qt/PatternQt.cpp @@ -31,7 +31,7 @@ namespace WebCore { -QBrush Pattern::createPlatformPattern(const AffineTransform&) const +QBrush Pattern::createPlatformPattern() const { QPixmap* pixmap = tileImage()->nativeImageForCurrentFrame(); if (!pixmap) diff --git a/Source/WebCore/platform/graphics/qt/StillImageQt.h b/Source/WebCore/platform/graphics/qt/StillImageQt.h index 368266a39..26df4714e 100644 --- a/Source/WebCore/platform/graphics/qt/StillImageQt.h +++ b/Source/WebCore/platform/graphics/qt/StillImageQt.h @@ -58,7 +58,7 @@ namespace WebCore { private: StillImage(const QPixmap& pixmap); StillImage(const QPixmap* pixmap); - ~StillImage(); + virtual ~StillImage(); const QPixmap* m_pixmap; bool m_ownsPixmap; diff --git a/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp b/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp index 66882cf4a..d18e53ed9 100644 --- a/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp @@ -32,21 +32,31 @@ #include "GlyphPageTreeNode.h" #include "Font.h" +#if !USE(HARFBUZZ_NG) #include "HarfBuzzSkia.h" +#else +#include "NotImplemented.h" +#endif #include "SimpleFontData.h" #include "SkTemplates.h" #include "SkPaint.h" #include "SkUtils.h" +#if !USE(HARFBUZZ_NG) extern "C" { #include "harfbuzz-shaper.h" } +#endif namespace WebCore { static int substituteWithVerticalGlyphs(const SimpleFontData* fontData, uint16_t* glyphs, unsigned bufferLength) { +#if USE(HARFBUZZ_NG) + notImplemented(); + return 0xFFFF; +#else HB_FaceRec_* hbFace = fontData->platformData().harfbuzzFace()->face(); if (!hbFace->gsub) { // if there is no GSUB table, treat it as not covered @@ -73,6 +83,7 @@ static int substituteWithVerticalGlyphs(const SimpleFontData* fontData, uint16_t glyphs[i] = static_cast<Glyph>(buffer->out_string[i].gindex); } return error; +#endif } bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp index 019037c45..17ad83d8f 100644 --- a/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp @@ -26,7 +26,7 @@ #include "config.h" -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include "GraphicsContext3D.h" @@ -92,4 +92,4 @@ bool GraphicsContext3D::getImageData(Image* image, } // namespace WebCore -#endif // ENABLE(WEBGL) +#endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp index 81dfa3aa1..6a4bcb0a3 100644 --- a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -251,9 +251,18 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag ResamplingMode resampling; if (platformContext->isAccelerated()) resampling = RESAMPLE_LINEAR; - else - resampling = platformContext->printing() ? RESAMPLE_NONE : - computeResamplingMode(platformContext, bitmap, srcRect.width(), srcRect.height(), SkScalarToFloat(destRect.width()), SkScalarToFloat(destRect.height())); + else if (platformContext->printing()) + resampling = RESAMPLE_NONE; + else { + // Take into account scale applied to the canvas when computing sampling mode (e.g. CSS scale or page scale). + SkRect destRectTarget = destRect; + if (!(canvas->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask))) + canvas->getTotalMatrix().mapRect(&destRectTarget, destRect); + + resampling = computeResamplingMode(platformContext, bitmap, srcRect.width(), srcRect.height(), + SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height())); + } + 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 diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h index c9decdeee..403e5492b 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h @@ -26,10 +26,6 @@ #include "Image.h" #include "TextureMapperLayer.h" -#if ENABLE(WEBGL) -#include "GraphicsContext3D.h" -#endif - namespace WebCore { class TextureMapperLayer; diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h index f1da4243f..7793f70ad 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h @@ -112,8 +112,18 @@ public: static PassOwnPtr<TextureMapper> create(AccelerationMode newMode = SoftwareMode); virtual ~TextureMapper() { } + enum ExposedEdges { + NoEdges = 0, + LeftEdge = 1 << 0, + RightEdge = 1 << 1, + TopEdge = 1 << 2, + BottomEdge = 1 << 3, + AllEdges = LeftEdge | RightEdge | TopEdge | BottomEdge, + }; + virtual void drawBorder(const Color&, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) = 0; - virtual void drawTexture(const BitmapTexture&, const FloatRect& target, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0f, const BitmapTexture* maskTexture = 0) = 0; + virtual void drawRepaintCounter(int value, int pointSize, const FloatPoint&, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) = 0; + virtual void drawTexture(const BitmapTexture&, const FloatRect& target, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0f, const BitmapTexture* maskTexture = 0, unsigned exposedEdges = AllEdges) = 0; // makes a surface the target for the following drawTexture calls. virtual void bindSurface(BitmapTexture* surface) = 0; diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp index 3f4ec6e94..efa659f84 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp @@ -87,10 +87,10 @@ void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* imag m_texture->updateContents(image, targetRect, sourceOffset); } -void TextureMapperTile::paint(TextureMapper* textureMapper, const TransformationMatrix& transform, float opacity, BitmapTexture* mask) +void TextureMapperTile::paint(TextureMapper* textureMapper, const TransformationMatrix& transform, float opacity, BitmapTexture* mask, const unsigned exposedEdges) { if (texture().get()) - textureMapper->drawTexture(*texture().get(), rect(), transform, opacity, mask); + textureMapper->drawTexture(*texture().get(), rect(), transform, opacity, mask, exposedEdges); } TextureMapperTiledBackingStore::TextureMapperTiledBackingStore() @@ -107,13 +107,27 @@ void TextureMapperTiledBackingStore::updateContentsFromImageIfNeeded(TextureMapp m_image.clear(); } +unsigned TextureMapperBackingStore::calculateExposedTileEdges(const FloatRect& totalRect, const FloatRect& tileRect) +{ + unsigned exposedEdges = TextureMapper::NoEdges; + if (!tileRect.x()) + exposedEdges |= TextureMapper::LeftEdge; + if (!tileRect.y()) + exposedEdges |= TextureMapper::TopEdge; + if (tileRect.width() + tileRect.x() >= totalRect.width()) + exposedEdges |= TextureMapper::RightEdge; + if (tileRect.height() + tileRect.y() >= totalRect.height()) + exposedEdges |= TextureMapper::BottomEdge; + return exposedEdges; +} + void TextureMapperTiledBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity, BitmapTexture* mask) { updateContentsFromImageIfNeeded(textureMapper); TransformationMatrix adjustedTransform = transform; adjustedTransform.multiply(TransformationMatrix::rectToRect(rect(), targetRect)); for (size_t i = 0; i < m_tiles.size(); ++i) { - m_tiles[i].paint(textureMapper, adjustedTransform, opacity, mask); + m_tiles[i].paint(textureMapper, adjustedTransform, opacity, mask, calculateExposedTileEdges(rect(), m_tiles[i].rect())); if (m_drawsDebugBorders) textureMapper->drawBorder(m_debugBorderColor, m_debugBorderWidth, m_tiles[i].rect(), adjustedTransform); } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h index 95abe5340..0f71c45b0 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h @@ -39,6 +39,9 @@ public: virtual PassRefPtr<BitmapTexture> texture() const = 0; virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float, BitmapTexture*) = 0; virtual ~TextureMapperBackingStore() { } + +protected: + static unsigned calculateExposedTileEdges(const FloatRect& totalRect, const FloatRect& tileRect); }; #if USE(GRAPHICS_SURFACE) @@ -82,7 +85,7 @@ public: inline void setRect(const FloatRect& rect) { m_rect = rect; } void updateContents(TextureMapper*, Image*, const IntRect&); - virtual void paint(TextureMapper*, const TransformationMatrix&, float, BitmapTexture*); + virtual void paint(TextureMapper*, const TransformationMatrix&, float, BitmapTexture*, const unsigned exposedEdges); virtual ~TextureMapperTile() { } TextureMapperTile(const FloatRect& rect) diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp index 6db7d6f0d..cca2e27ec 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp @@ -24,6 +24,7 @@ #include "GraphicsContext.h" #include "GraphicsContext3D.h" #include "Image.h" +#include "NotImplemented.h" #include "TextureMapperShaderManager.h" #include "Timer.h" #include <wtf/HashMap.h> @@ -236,6 +237,7 @@ TextureMapperGL::TextureMapperGL() : TextureMapper(OpenGLMode) , m_data(new TextureMapperGLData) , m_context(0) + , m_enableEdgeDistanceAntialiasing(false) { } @@ -304,19 +306,24 @@ void TextureMapperGL::endPainting() #endif } -void TextureMapperGL::drawRect(const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram* shaderProgram, GLenum drawingMode, bool needsBlending) +void TextureMapperGL::drawQuad(const DrawQuad& quadToDraw, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram* shaderProgram, GLenum drawingMode, bool needsBlending) { GL_CMD(glEnableVertexAttribArray(shaderProgram->vertexAttrib())); GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0)); - const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1}; - GL_CMD(glVertexAttribPointer(shaderProgram->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, unitRect)); + + const GLfloat quad[] = { + quadToDraw.targetRectMappedToUnitSquare.p1().x(), quadToDraw.targetRectMappedToUnitSquare.p1().y(), + quadToDraw.targetRectMappedToUnitSquare.p2().x(), quadToDraw.targetRectMappedToUnitSquare.p2().y(), + quadToDraw.targetRectMappedToUnitSquare.p3().x(), quadToDraw.targetRectMappedToUnitSquare.p3().y(), + quadToDraw.targetRectMappedToUnitSquare.p4().x(), quadToDraw.targetRectMappedToUnitSquare.p4().y() + }; + GL_CMD(glVertexAttribPointer(shaderProgram->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, quad)); TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multiply(modelViewMatrix).multiply(TransformationMatrix( - targetRect.width(), 0, 0, 0, - 0, targetRect.height(), 0, 0, + quadToDraw.originalTargetRect.width(), 0, 0, 0, + 0, quadToDraw.originalTargetRect.height(), 0, 0, 0, 0, 1, 0, - targetRect.x(), targetRect.y(), 0, 1)); - + quadToDraw.originalTargetRect.x(), quadToDraw.originalTargetRect.y(), 0, 1)); const GLfloat m4[] = { matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(), matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(), @@ -351,10 +358,42 @@ void TextureMapperGL::drawBorder(const Color& color, float width, const FloatRec alpha)); GL_CMD(glLineWidth(width)); - drawRect(targetRect, modelViewMatrix, program.get(), GL_LINE_LOOP, color.hasAlpha()); + drawQuad(targetRect, modelViewMatrix, program.get(), GL_LINE_LOOP, color.hasAlpha()); +} + +void TextureMapperGL::drawRepaintCounter(int value, int pointSize, const FloatPoint& targetPoint, const TransformationMatrix& modelViewMatrix) +{ +#if PLATFORM(QT) + QString counterString = QString::number(value); + + QFont font(QString::fromLatin1("Monospace"), pointSize, QFont::Bold); + font.setStyleHint(QFont::TypeWriter); + + QFontMetrics fontMetrics(font); + int width = fontMetrics.width(counterString) + 4; + int height = fontMetrics.height(); + + IntSize size(width, height); + IntRect sourceRect(IntPoint::zero(), size); + IntRect targetRect(roundedIntPoint(targetPoint), size); + + QImage image(size, QImage::Format_ARGB32_Premultiplied); + QPainter painter(&image); + painter.fillRect(sourceRect, Qt::blue); // Since we won't swap R+B for speed, this will paint red. + painter.setFont(font); + painter.setPen(Qt::white); + painter.drawText(2, height * 0.85, counterString); + + RefPtr<BitmapTexture> texture = acquireTextureFromPool(size); + const uchar* bits = image.bits(); + texture->updateContents(bits, sourceRect, IntPoint::zero(), image.bytesPerLine()); + drawTexture(*texture, targetRect, modelViewMatrix, 1.0f, 0, AllEdges); +#else + notImplemented(); +#endif } -void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* mask) +void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* mask, unsigned exposedEdges) { if (!texture.isValid()) return; @@ -363,7 +402,7 @@ void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect& return; const BitmapTextureGL& textureGL = static_cast<const BitmapTextureGL&>(texture); - drawTexture(textureGL.id(), textureGL.isOpaque() ? 0 : SupportsBlending, textureGL.size(), targetRect, matrix, opacity, mask); + drawTexture(textureGL.id(), textureGL.isOpaque() ? 0 : SupportsBlending, textureGL.size(), targetRect, matrix, opacity, mask, exposedEdges); } #if defined(GL_ARB_texture_rectangle) @@ -382,6 +421,7 @@ void TextureMapperGL::drawTextureRectangleARB(uint32_t texture, Flags flags, con GL_CMD(glUniform1i(program->sourceTextureLocation(), 0)); GL_CMD(glUniform1f(program->flipLocation(), !!(flags & ShouldFlipTexture))); + GL_CMD(glUniform2f(program->textureSizeLocation(), textureSize.width(), textureSize.height())); if (TextureMapperShaderProgram::isValidUniformLocation(program->opacityLocation())) GL_CMD(glUniform1f(program->opacityLocation(), opacity)); @@ -395,12 +435,16 @@ void TextureMapperGL::drawTextureRectangleARB(uint32_t texture, Flags flags, con } bool needsBlending = (flags & SupportsBlending) || opacity < 0.99 || maskTexture; - drawRect(targetRect, modelViewMatrix, program.get(), GL_TRIANGLE_FAN, needsBlending); + drawQuad(targetRect, modelViewMatrix, program.get(), GL_TRIANGLE_FAN, needsBlending); } #endif // defined(GL_ARB_texture_rectangle) -void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture) +void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const IntSize& /* textureSize */, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges) { + bool needsAntiliaing = m_enableEdgeDistanceAntialiasing && !modelViewMatrix.isIntegerTranslation(); + if (needsAntiliaing && drawTextureWithAntialiasing(texture, flags, targetRect, modelViewMatrix, opacity, maskTexture, exposedEdges)) + return; + RefPtr<TextureMapperShaderProgram> program; if (maskTexture) program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::OpacityAndMask); @@ -408,6 +452,142 @@ void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const IntSize& program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Simple); GL_CMD(glUseProgram(program->id())); + drawTexturedQuadWithProgram(program.get(), texture, flags, targetRect, modelViewMatrix, opacity, maskTexture); +} + +static TransformationMatrix viewportMatrix() +{ + GLint viewport[4]; + GL_CMD(glGetIntegerv(GL_VIEWPORT, viewport)); + + TransformationMatrix matrix; + matrix.translate3d(viewport[0], viewport[1], 0); + matrix.scale3d(viewport[2], viewport[3], 0); + + // Map x, y and z to unit square from OpenGL normalized device + // coordinates which are -1 to 1 on every axis. + matrix.translate3d(0.5, 0.5, 0.5); + matrix.scale3d(0.5, 0.5, 0.5); + + return matrix; +} + +static void scaleLineEquationCoeffecientsToOptimizeDistanceCalculation(float* coeffecients) +{ + // In the fragment shader we want to calculate the distance from this + // line to a point (p), which is given by the formula: + // (A*p.x + B*p.y + C) / sqrt (a^2 + b^2) + // We can do a small amount of precalculation here to reduce the + // amount of math in the shader by scaling the coeffecients now. + float scale = 1.0 / FloatPoint(coeffecients[0], coeffecients[1]).length(); + coeffecients[0] = coeffecients[0] * scale; + coeffecients[1] = coeffecients[1] * scale; + coeffecients[2] = coeffecients[2] * scale; +} + +static void getStandardEquationCoeffecientsForLine(const FloatPoint& p1, const FloatPoint& p2, float* coeffecients) +{ + // Given two points, the standard equation of a line (Ax + By + C = 0) + // can be calculated via the formula: + // (p1.y – p2.y)x + (p1.x – p2.x)y + ((p1.x*p2.y) – (p2.x*p1.y)) = 0 + coeffecients[0] = p1.y() - p2.y(); + coeffecients[1] = p2.x() - p1.x(); + coeffecients[2] = p1.x() * p2.y() - p2.x() * p1.y(); + scaleLineEquationCoeffecientsToOptimizeDistanceCalculation(coeffecients); +} + +static void quadToEdgeArray(const FloatQuad& quad, float* edgeArray) +{ + if (quad.isCounterclockwise()) { + getStandardEquationCoeffecientsForLine(quad.p4(), quad.p3(), edgeArray); + getStandardEquationCoeffecientsForLine(quad.p3(), quad.p2(), edgeArray + 3); + getStandardEquationCoeffecientsForLine(quad.p2(), quad.p1(), edgeArray + 6); + getStandardEquationCoeffecientsForLine(quad.p1(), quad.p4(), edgeArray + 9); + return; + } + getStandardEquationCoeffecientsForLine(quad.p4(), quad.p1(), edgeArray); + getStandardEquationCoeffecientsForLine(quad.p1(), quad.p2(), edgeArray + 3); + getStandardEquationCoeffecientsForLine(quad.p2(), quad.p3(), edgeArray + 6); + getStandardEquationCoeffecientsForLine(quad.p3(), quad.p4(), edgeArray + 9); +} + +static FloatSize scaledVectorDifference(const FloatPoint& point1, const FloatPoint& point2, float scale) +{ + FloatSize vector = point1 - point2; + if (vector.diagonalLengthSquared()) + vector.scale(1.0 / vector.diagonalLength()); + + vector.scale(scale); + return vector; +} + +static FloatQuad inflateQuad(const FloatQuad& quad, float distance) +{ + FloatQuad expandedQuad = quad; + expandedQuad.setP1(expandedQuad.p1() + scaledVectorDifference(quad.p1(), quad.p2(), distance)); + expandedQuad.setP4(expandedQuad.p4() + scaledVectorDifference(quad.p4(), quad.p3(), distance)); + + expandedQuad.setP1(expandedQuad.p1() + scaledVectorDifference(quad.p1(), quad.p4(), distance)); + expandedQuad.setP2(expandedQuad.p2() + scaledVectorDifference(quad.p2(), quad.p3(), distance)); + + expandedQuad.setP2(expandedQuad.p2() + scaledVectorDifference(quad.p2(), quad.p1(), distance)); + expandedQuad.setP3(expandedQuad.p3() + scaledVectorDifference(quad.p3(), quad.p4(), distance)); + + expandedQuad.setP3(expandedQuad.p3() + scaledVectorDifference(quad.p3(), quad.p2(), distance)); + expandedQuad.setP4(expandedQuad.p4() + scaledVectorDifference(quad.p4(), quad.p1(), distance)); + + return expandedQuad; +} + +bool TextureMapperGL::drawTextureWithAntialiasing(uint32_t texture, Flags flags, const FloatRect& originalTargetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges) +{ + // The antialiasing path does not support mask textures at the moment. + if (maskTexture) + return false; + + // For now we punt on rendering tiled layers with antialiasing. It's quite hard + // to render them without seams. + if (exposedEdges != AllEdges) + return false; + + // The goal here is render a slightly larger (0.75 pixels in screen space) quad and to + // gradually taper off the alpha values to do a simple version of edge distance + // antialiasing. Note here that we are also including the viewport matrix (which + // translates from normalized device coordinates to screen coordinates), because these + // values are consumed in the fragment shader, which works in screen coordinates. + TransformationMatrix screenSpaceTransform = viewportMatrix().multiply(TransformationMatrix(data().projectionMatrix)).multiply(modelViewMatrix).to2dTransform(); + if (!screenSpaceTransform.isInvertible()) + return false; + FloatQuad quadInScreenSpace = screenSpaceTransform.mapQuad(originalTargetRect); + + const float inflationDistance = 0.75; + FloatQuad expandedQuadInScreenSpace = inflateQuad(quadInScreenSpace, inflationDistance); + + // In the non-antialiased case the vertices passed are the unit rectangle and double + // as the texture coordinates (0,0 1,0, 1,1 and 0,1). Here we map the expanded quad + // coordinates in screen space back to the original rect's texture coordinates. + // This has the effect of slightly increasing the size of the original quad's geometry + // in the vertex shader. + FloatQuad expandedQuadInTextureCoordinates = screenSpaceTransform.inverse().mapQuad(expandedQuadInScreenSpace); + expandedQuadInTextureCoordinates.move(-originalTargetRect.x(), -originalTargetRect.y()); + expandedQuadInTextureCoordinates.scale(1 / originalTargetRect.width(), 1 / originalTargetRect.height()); + + // We prepare both the expanded quad for the fragment shader as well as the rectangular bounding + // box of that quad, as that seems necessary to properly antialias backfacing quads. + float targetQuadEdges[24]; + quadToEdgeArray(expandedQuadInScreenSpace, targetQuadEdges); + quadToEdgeArray(inflateQuad(quadInScreenSpace.boundingBox(), inflationDistance), targetQuadEdges + 12); + + RefPtr<TextureMapperShaderProgramAntialiasingNoMask> program = data().sharedGLData().textureMapperShaderManager.antialiasingNoMaskProgram(); + GL_CMD(glUseProgram(program->id())); + GL_CMD(glUniform3fv(program->expandedQuadEdgesInScreenSpaceLocation(), 8, targetQuadEdges)); + + drawTexturedQuadWithProgram(program.get(), texture, flags, DrawQuad(originalTargetRect, expandedQuadInTextureCoordinates), modelViewMatrix, opacity, 0 /* maskTexture */); + return true; +} + +void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram* program, uint32_t texture, Flags flags, const DrawQuad& quadToDraw, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture) +{ GL_CMD(glEnableVertexAttribArray(program->vertexAttrib())); GL_CMD(glActiveTexture(GL_TEXTURE0)); GL_CMD(glBindTexture(GL_TEXTURE_2D, texture)); @@ -427,7 +607,7 @@ void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const IntSize& } bool needsBlending = (flags & SupportsBlending) || opacity < 0.99 || maskTexture; - drawRect(targetRect, modelViewMatrix, program.get(), GL_TRIANGLE_FAN, needsBlending); + drawQuad(quadToDraw, modelViewMatrix, program, GL_TRIANGLE_FAN, needsBlending); } bool BitmapTextureGL::canReuseWith(const IntSize& contentsSize, Flags) diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h index e75bb08b4..076e65f73 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h @@ -50,11 +50,14 @@ public: // TextureMapper implementation virtual void drawBorder(const Color&, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) OVERRIDE; - virtual void drawTexture(const BitmapTexture&, const FloatRect&, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture) OVERRIDE; - virtual void drawTexture(uint32_t texture, Flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture); + virtual void drawRepaintCounter(int value, int pointSize, const FloatPoint&, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) OVERRIDE; + virtual void drawTexture(const BitmapTexture&, const FloatRect&, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges) OVERRIDE; + virtual void drawTexture(uint32_t texture, Flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges = AllEdges); + #if defined(GL_ARB_texture_rectangle) virtual void drawTextureRectangleARB(uint32_t texture, Flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture); #endif + virtual void bindSurface(BitmapTexture* surface) OVERRIDE; virtual void beginClip(const TransformationMatrix&, const FloatRect&) OVERRIDE; virtual void beginPainting(PaintFlags = 0) OVERRIDE; @@ -69,6 +72,7 @@ public: void drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture& contentTexture, const FilterOperation&, int pass); #endif + void setEnableEdgeDistanceAntialiasing(bool enabled) { m_enableEdgeDistanceAntialiasing = enabled; } private: @@ -94,7 +98,21 @@ private: Vector<ClipState> clipStack; }; - void drawRect(const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram*, GLenum drawingMode, bool needsBlending); + struct DrawQuad { + DrawQuad(const FloatRect& originalTargetRect, const FloatQuad& targetRectMappedToUnitSquare = FloatRect(FloatPoint(), FloatSize(1, 1))) + : originalTargetRect(originalTargetRect) + , targetRectMappedToUnitSquare(targetRectMappedToUnitSquare) + { + } + + FloatRect originalTargetRect; + FloatQuad targetRectMappedToUnitSquare; + }; + + bool drawTextureWithAntialiasing(uint32_t texture, Flags, const FloatRect& originalTargetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges); + void drawTexturedQuadWithProgram(TextureMapperShaderProgram*, uint32_t texture, Flags, const DrawQuad&, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture); + void drawQuad(const DrawQuad&, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram*, GLenum drawingMode, bool needsBlending); + bool beginScissorClip(const TransformationMatrix&, const FloatRect&); void bindDefaultSurface(); ClipStack& clipStack(); @@ -102,6 +120,8 @@ private: TextureMapperGLData* m_data; GraphicsContext* m_context; ClipStack m_clipStack; + bool m_enableEdgeDistanceAntialiasing; + friend class BitmapTextureGL; }; diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp index 79470b393..d5019e6a6 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp @@ -82,7 +82,7 @@ void TextureMapperImageBuffer::beginClip(const TransformationMatrix& matrix, con #endif } -void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture) +void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture, unsigned /* exposedEdges */) { GraphicsContext* context = currentContext(); if (!context) diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h index ebcba4b08..4e2c69154 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h @@ -52,7 +52,8 @@ public: // TextureMapper implementation virtual void drawBorder(const Color& color, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) OVERRIDE { }; - virtual void drawTexture(const BitmapTexture&, const FloatRect& targetRect, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture) OVERRIDE; + virtual void drawRepaintCounter(int value, int pointSize, const FloatPoint&, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) OVERRIDE { }; + virtual void drawTexture(const BitmapTexture&, const FloatRect& targetRect, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges) OVERRIDE; virtual void beginClip(const TransformationMatrix&, const FloatRect&) OVERRIDE; virtual void bindSurface(BitmapTexture* surface) OVERRIDE { m_currentSurface = surface;} virtual void endClip() OVERRIDE { graphicsContext()->restore(); } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp index fd4bf2f7a..cdd495201 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp @@ -31,6 +31,7 @@ #if USE(CAIRO) #include "CairoUtilities.h" +#include <wtf/text/CString.h> #endif namespace WebCore { diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp index b165df670..0fbdbe95c 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp @@ -1,6 +1,7 @@ /* Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) Copyright (C) 2012 Igalia S.L. + Copyright (C) 2011 Google Inc. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -105,14 +106,53 @@ static const char* fragmentShaderSourceSimple = } ); +static const char* fragmentShaderSourceAntialiasingNoMask = + FRAGMENT_SHADER( + uniform sampler2D s_source; + varying highp vec2 v_sourceTexCoord; + uniform lowp float u_opacity; + uniform vec3 u_expandedQuadEdgesInScreenSpace[8]; + void main() + { + vec4 sampledColor = texture2D(s_source, clamp(v_sourceTexCoord, 0.0, 1.0)); + vec3 pos = vec3(gl_FragCoord.xy, 1); + + // The data passed in u_expandedQuadEdgesInScreenSpace is merely the + // pre-scaled coeffecients of the line equations describing the four edges + // of the expanded quad in screen space and the rectangular bounding box + // of the expanded quad. + // + // We are doing a simple distance calculation here according to the formula: + // (A*p.x + B*p.y + C) / sqrt(A^2 + B^2) = distance from line to p + // Note that A, B and C have already been scaled by 1 / sqrt(A^2 + B^2). + float a0 = clamp(dot(u_expandedQuadEdgesInScreenSpace[0], pos), 0.0, 1.0); + float a1 = clamp(dot(u_expandedQuadEdgesInScreenSpace[1], pos), 0.0, 1.0); + float a2 = clamp(dot(u_expandedQuadEdgesInScreenSpace[2], pos), 0.0, 1.0); + float a3 = clamp(dot(u_expandedQuadEdgesInScreenSpace[3], pos), 0.0, 1.0); + float a4 = clamp(dot(u_expandedQuadEdgesInScreenSpace[4], pos), 0.0, 1.0); + float a5 = clamp(dot(u_expandedQuadEdgesInScreenSpace[5], pos), 0.0, 1.0); + float a6 = clamp(dot(u_expandedQuadEdgesInScreenSpace[6], pos), 0.0, 1.0); + float a7 = clamp(dot(u_expandedQuadEdgesInScreenSpace[7], pos), 0.0, 1.0); + + // Now we want to reduce the alpha value of the fragment if it is close to the + // edges of the expanded quad (or rectangular bounding box -- which seems to be + // important for backfacing quads). Note that we are combining the contribution + // from the (top || bottom) and (left || right) edge by simply multiplying. This follows + // the approach described at: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html, + // in this case without using Gaussian weights. + gl_FragColor = sampledColor * u_opacity * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); + } + ); + static const char* fragmentShaderSourceRectSimple = FRAGMENT_SHADER( uniform sampler2DRect s_source; + uniform lowp vec2 u_textureSize; uniform lowp float u_opacity; varying highp vec2 v_sourceTexCoord; void main(void) { - lowp vec4 color = texture2DRect(s_source, v_sourceTexCoord); + lowp vec4 color = texture2DRect(s_source, u_textureSize * v_sourceTexCoord); gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity); } ); @@ -155,6 +195,11 @@ PassRefPtr<TextureMapperShaderProgramSolidColor> TextureMapperShaderManager::sol return static_pointer_cast<TextureMapperShaderProgramSolidColor>(getShaderProgram(SolidColor)); } +PassRefPtr<TextureMapperShaderProgramAntialiasingNoMask> TextureMapperShaderManager::antialiasingNoMaskProgram() +{ + return static_pointer_cast<TextureMapperShaderProgramAntialiasingNoMask>(getShaderProgram(AntialiasingNoMask)); +} + PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProgram(ShaderType shaderType) { RefPtr<TextureMapperShaderProgram> program; @@ -172,6 +217,9 @@ PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProg case RectSimple: program = TextureMapperShaderProgramRectSimple::create(); break; + case AntialiasingNoMask: + program = TextureMapperShaderProgramAntialiasingNoMask::create(); + break; case OpacityAndMask: program = TextureMapperShaderProgramOpacityAndMask::create(); break; @@ -195,6 +243,7 @@ TextureMapperShaderProgram::TextureMapperShaderProgram(const char* vertexShaderS , m_fragmentShader(0) , m_matrixLocation(-1) , m_flipLocation(-1) + , m_textureSizeLocation(-1) , m_sourceTextureLocation(-1) , m_opacityLocation(-1) , m_maskTextureLocation(-1) @@ -214,11 +263,13 @@ void TextureMapperShaderProgram::initializeProgram() GLuint programID = glCreateProgram(); glCompileShader(vertexShader); glCompileShader(fragmentShader); + glAttachShader(programID, vertexShader); glAttachShader(programID, fragmentShader); glLinkProgram(programID); m_vertexAttrib = glGetAttribLocation(programID, "a_vertex"); + m_id = programID; m_vertexShader = vertexShader; m_fragmentShader = fragmentShader; @@ -265,8 +316,9 @@ TextureMapperShaderProgramRectSimple::TextureMapperShaderProgramRectSimple() : TextureMapperShaderProgram(vertexShaderSourceSimple, fragmentShaderSourceRectSimple) { initializeProgram(); - getUniformLocation(m_flipLocation, "u_flip"); getUniformLocation(m_matrixLocation, "u_matrix"); + getUniformLocation(m_flipLocation, "u_flip"); + getUniformLocation(m_textureSizeLocation, "u_textureSize"); getUniformLocation(m_sourceTextureLocation, "s_source"); getUniformLocation(m_opacityLocation, "u_opacity"); } @@ -293,6 +345,17 @@ TextureMapperShaderProgramRectOpacityAndMask::TextureMapperShaderProgramRectOpac getUniformLocation(m_opacityLocation, "u_opacity"); } +TextureMapperShaderProgramAntialiasingNoMask::TextureMapperShaderProgramAntialiasingNoMask() + : TextureMapperShaderProgram(vertexShaderSourceSimple, fragmentShaderSourceAntialiasingNoMask) +{ + initializeProgram(); + getUniformLocation(m_matrixLocation, "u_matrix"); + getUniformLocation(m_sourceTextureLocation, "s_source"); + getUniformLocation(m_opacityLocation, "u_opacity"); + getUniformLocation(m_expandedQuadEdgesInScreenSpaceLocation, "u_expandedQuadEdgesInScreenSpace"); + getUniformLocation(m_flipLocation, "u_flip"); +} + TextureMapperShaderManager::TextureMapperShaderManager() { ASSERT(initializeOpenGLShims()); diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h index 8bbb30a45..785498e7f 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h @@ -53,6 +53,7 @@ public: virtual void prepare(float opacity, const BitmapTexture*) { } GLint matrixLocation() const { return m_matrixLocation; } GLint flipLocation() const { return m_flipLocation; } + GLint textureSizeLocation() const { return m_textureSizeLocation; } GLint sourceTextureLocation() const { return m_sourceTextureLocation; } GLint maskTextureLocation() const { return m_maskTextureLocation; } GLint opacityLocation() const { return m_opacityLocation; } @@ -72,6 +73,7 @@ protected: GLuint m_fragmentShader; GLint m_matrixLocation; GLint m_flipLocation; + GLint m_textureSizeLocation; GLint m_sourceTextureLocation; GLint m_opacityLocation; GLint m_maskTextureLocation; @@ -175,11 +177,29 @@ private: GLint m_colorLocation; }; +class TextureMapperShaderProgramAntialiasingNoMask : public TextureMapperShaderProgram { +public: + static PassRefPtr<TextureMapperShaderProgramAntialiasingNoMask> create() + { + return adoptRef(new TextureMapperShaderProgramAntialiasingNoMask()); + } + + GLint expandedQuadVerticesInTextureCoordinatesLocation() { return m_expandedQuadVerticesInTextureCordinatesLocation; } + GLint expandedQuadEdgesInScreenSpaceLocation() { return m_expandedQuadEdgesInScreenSpaceLocation; } + +private: + TextureMapperShaderProgramAntialiasingNoMask(); + + GLint m_expandedQuadVerticesInTextureCordinatesLocation; + GLint m_expandedQuadEdgesInScreenSpaceLocation; +}; + class TextureMapperShaderManager { public: enum ShaderType { Invalid = 0, // HashMaps do not like 0 as a key. Simple, + AntialiasingNoMask, RectSimple, OpacityAndMask, RectOpacityAndMask, @@ -196,6 +216,7 @@ public: PassRefPtr<TextureMapperShaderProgram> getShaderProgram(ShaderType); PassRefPtr<TextureMapperShaderProgramSolidColor> solidColorProgram(); + PassRefPtr<TextureMapperShaderProgramAntialiasingNoMask> antialiasingNoMaskProgram(); private: typedef HashMap<ShaderType, RefPtr<TextureMapperShaderProgram>, DefaultHash<int>::Hash, HashTraits<int> > TextureMapperShaderProgramMap; diff --git a/Source/WebCore/platform/gtk/ContextMenuGtk.cpp b/Source/WebCore/platform/gtk/ContextMenuGtk.cpp index 62a7eecd2..8916525db 100644 --- a/Source/WebCore/platform/gtk/ContextMenuGtk.cpp +++ b/Source/WebCore/platform/gtk/ContextMenuGtk.cpp @@ -23,8 +23,9 @@ #include "ContextMenu.h" -#include <wtf/gobject/GOwnPtr.h> #include <gtk/gtk.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> namespace WebCore { @@ -48,10 +49,14 @@ void ContextMenu::appendItem(ContextMenuItem& item) { ASSERT(m_platformDescription); - GtkMenuItem* platformItem = item.releasePlatformDescription(); + GRefPtr<GtkWidget> platformItem = GTK_WIDGET(item.releasePlatformDescription()); ASSERT(platformItem); - gtk_menu_shell_append(GTK_MENU_SHELL(m_platformDescription), GTK_WIDGET(platformItem)); - gtk_widget_show(GTK_WIDGET(platformItem)); + + if (GtkWidget* parent = gtk_widget_get_parent(platformItem.get())) + gtk_container_remove(GTK_CONTAINER(parent), platformItem.get()); + + gtk_menu_shell_append(GTK_MENU_SHELL(m_platformDescription), platformItem.get()); + gtk_widget_show(platformItem.get()); } void ContextMenu::setPlatformDescription(PlatformMenuDescription menu) diff --git a/Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp b/Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp index 68ae5a5de..d70b5be6b 100644 --- a/Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp +++ b/Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp @@ -144,6 +144,17 @@ static PlatformMenuItemDescription createPlatformMenuItemDescription(ContextMenu ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription item) : m_platformDescription(item) { + // Don't show accel labels in context menu items. + GtkAction* action = gtkAction(); + if (!action) + return; + + if (!gtk_action_get_accel_path(action)) + return; + + GtkWidget* child = gtk_bin_get_child(GTK_BIN(item)); + if (GTK_IS_ACCEL_LABEL(child)) + gtk_accel_label_set_accel_closure(GTK_ACCEL_LABEL(child), 0); } ContextMenuItem::ContextMenuItem(ContextMenu* subMenu) diff --git a/Source/WebCore/platform/gtk/GamepadsGtk.cpp b/Source/WebCore/platform/gtk/GamepadsGtk.cpp new file mode 100644 index 000000000..f8a73f4e6 --- /dev/null +++ b/Source/WebCore/platform/gtk/GamepadsGtk.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2012 Zan Dobersek <zandobersek@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +#include "config.h" +#include "Gamepads.h" + +#if ENABLE(GAMEPAD) + +#include "GamepadDeviceLinux.h" +#include "GamepadList.h" +#include "Logging.h" +#include <gio/gunixinputstream.h> +#include <gudev/gudev.h> +#include <wtf/HashMap.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> +#include <wtf/text/StringHash.h> + +namespace WebCore { + +class GamepadDeviceGtk : public GamepadDeviceLinux { +public: + static PassOwnPtr<GamepadDeviceGtk> create(String deviceFile) + { + return adoptPtr(new GamepadDeviceGtk(deviceFile)); + } + ~GamepadDeviceGtk(); + +private: + GamepadDeviceGtk(String deviceFile); + + static gboolean readCallback(GObject* pollableStream, gpointer data); + GRefPtr<GInputStream> m_inputStream; + GRefPtr<GSource> m_source; +}; + +GamepadDeviceGtk::GamepadDeviceGtk(String deviceFile) + : GamepadDeviceLinux(deviceFile) +{ + if (m_fileDescriptor == -1) + return; + + m_inputStream = adoptGRef(g_unix_input_stream_new(m_fileDescriptor, FALSE)); + m_source = adoptGRef(g_pollable_input_stream_create_source(G_POLLABLE_INPUT_STREAM(m_inputStream.get()), 0)); + g_source_set_callback(m_source.get(), reinterpret_cast<GSourceFunc>(readCallback), this, 0); + g_source_attach(m_source.get(), 0); +} + +GamepadDeviceGtk::~GamepadDeviceGtk() +{ + if (m_source) + g_source_destroy(m_source.get()); +} + +gboolean GamepadDeviceGtk::readCallback(GObject* pollableStream, gpointer data) +{ + GamepadDeviceGtk* gamepadDevice = reinterpret_cast<GamepadDeviceGtk*>(data); + GOwnPtr<GError> error; + struct js_event event; + + gssize len = g_pollable_input_stream_read_nonblocking(G_POLLABLE_INPUT_STREAM(pollableStream), + &event, sizeof(event), 0, &error.outPtr()); + + // FIXME: Properly log the error. + // In the case of G_IO_ERROR_WOULD_BLOCK error return TRUE to wait until + // the source becomes readable again and FALSE otherwise. + if (error) + return g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK); + + ASSERT(len == sizeof(event)); + gamepadDevice->updateForEvent(event); + return TRUE; +} + +class GamepadsGtk { +public: + GamepadsGtk(unsigned length); + + void registerDevice(String deviceFile); + void unregisterDevice(String deviceFile); + + void updateGamepadList(GamepadList*); + +private: + ~GamepadsGtk(); + static void onUEventCallback(GUdevClient*, gchar* action, GUdevDevice*, gpointer data); + static gboolean isGamepadDevice(GUdevDevice*); + + Vector<OwnPtr<GamepadDeviceGtk> > m_slots; + HashMap<String, GamepadDeviceGtk*> m_deviceMap; + + GRefPtr<GUdevClient> m_gudevClient; +}; + +GamepadsGtk::GamepadsGtk(unsigned length) + : m_slots(length) +{ + static const char* subsystems[] = { "input", 0 }; + m_gudevClient = adoptGRef(g_udev_client_new(subsystems)); + g_signal_connect(m_gudevClient.get(), "uevent", G_CALLBACK(onUEventCallback), this); + + GOwnPtr<GList> devicesList(g_udev_client_query_by_subsystem(m_gudevClient.get(), subsystems[0])); + for (GList* listItem = devicesList.get(); listItem; listItem = g_list_next(listItem)) { + GUdevDevice* device = G_UDEV_DEVICE(listItem->data); + String deviceFile = String::fromUTF8(g_udev_device_get_device_file(device)); + if (isGamepadDevice(device)) + registerDevice(deviceFile); + g_object_unref(device); + } +} + +GamepadsGtk::~GamepadsGtk() +{ + g_signal_handlers_disconnect_matched(m_gudevClient.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); +} + +void GamepadsGtk::registerDevice(String deviceFile) +{ + LOG(Gamepad, "GamepadsGtk::registerDevice %s", deviceFile.ascii().data()); + ASSERT(!m_deviceMap.contains(deviceFile)); + + for (unsigned index = 0; index < m_slots.size(); index++) { + if (!m_slots[index]) { + m_slots[index] = GamepadDeviceGtk::create(deviceFile); + m_deviceMap.add(deviceFile, m_slots[index].get()); + break; + } + } +} + +void GamepadsGtk::unregisterDevice(String deviceFile) +{ + LOG(Gamepad, "GamepadsGtk::unregisterDevice %s", deviceFile.ascii().data()); + ASSERT(m_deviceMap.contains(deviceFile)); + + GamepadDeviceGtk* gamepadDevice = m_deviceMap.take(deviceFile); + size_t index = m_slots.find(gamepadDevice); + ASSERT(index != notFound); + + m_slots[index].clear(); +} + +void GamepadsGtk::updateGamepadList(GamepadList* into) +{ + ASSERT(m_slots.size() == into->length()); + + for (unsigned i = 0; i < m_slots.size(); i++) { + if (m_slots[i].get() && m_slots[i]->connected()) { + GamepadDeviceGtk* gamepadDevice = m_slots[i].get(); + RefPtr<Gamepad> gamepad = into->item(i); + if (!gamepad) + gamepad = Gamepad::create(); + + gamepad->index(i); + gamepad->id(gamepadDevice->id()); + gamepad->timestamp(gamepadDevice->timestamp()); + gamepad->axes(gamepadDevice->axesCount(), gamepadDevice->axesData()); + gamepad->buttons(gamepadDevice->buttonsCount(), gamepadDevice->buttonsData()); + + into->set(i, gamepad); + } else + into->set(i, 0); + } +} + +void GamepadsGtk::onUEventCallback(GUdevClient* udevClient, gchar* action, GUdevDevice* device, gpointer data) +{ + if (!isGamepadDevice(device)) + return; + + GamepadsGtk* gamepadsGtk = reinterpret_cast<GamepadsGtk*>(data); + String deviceFile = String::fromUTF8(g_udev_device_get_device_file(device)); + + if (!g_strcmp0(action, "add")) + gamepadsGtk->registerDevice(deviceFile); + else if (!g_strcmp0(action, "remove")) + gamepadsGtk->unregisterDevice(deviceFile); +} + +gboolean GamepadsGtk::isGamepadDevice(GUdevDevice* device) +{ + const gchar* deviceFile = g_udev_device_get_device_file(device); + const gchar* sysfsPath = g_udev_device_get_sysfs_path(device); + if (!deviceFile || !sysfsPath) + return FALSE; + + if (!g_udev_device_has_property(device, "ID_INPUT") || !g_udev_device_has_property(device, "ID_INPUT_JOYSTICK")) + return FALSE; + + return g_str_has_prefix(deviceFile, "/dev/input/js"); +} + +void sampleGamepads(GamepadList* into) +{ + DEFINE_STATIC_LOCAL(GamepadsGtk, gamepadsGtk, (into->length())); + gamepadsGtk.updateGamepadList(into); +} + +} // namespace WebCore + +#endif // ENABLE(GAMEPAD) diff --git a/Source/WebCore/platform/gtk/LoggingGtk.cpp b/Source/WebCore/platform/gtk/LoggingGtk.cpp index 588ed7cf7..f16a1b24c 100644 --- a/Source/WebCore/platform/gtk/LoggingGtk.cpp +++ b/Source/WebCore/platform/gtk/LoggingGtk.cpp @@ -20,8 +20,10 @@ #include "config.h" #include "Logging.h" -#include "PlatformString.h" +#if !LOG_DISABLED + +#include "PlatformString.h" #include <glib.h> #include <string.h> @@ -62,3 +64,5 @@ void initializeLoggingChannelsIfNecessary() } } // namespace WebCore + +#endif // !LOG_DISABLED diff --git a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp index 4b6c1c1a9..5762a8fc7 100644 --- a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp +++ b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp @@ -137,7 +137,7 @@ FloatRect screenAvailableRect(Widget* widget) } -void screenColorProfile(Widget*, const String&, ColorProfile&) +void screenColorProfile(Widget*, ColorProfile&) { notImplemented(); } diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp index f05e219a2..2eb4f2bad 100644 --- a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -238,10 +238,11 @@ bool RenderThemeGtk::paintTextArea(RenderObject* o, const PaintInfo& i, const In static void paintGdkPixbuf(GraphicsContext* context, const GdkPixbuf* icon, const IntRect& iconRect) { IntSize iconSize(gdk_pixbuf_get_width(icon), gdk_pixbuf_get_height(icon)); + GRefPtr<GdkPixbuf> scaledIcon; if (iconRect.size() != iconSize) { // We could use cairo_scale() here but cairo/pixman downscale quality is quite bad. - GRefPtr<GdkPixbuf> scaledIcon = gdk_pixbuf_scale_simple(icon, iconRect.width(), iconRect.height(), - GDK_INTERP_BILINEAR); + scaledIcon = adoptGRef(gdk_pixbuf_scale_simple(icon, iconRect.width(), iconRect.height(), + GDK_INTERP_BILINEAR)); icon = scaledIcon.get(); } diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.h b/Source/WebCore/platform/image-decoders/ImageDecoder.h index 2611be900..760ac93f8 100644 --- a/Source/WebCore/platform/image-decoders/ImageDecoder.h +++ b/Source/WebCore/platform/image-decoders/ImageDecoder.h @@ -315,7 +315,7 @@ namespace WebCore { #else // FIXME: add support for multiple monitors. ColorProfile profile; - screenColorProfile(0, "monitor", profile); + screenColorProfile(0, profile); if (!profile.isEmpty()) outputDeviceProfile = qcms_profile_from_memory(profile.data(), profile.size()); #endif diff --git a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index ec8de28a4..91f1236b3 100644 --- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -86,13 +86,17 @@ inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_RGB; } inline bool colorSpaceHasAlpha(J_COLOR_SPACE) { return false; } #endif -#if OS(ANDROID) +#if USE(LOW_QUALITY_IMAGE_NO_JPEG_DITHERING) inline J_DCT_METHOD dctMethod() { return JDCT_IFAST; } inline J_DITHER_MODE ditherMode() { return JDITHER_NONE; } -inline bool doFancyUpsampling() { return false; } #else inline J_DCT_METHOD dctMethod() { return JDCT_ISLOW; } inline J_DITHER_MODE ditherMode() { return JDITHER_FS; } +#endif + +#if USE(LOW_QUALITY_IMAGE_NO_JPEG_FANCY_UPSAMPLING) +inline bool doFancyUpsampling() { return false; } +#else inline bool doFancyUpsampling() { return true; } #endif diff --git a/Source/WebCore/platform/linux/GamepadDeviceLinux.cpp b/Source/WebCore/platform/linux/GamepadDeviceLinux.cpp new file mode 100644 index 000000000..c25bc1b5d --- /dev/null +++ b/Source/WebCore/platform/linux/GamepadDeviceLinux.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2012 Zan Dobersek <zandobersek@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +#include "config.h" +#include "GamepadDeviceLinux.h" + +#if ENABLE(GAMEPAD) + +#include <fcntl.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +GamepadDeviceLinux::GamepadDeviceLinux(String deviceFile) + : m_fileDescriptor(-1) + , m_connected(false) + , m_lastTimestamp(0) +{ + // FIXME: Log errors when returning early. + m_fileDescriptor = open(deviceFile.utf8().data(), O_RDONLY | O_NONBLOCK); + if (m_fileDescriptor == -1) + return; + + char deviceName[1024]; + if (ioctl(m_fileDescriptor, JSIOCGNAME(sizeof(deviceName)), deviceName) < 0) + return; + m_deviceName = String(deviceName).simplifyWhiteSpace(); + + uint8_t numberOfAxes; + uint8_t numberOfButtons; + if (ioctl(m_fileDescriptor, JSIOCGAXES, &numberOfAxes) < 0 || ioctl(m_fileDescriptor, JSIOCGBUTTONS, &numberOfButtons) < 0) + return; + m_axes.fill(0.0, numberOfAxes); + m_buttons.fill(0.0, numberOfButtons); +} + +GamepadDeviceLinux::~GamepadDeviceLinux() +{ + if (m_fileDescriptor != -1) + close(m_fileDescriptor); +} + +void GamepadDeviceLinux::updateForEvent(struct js_event event) +{ + if (!(event.type & JS_EVENT_AXIS || event.type & JS_EVENT_BUTTON)) + return; + + // Mark the device as connected only if it is not yet connected, the event is not an initialization + // and the value is not 0 (indicating a genuine interaction with the device). + if (!m_connected && !(event.type & JS_EVENT_INIT) && event.value) + m_connected = true; + + if (event.type & JS_EVENT_AXIS) + m_axes[event.number] = normalizeAxisValue(event.value); + else if (event.type & JS_EVENT_BUTTON) + m_buttons[event.number] = normalizeButtonValue(event.value); + + m_lastTimestamp = event.time; +} + +float GamepadDeviceLinux::normalizeAxisValue(short value) +{ + // Normalize from range [-32767, 32767] into range [-1.0, 1.0] + return value / 32767.0f; +} + +float GamepadDeviceLinux::normalizeButtonValue(short value) +{ + // Normalize from range [0, 1] into range [0.0, 1.0] + return value / 1.0f; +} + +} // namespace WebCore + +#endif // ENABLE(GAMEPAD) diff --git a/Source/WebCore/platform/linux/GamepadDeviceLinux.h b/Source/WebCore/platform/linux/GamepadDeviceLinux.h new file mode 100644 index 000000000..d485e83a9 --- /dev/null +++ b/Source/WebCore/platform/linux/GamepadDeviceLinux.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 Zan Dobersek <zandobersek@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +#ifndef GamepadDeviceLinux_h +#define GamepadDeviceLinux_h + +#if ENABLE(GAMEPAD) + +#include <linux/joystick.h> +#include <wtf/Vector.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class GamepadDeviceLinux { +public: + bool connected() { return m_connected; }; + + String id() { return m_deviceName; } + unsigned long long timestamp() { return m_lastTimestamp; } + + unsigned axesCount() { return m_axes.size(); } + float* axesData() { return m_axes.data(); } + + unsigned buttonsCount() { return m_buttons.size(); } + float* buttonsData() { return m_buttons.data(); } + +protected: + GamepadDeviceLinux(String deviceFile); + ~GamepadDeviceLinux(); + + void updateForEvent(struct js_event); + int m_fileDescriptor; + +private: + float normalizeAxisValue(short value); + float normalizeButtonValue(short value); + + bool m_connected; + String m_deviceName; + unsigned long long m_lastTimestamp; + + Vector<float> m_axes; + Vector<float> m_buttons; +}; + +} // namespace WebCore + +#endif // ENABLE(GAMEPAD) + +#endif // GamepadDeviceLinux_h diff --git a/Source/WebCore/platform/mac/LoggingMac.mm b/Source/WebCore/platform/mac/LoggingMac.mm index 4c9b30351..fa007ec2d 100644 --- a/Source/WebCore/platform/mac/LoggingMac.mm +++ b/Source/WebCore/platform/mac/LoggingMac.mm @@ -27,6 +27,8 @@ #include "Logging.h" +#if !LOG_DISABLED + namespace WebCore { static inline void initializeWithUserDefault(WTFLogChannel& channel) @@ -77,3 +79,5 @@ void initializeLoggingChannelsIfNecessary() } } + +#endif // !LOG_DISABLED diff --git a/Source/WebCore/platform/mac/PasteboardMac.mm b/Source/WebCore/platform/mac/PasteboardMac.mm index c1ec63551..604aa7fae 100644 --- a/Source/WebCore/platform/mac/PasteboardMac.mm +++ b/Source/WebCore/platform/mac/PasteboardMac.mm @@ -368,6 +368,9 @@ String Pasteboard::plainText(Frame* frame) static PassRefPtr<DocumentFragment> documentFragmentWithImageResource(Frame* frame, PassRefPtr<ArchiveResource> resource) { + if (!resource) + return 0; + if (DocumentLoader* loader = frame->loader()->documentLoader()) loader->addArchiveResource(resource.get()); diff --git a/Source/WebCore/platform/mac/PlatformScreenMac.mm b/Source/WebCore/platform/mac/PlatformScreenMac.mm index 273ff78d6..203418b87 100644 --- a/Source/WebCore/platform/mac/PlatformScreenMac.mm +++ b/Source/WebCore/platform/mac/PlatformScreenMac.mm @@ -76,7 +76,7 @@ FloatRect screenAvailableRect(Widget* widget) return toUserSpace([screenForWindow(window) visibleFrame], window); } -void screenColorProfile(Widget*, const String&, ColorProfile&) +void screenColorProfile(Widget*, ColorProfile&) { notImplemented(); } diff --git a/Source/WebCore/platform/mac/PopupMenuMac.mm b/Source/WebCore/platform/mac/PopupMenuMac.mm index 46077814c..855784470 100644 --- a/Source/WebCore/platform/mac/PopupMenuMac.mm +++ b/Source/WebCore/platform/mac/PopupMenuMac.mm @@ -119,6 +119,9 @@ void PopupMenuMac::populate() [m_popup.get() addItemWithTitle:@""]; NSMenuItem *menuItem = [m_popup.get() lastItem]; [menuItem setAttributedTitle:string]; + // We set the title as well as the attributed title here. The attributed title will be displayed in the menu, + // but typeahead will use the non-attributed string that doesn't contain any leading or trailing whitespace. + [menuItem setTitle:[[string string] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]]; [menuItem setEnabled:client()->itemIsEnabled(i)]; [menuItem setToolTip:client()->itemToolTip(i)]; [string release]; diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm index 2fe336f74..323719bd6 100644 --- a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm +++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm @@ -27,6 +27,7 @@ #include "ScrollbarThemeMac.h" #include "ImageBuffer.h" +#include "GraphicsLayer.h" #include "LocalCurrentGraphicsContext.h" #include "NSScrollerImpDetails.h" #include "PlatformMouseEvent.h" diff --git a/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp b/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp index 9dd4bb176..f4f9822de 100644 --- a/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp +++ b/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp @@ -56,6 +56,20 @@ void MediaStreamCenter::endLocalMediaStream(MediaStreamDescriptor* streamDescrip streamDescriptor->setEnded(); } +void MediaStreamCenter::addMediaStreamTrack(MediaStreamDescriptor* streamDescriptor, MediaStreamComponent* component) +{ + MediaStreamDescriptorOwner* owner = streamDescriptor->owner(); + if (owner) + owner->addTrack(component); +} + +void MediaStreamCenter::removeMediaStreamTrack(MediaStreamDescriptor* streamDescriptor, MediaStreamComponent* component) +{ + MediaStreamDescriptorOwner* owner = streamDescriptor->owner(); + if (owner) + owner->removeTrack(component); +} + } // namespace WebCore #endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebCore/platform/mediastream/MediaStreamCenter.h b/Source/WebCore/platform/mediastream/MediaStreamCenter.h index b3278c734..c8a51deb8 100644 --- a/Source/WebCore/platform/mediastream/MediaStreamCenter.h +++ b/Source/WebCore/platform/mediastream/MediaStreamCenter.h @@ -57,9 +57,10 @@ public: // Calls from the DOM objects to notify the platform virtual void didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*) = 0; + virtual void didAddMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*) = 0; + virtual void didRemoveMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*) = 0; virtual void didStopLocalMediaStream(MediaStreamDescriptor*) = 0; virtual void didCreateMediaStream(MediaStreamDescriptor*) = 0; - virtual String constructSDP(IceCandidateDescriptor*) = 0; virtual String constructSDP(SessionDescriptionDescriptor*) = 0; @@ -67,6 +68,8 @@ protected: MediaStreamCenter(); void endLocalMediaStream(MediaStreamDescriptor*); + void addMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*); + void removeMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*); }; } // namespace WebCore diff --git a/Source/WebCore/platform/mediastream/MediaStreamDescriptor.h b/Source/WebCore/platform/mediastream/MediaStreamDescriptor.h index 46332af31..c6061052d 100644 --- a/Source/WebCore/platform/mediastream/MediaStreamDescriptor.h +++ b/Source/WebCore/platform/mediastream/MediaStreamDescriptor.h @@ -45,6 +45,8 @@ public: virtual ~MediaStreamDescriptorOwner() { } virtual void streamEnded() = 0; + virtual void addTrack(MediaStreamComponent*) = 0; + virtual void removeTrack(MediaStreamComponent*) = 0; }; class MediaStreamDescriptor : public RefCounted<MediaStreamDescriptor> { diff --git a/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.cpp b/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.cpp index 1317d2d83..3c82f5f8b 100644 --- a/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.cpp +++ b/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.cpp @@ -83,6 +83,14 @@ void MediaStreamCenterChromium::didSetMediaStreamTrackEnabled(MediaStreamDescrip } } +void MediaStreamCenterChromium::didAddMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*) +{ +} + +void MediaStreamCenterChromium::didRemoveMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*) +{ +} + void MediaStreamCenterChromium::didStopLocalMediaStream(MediaStreamDescriptor* stream) { if (m_private) @@ -115,6 +123,16 @@ void MediaStreamCenterChromium::stopLocalMediaStream(const WebKit::WebMediaStrea endLocalMediaStream(stream); } +void MediaStreamCenterChromium::addMediaStreamTrack(const WebKit::WebMediaStreamDescriptor& stream, const WebKit::WebMediaStreamComponent& component) +{ + MediaStreamCenter::addMediaStreamTrack(stream, component); +} + +void MediaStreamCenterChromium::removeMediaStreamTrack(const WebKit::WebMediaStreamDescriptor& stream, const WebKit::WebMediaStreamComponent& component) +{ + MediaStreamCenter::removeMediaStreamTrack(stream, component); +} + } // namespace WebCore #endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.h b/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.h index d284a86fa..e3fff8af4 100644 --- a/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.h +++ b/Source/WebCore/platform/mediastream/chromium/MediaStreamCenterChromium.h @@ -42,6 +42,7 @@ namespace WebKit { class WebMediaStreamCenter; +class WebMediaStreamComponent; class WebMediaStreamDescriptor; } @@ -61,6 +62,8 @@ public: // MediaStreamCenter virtual void queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient>) OVERRIDE; virtual void didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*) OVERRIDE; + virtual void didAddMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*) OVERRIDE; + virtual void didRemoveMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*) OVERRIDE; virtual void didStopLocalMediaStream(MediaStreamDescriptor*) OVERRIDE; virtual void didCreateMediaStream(MediaStreamDescriptor*) OVERRIDE; virtual String constructSDP(IceCandidateDescriptor*) OVERRIDE; @@ -68,6 +71,8 @@ public: // WebKit::WebMediaStreamCenterClient virtual void stopLocalMediaStream(const WebKit::WebMediaStreamDescriptor&) OVERRIDE; + virtual void addMediaStreamTrack(const WebKit::WebMediaStreamDescriptor&, const WebKit::WebMediaStreamComponent&) OVERRIDE; + virtual void removeMediaStreamTrack(const WebKit::WebMediaStreamDescriptor&, const WebKit::WebMediaStreamComponent&) OVERRIDE; private: OwnPtr<WebKit::WebMediaStreamCenter> m_private; diff --git a/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.cpp b/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.cpp index fe8bb460d..dc483ff3b 100644 --- a/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.cpp +++ b/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.cpp @@ -68,6 +68,14 @@ void MediaStreamCenterGStreamer::didSetMediaStreamTrackEnabled(MediaStreamDescri { } +void MediaStreamCenterGStreamer::didAddMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*) +{ +} + +void MediaStreamCenterGStreamer::didRemoveMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*) +{ +} + void MediaStreamCenterGStreamer::didStopLocalMediaStream(MediaStreamDescriptor*) { } diff --git a/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.h b/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.h index 1564e33bd..7641fb58e 100644 --- a/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.h +++ b/Source/WebCore/platform/mediastream/gstreamer/MediaStreamCenterGStreamer.h @@ -55,6 +55,8 @@ public: // MediaStreamCenter virtual void queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient>) OVERRIDE; virtual void didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*) OVERRIDE; + virtual void didAddMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*) OVERRIDE; + virtual void didRemoveMediaStreamTrack(MediaStreamDescriptor*, MediaStreamComponent*) OVERRIDE; virtual void didStopLocalMediaStream(MediaStreamDescriptor*) OVERRIDE; virtual void didCreateMediaStream(MediaStreamDescriptor*) OVERRIDE; virtual String constructSDP(IceCandidateDescriptor*) OVERRIDE; diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp index 1c22bb493..c64fdc8aa 100644 --- a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp +++ b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp @@ -625,12 +625,12 @@ void NetworkJob::sendResponseIfNeeded() mimeType = "application/x-ftp-directory"; else if (mimeType.isNull()) mimeType = extractMIMETypeFromMediaType(m_contentType); - if (mimeType.isNull()) { - if (m_dataReceived) - mimeType = MIMETypeRegistry::getMIMETypeForPath(urlFilename); - else - // For empty content, we shouldn't download. - mimeType = "text/plain"; + if (mimeType.isNull()) + mimeType = MIMETypeRegistry::getMIMETypeForPath(urlFilename); + if (!m_dataReceived && mimeType == "application/octet-stream") { + // For empty content, if can't guess its mimetype from filename, we manually + // set the mimetype to "text/plain" in case it goes to download. + mimeType = "text/plain"; } m_response.setMimeType(mimeType); diff --git a/Source/WebCore/platform/network/blackberry/ResourceRequest.h b/Source/WebCore/platform/network/blackberry/ResourceRequest.h index fdd9db28a..1b0f958f8 100644 --- a/Source/WebCore/platform/network/blackberry/ResourceRequest.h +++ b/Source/WebCore/platform/network/blackberry/ResourceRequest.h @@ -107,7 +107,7 @@ public: bool mustHandleInternally() const { return m_mustHandleInternally; } void initializePlatformRequest(BlackBerry::Platform::NetworkRequest&, bool cookiesEnabled, bool isInitial = false, bool isRedirect = false) const; - void setForceDownload(bool forceDownload) { m_forceDownload = true; } + void setForceDownload(bool forceDownload) { m_forceDownload = forceDownload; } bool forceDownload() const { return m_forceDownload; } void setSuggestedSaveName(const String& name) { m_suggestedSaveName = name; } String suggestedSaveName() const { return m_suggestedSaveName; } diff --git a/Source/WebCore/platform/network/mac/UTIUtilities.h b/Source/WebCore/platform/network/mac/UTIUtilities.h new file mode 100644 index 000000000..b3787edd7 --- /dev/null +++ b/Source/WebCore/platform/network/mac/UTIUtilities.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 UTIUtilities_h +#define UTIUtilities_h + +#import <wtf/RetainPtr.h> + +namespace WebCore { +RetainPtr<CFStringRef> mimeTypeFromUTITree(CFStringRef uti); +} + +#endif // UTIUtilities_h diff --git a/Source/WebCore/platform/network/mac/UTIUtilities.mm b/Source/WebCore/platform/network/mac/UTIUtilities.mm new file mode 100644 index 000000000..9cdc0d629 --- /dev/null +++ b/Source/WebCore/platform/network/mac/UTIUtilities.mm @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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. + */ + +#import "config.h" +#import "UTIUtilities.h" + +#if PLATFORM(IOS) +#import "SoftLinking.h" +#import <MobileCoreServices/MobileCoreServices.h> + +SOFT_LINK_FRAMEWORK(MobileCoreServices) + +SOFT_LINK(MobileCoreServices, UTTypeCopyDeclaration, CFDictionaryRef, (CFStringRef inUTI), (inUTI)) +SOFT_LINK(MobileCoreServices, UTTypeCopyPreferredTagWithClass, CFStringRef, (CFStringRef inUTI, CFStringRef inTagClass), (inUTI, inTagClass)) + +SOFT_LINK_CONSTANT(MobileCoreServices, kUTTypeConformsToKey, CFStringRef) +SOFT_LINK_CONSTANT(MobileCoreServices, kUTTagClassMIMEType, CFStringRef) + +#define kUTTagClassMIMEType getkUTTagClassMIMEType() +#define kUTTypeConformsToKey getkUTTypeConformsToKey() +#endif + +namespace WebCore { + +RetainPtr<CFStringRef> mimeTypeFromUTITree(CFStringRef uti) +{ + // Check if this UTI has a MIME type. + RetainPtr<CFStringRef> mimeType(AdoptCF, UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)); + if (mimeType) + return mimeType.get(); + + // If not, walk the ancestory of this UTI via its "ConformsTo" tags and return the first MIME type we find. + RetainPtr<CFDictionaryRef> decl(AdoptCF, UTTypeCopyDeclaration(uti)); + if (!decl) + return nil; + CFTypeRef value = CFDictionaryGetValue(decl.get(), kUTTypeConformsToKey); + if (!value) + return nil; + CFTypeID typeID = CFGetTypeID(value); + + if (typeID == CFStringGetTypeID()) + return mimeTypeFromUTITree((CFStringRef)value); + + if (typeID == CFArrayGetTypeID()) { + CFArrayRef newTypes = (CFArrayRef)value; + CFIndex count = CFArrayGetCount(newTypes); + for (CFIndex i = 0; i < count; ++i) { + CFTypeRef object = CFArrayGetValueAtIndex(newTypes, i); + if (CFGetTypeID(object) != CFStringGetTypeID()) + continue; + + if (RetainPtr<CFStringRef> mimeType = mimeTypeFromUTITree((CFStringRef)object)) + return mimeType; + } + } + + return nil; +} + +} diff --git a/Source/WebCore/platform/network/mac/WebCoreURLResponse.mm b/Source/WebCore/platform/network/mac/WebCoreURLResponse.mm index 09604929c..be2e2767f 100644 --- a/Source/WebCore/platform/network/mac/WebCoreURLResponse.mm +++ b/Source/WebCore/platform/network/mac/WebCoreURLResponse.mm @@ -30,6 +30,7 @@ #import "WebCoreURLResponse.h" #import "MIMETypeRegistry.h" +#import "UTIUtilities.h" #import "WebCoreSystemInterface.h" #import <wtf/Assertions.h> #import <wtf/RetainPtr.h> @@ -447,41 +448,6 @@ static CFDictionaryRef createExtensionToMIMETypeMap() return CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, (const void**)&values, sizeof(keys)/sizeof(CFStringRef), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } -static RetainPtr<CFStringRef> mimeTypeFromUTITree(CFStringRef uti) -{ - // Check if this UTI has a MIME type. - RetainPtr<CFStringRef> mimeType(AdoptCF, UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)); - if (mimeType) - return mimeType.get(); - - // If not, walk the ancestory of this UTI via its "ConformsTo" tags and return the first MIME type we find. - RetainPtr<CFDictionaryRef> decl(AdoptCF, UTTypeCopyDeclaration(uti)); - if (!decl) - return nil; - CFTypeRef value = CFDictionaryGetValue(decl.get(), kUTTypeConformsToKey); - if (!value) - return nil; - CFTypeID typeID = CFGetTypeID(value); - - if (typeID == CFStringGetTypeID()) - return mimeTypeFromUTITree((CFStringRef)value); - - if (typeID == CFArrayGetTypeID()) { - CFArrayRef newTypes = (CFArrayRef)value; - CFIndex count = CFArrayGetCount(newTypes); - for (CFIndex i = 0; i < count; ++i) { - CFTypeRef object = CFArrayGetValueAtIndex(newTypes, i); - if (CFGetTypeID(object) != CFStringGetTypeID()) - continue; - - if (RetainPtr<CFStringRef> mimeType = mimeTypeFromUTITree((CFStringRef)object)) - return mimeType; - } - } - - return nil; -} - void adjustMIMETypeIfNecessary(CFURLResponseRef cfResponse) { RetainPtr<CFStringRef> result = wkGetCFURLResponseMIMEType(cfResponse); diff --git a/Source/WebCore/platform/network/soup/CookieJarSoup.cpp b/Source/WebCore/platform/network/soup/CookieJarSoup.cpp index c6e9bce57..cea115699 100644 --- a/Source/WebCore/platform/network/soup/CookieJarSoup.cpp +++ b/Source/WebCore/platform/network/soup/CookieJarSoup.cpp @@ -162,11 +162,9 @@ bool getRawCookies(const Document* document, const KURL& url, Vector<Cookie>& ra GOwnPtr<SoupCookie> cookie(static_cast<SoupCookie*>(iter->data)); if (!soup_cookie_applies_to_uri(cookie.get(), uri.get())) continue; - // FIXME: we are currently passing false always for session because there's no API to know - // whether SoupCookieJar is persistent or not. We could probably add soup_cookie_jar_is_persistent(). rawCookies.append(Cookie(String::fromUTF8(cookie->name), String::fromUTF8(cookie->value), String::fromUTF8(cookie->domain), String::fromUTF8(cookie->path), static_cast<double>(soup_date_to_time_t(cookie->expires)) * 1000, - cookie->http_only, cookie->secure, false)); + cookie->http_only, cookie->secure, soup_cookie_jar_is_persistent(jar))); } return true; diff --git a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp index 10c6fa985..60e4e1532 100644 --- a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp +++ b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp @@ -88,7 +88,7 @@ public: loadingSynchronousRequest = true; GRefPtr<GMainContext> innerMainContext = adoptGRef(g_main_context_new()); g_main_context_push_thread_default(innerMainContext.get()); - m_mainLoop = g_main_loop_new(innerMainContext.get(), false); + m_mainLoop = adoptGRef(g_main_loop_new(innerMainContext.get(), false)); adjustMaxConnections(1); } @@ -200,11 +200,13 @@ static void ensureSessionIsInitialized(SoupSession* session) setSoupCookieJar(jar); } +#if !LOG_DISABLED if (!soup_session_get_feature(session, SOUP_TYPE_LOGGER) && LogNetwork.state == WTFLogChannelOn) { SoupLogger* logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(SOUP_LOGGER_LOG_BODY), -1); soup_session_add_feature(session, SOUP_SESSION_FEATURE(logger)); g_object_unref(logger); } +#endif // !LOG_DISABLED if (!soup_session_get_feature(session, SOUP_TYPE_REQUESTER)) { SoupRequester* requester = soup_requester_new(); diff --git a/Source/WebCore/platform/qt/LoggingQt.cpp b/Source/WebCore/platform/qt/LoggingQt.cpp index a9346de81..8089e9453 100644 --- a/Source/WebCore/platform/qt/LoggingQt.cpp +++ b/Source/WebCore/platform/qt/LoggingQt.cpp @@ -20,6 +20,8 @@ #include "config.h" #include "Logging.h" +#if !LOG_DISABLED + #include "PlatformString.h" #include <QDebug> #include <QStringList> @@ -54,3 +56,5 @@ void initializeLoggingChannelsIfNecessary() } } // namespace WebCore + +#endif // !LOG_DISABLED diff --git a/Source/WebCore/platform/qt/PlatformScreenQt.cpp b/Source/WebCore/platform/qt/PlatformScreenQt.cpp index 564176422..cf381ee68 100644 --- a/Source/WebCore/platform/qt/PlatformScreenQt.cpp +++ b/Source/WebCore/platform/qt/PlatformScreenQt.cpp @@ -143,7 +143,7 @@ FloatRect screenAvailableRect(Widget* widget) return FloatRect(r.x(), r.y(), r.width(), r.height()); } -void screenColorProfile(Widget*, const String&, ColorProfile&) +void screenColorProfile(Widget*, ColorProfile&) { notImplemented(); } diff --git a/Source/WebCore/platform/qt/QWebPageClient.h b/Source/WebCore/platform/qt/QWebPageClient.h index 6c9a1ae6c..078999dc2 100644 --- a/Source/WebCore/platform/qt/QWebPageClient.h +++ b/Source/WebCore/platform/qt/QWebPageClient.h @@ -34,7 +34,7 @@ #include <GraphicsLayer.h> #endif -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) #include <GraphicsContext3D.h> #endif @@ -106,7 +106,7 @@ public: virtual void setWidgetVisible(WebCore::Widget*, bool visible) = 0; -#if ENABLE(WEBGL) +#if USE(3D_GRAPHICS) virtual void createPlatformGraphicsContext3D(PlatformGraphicsContext3D*, PlatformGraphicsSurface3D*) = 0; #endif diff --git a/Source/WebCore/platform/text/DateTimeFormat.cpp b/Source/WebCore/platform/text/DateTimeFormat.cpp new file mode 100644 index 000000000..6de7fdcde --- /dev/null +++ b/Source/WebCore/platform/text/DateTimeFormat.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" +#include "DateTimeFormat.h" + +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#include <wtf/ASCIICType.h> +#include <wtf/text/StringBuilder.h> + +namespace WebCore { + +static const DateTimeFormat::FieldType lowerCaseToFieldTypeMap[26] = { + DateTimeFormat::FieldTypePeriod, // a + DateTimeFormat::FieldTypeInvalid, // b + DateTimeFormat::FieldTypeLocalDayOfWeekStandAlon, // c + DateTimeFormat::FieldTypeDayOfMonth, // d + DateTimeFormat::FieldTypeLocalDayOfWeek, // e + DateTimeFormat::FieldTypeInvalid, // f + DateTimeFormat::FieldTypeModifiedJulianDay, // g + DateTimeFormat::FieldTypeHour12, // h + DateTimeFormat::FieldTypeInvalid, // i + DateTimeFormat::FieldTypeInvalid, // j + DateTimeFormat::FieldTypeHour24, // k + DateTimeFormat::FieldTypeInvalid, // l + DateTimeFormat::FieldTypeMinute, // m + DateTimeFormat::FieldTypeInvalid, // n + DateTimeFormat::FieldTypeInvalid, // o + DateTimeFormat::FieldTypeInvalid, // p + DateTimeFormat::FieldTypeQuaterStandAlone, // q + DateTimeFormat::FieldTypeInvalid, // r + DateTimeFormat::FieldTypeSecond, // s + DateTimeFormat::FieldTypeInvalid, // t + DateTimeFormat::FieldTypeExtendedYear, // u + DateTimeFormat::FieldTypeNonLocationZone, // v + DateTimeFormat::FieldTypeWeekOfMonth, // w + DateTimeFormat::FieldTypeInvalid, // x + DateTimeFormat::FieldTypeYear, // y + DateTimeFormat::FieldTypeZone, // z +}; + +static const DateTimeFormat::FieldType upperCaseToFieldTypeMap[26] = { + DateTimeFormat::FieldTypeMillisecondsInDay, // A + DateTimeFormat::FieldTypeInvalid, // B + DateTimeFormat::FieldTypeInvalid, // C + DateTimeFormat::FieldTypeDayOfYear, // D + DateTimeFormat::FieldTypeDayOfWeek, // E + DateTimeFormat::FieldTypeDayOfWeekInMonth, // F + DateTimeFormat::FieldTypeEra, // G + DateTimeFormat::FieldTypeHour23, // H + DateTimeFormat::FieldTypeInvalid, // I + DateTimeFormat::FieldTypeInvalid, // J + DateTimeFormat::FieldTypeHour11, // K + DateTimeFormat::FieldTypeMonthStandAlone, // L + DateTimeFormat::FieldTypeMonth, // M + DateTimeFormat::FieldTypeInvalid, // N + DateTimeFormat::FieldTypeInvalid, // O + DateTimeFormat::FieldTypeInvalid, // P + DateTimeFormat::FieldTypeQuater, // Q + DateTimeFormat::FieldTypeInvalid, // R + DateTimeFormat::FieldTypeFractionalSecond, // S + DateTimeFormat::FieldTypeInvalid, // T + DateTimeFormat::FieldTypeInvalid, // U + DateTimeFormat::FieldTypeInvalid, // V + DateTimeFormat::FieldTypeWeekOfYear, // W + DateTimeFormat::FieldTypeInvalid, // X + DateTimeFormat::FieldTypeYearOfWeekOfYear, // Y + DateTimeFormat::FieldTypeRFC822Zone, // Z +}; + +static DateTimeFormat::FieldType mapCharacterToFieldType(const UChar ch) +{ + if (isASCIIUpper(ch)) + return upperCaseToFieldTypeMap[ch - 'A']; + + if (isASCIILower(ch)) + return lowerCaseToFieldTypeMap[ch - 'a']; + + return DateTimeFormat::FieldTypeLiteral; +} + +bool DateTimeFormat::parse(const String& source, TokenHandler& tokenHandler) +{ + enum State { + StateInQuote, + StateInQuoteQuote, + StateLiteral, + StateQuote, + StateSymbol, + } state = StateLiteral; + + FieldType fieldType = FieldTypeLiteral; + StringBuilder literalBuffer; + int fieldCounter = 0; + + for (unsigned int index = 0; index < source.length(); ++index) { + const UChar ch = source[index]; + switch (state) { + case StateInQuote: + if (ch == '\'') { + state = StateInQuoteQuote; + break; + } + + literalBuffer.append(ch); + break; + + case StateInQuoteQuote: + if (ch == '\'') { + literalBuffer.append('\''); + state = StateInQuote; + break; + } + + fieldType = mapCharacterToFieldType(ch); + if (fieldType == FieldTypeInvalid) + return false; + + if (fieldType == FieldTypeLiteral) { + literalBuffer.append(ch); + state = StateLiteral; + break; + } + + if (literalBuffer.length()) { + tokenHandler.visitLiteral(literalBuffer.toString()); + literalBuffer.clear(); + } + + fieldCounter = 1; + state = StateSymbol; + break; + + case StateLiteral: + if (ch == '\'') { + state = StateQuote; + break; + } + + fieldType = mapCharacterToFieldType(ch); + if (fieldType == FieldTypeInvalid) + return false; + + if (fieldType == FieldTypeLiteral) { + literalBuffer.append(ch); + break; + } + + if (literalBuffer.length()) { + tokenHandler.visitLiteral(literalBuffer.toString()); + literalBuffer.clear(); + } + + fieldCounter = 1; + state = StateSymbol; + break; + + case StateQuote: + literalBuffer.append(ch); + state = ch == '\'' ? StateLiteral : StateInQuote; + break; + + case StateSymbol: { + ASSERT(fieldType != FieldTypeInvalid); + ASSERT(fieldType != FieldTypeLiteral); + ASSERT(literalBuffer.isEmpty()); + + FieldType fieldType2 = mapCharacterToFieldType(ch); + if (fieldType2 == FieldTypeInvalid) + return false; + + if (fieldType == fieldType2) { + ++fieldCounter; + break; + } + + tokenHandler.visitField(fieldType, fieldCounter); + + if (fieldType2 == FieldTypeLiteral) { + if (ch == '\'') + state = StateQuote; + else { + literalBuffer.append(ch); + state = StateLiteral; + } + break; + } + + fieldCounter = 1; + fieldType = fieldType2; + break; + } + } + } + + ASSERT(fieldType != FieldTypeInvalid); + + switch (state) { + case StateLiteral: + case StateInQuoteQuote: + if (literalBuffer.length()) + tokenHandler.visitLiteral(literalBuffer.toString()); + return true; + + case StateQuote: + case StateInQuote: + if (literalBuffer.length()) + tokenHandler.visitLiteral(literalBuffer.toString()); + return false; + + case StateSymbol: + ASSERT(fieldType != FieldTypeLiteral); + ASSERT(!literalBuffer.length()); + tokenHandler.visitField(fieldType, fieldCounter); + return true; + } + + ASSERT_NOT_REACHED(); + return false; +} + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/platform/text/DateTimeFormat.h b/Source/WebCore/platform/text/DateTimeFormat.h new file mode 100644 index 000000000..e7d539f2b --- /dev/null +++ b/Source/WebCore/platform/text/DateTimeFormat.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +#ifndef DateTimeFormat_h +#define DateTimeFormat_h + +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#include <wtf/text/WTFString.h> + +namespace WebCore { + +// DateTimeFormat parses date time format defined in Unicode Technical +// standard 35, Locale Data Markup Language (LDML)[1]. +// [1] LDML http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns +class DateTimeFormat { +public: + enum FieldType { + FieldTypeInvalid, + FieldTypeLiteral, + + // Era: AD + FieldTypeEra = 'G', + + // Year: 1996 + FieldTypeYear = 'y', + FieldTypeYearOfWeekOfYear = 'Y', + FieldTypeExtendedYear = 'u', + + // Quater: Q2 + FieldTypeQuater = 'Q', + FieldTypeQuaterStandAlone = 'q', + + // Month: September + FieldTypeMonth = 'M', + FieldTypeMonthStandAlone = 'L', + + // Week: 42 + FieldTypeWeekOfYear = 'W', + FieldTypeWeekOfMonth = 'w', + + // Day: 12 + FieldTypeDayOfMonth = 'd', + FieldTypeDayOfYear = 'D', + FieldTypeDayOfWeekInMonth = 'F', + FieldTypeModifiedJulianDay = 'g', + + // Week Day: Tuesday + FieldTypeDayOfWeek = 'E', + FieldTypeLocalDayOfWeek = 'e', + FieldTypeLocalDayOfWeekStandAlon = 'c', + + // Period: AM or PM + FieldTypePeriod = 'a', + + // Hour: 7 + FieldTypeHour12 = 'h', + FieldTypeHour23 = 'H', + FieldTypeHour11 = 'K', + FieldTypeHour24 = 'k', + + // Minute: 59 + FieldTypeMinute = 'm', + + // Second: 12 + FieldTypeSecond = 's', + FieldTypeFractionalSecond = 'S', + FieldTypeMillisecondsInDay = 'A', + + // Zone: PDT + FieldTypeZone = 'z', + FieldTypeRFC822Zone = 'Z', + FieldTypeNonLocationZone = 'v', + }; + + class TokenHandler { + public: + virtual ~TokenHandler() { } + virtual void visitField(FieldType, int numberOfPatternCharacters) = 0; + virtual void visitLiteral(const String&) = 0; + }; + + // Returns true if succeeded, false if failed. + static bool parse(const String&, TokenHandler&); +}; + +} // namespace WebCore + +#endif + +#endif // DateTimeFormat_h diff --git a/Source/WebCore/platform/text/LocaleICU.cpp b/Source/WebCore/platform/text/LocaleICU.cpp index f6b4ef80f..51ba4aa35 100644 --- a/Source/WebCore/platform/text/LocaleICU.cpp +++ b/Source/WebCore/platform/text/LocaleICU.cpp @@ -51,6 +51,11 @@ LocaleICU::LocaleICU(const char* locale) #if ENABLE(CALENDAR_PICKER) , m_firstDayOfWeek(0) #endif +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + , m_mediumTimeFormat(0) + , m_shortTimeFormat(0) + , m_didCreateTimeFormat(false) +#endif { } @@ -317,7 +322,7 @@ String LocaleICU::formatLocalizedDate(const DateComponents& dateComponents) return String::adopt(buffer); } -#if ENABLE(CALENDAR_PICKER) +#if ENABLE(CALENDAR_PICKER) || ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) static String getDateFormatPattern(const UDateFormat* dateFormat) { if (!dateFormat) @@ -334,7 +339,9 @@ static String getDateFormatPattern(const UDateFormat* dateFormat) return emptyString(); return String::adopt(buffer); } +#endif +#if ENABLE(CALENDAR_PICKER) static inline bool isICUYearSymbol(UChar letter) { return letter == 'y' || letter == 'Y'; @@ -493,5 +500,63 @@ unsigned LocaleICU::firstDayOfWeek() } #endif +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + +String LocaleICU::localizedDecimalSeparator() +{ + initializeDecimalFormat(); + return m_decimalSymbols[DecimalSeparatorIndex]; +} + +static PassOwnPtr<Vector<String> > createFallbackAMPMLabels() +{ + OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>()); + labels->reserveCapacity(2); + labels->append("AM"); + labels->append("PM"); + return labels.release(); +} + +void LocaleICU::initializeDateTimeFormat() +{ + if (m_didCreateTimeFormat) + return; + + // We assume ICU medium time pattern and short time pattern are compatible + // with LDML, because ICU specific pattern character "V" doesn't appear + // in both medium and short time pattern. + m_mediumTimeFormat = openDateFormat(UDAT_MEDIUM, UDAT_NONE); + m_localizedTimeFormatText = getDateFormatPattern(m_mediumTimeFormat); + + m_shortTimeFormat = openDateFormat(UDAT_SHORT, UDAT_NONE); + m_localizedShortTimeFormatText = getDateFormatPattern(m_shortTimeFormat); + + m_timeAMPMLabels = createLabelVector(m_mediumTimeFormat, UDAT_AM_PMS, UCAL_AM, 2); + if (!m_timeAMPMLabels) + m_timeAMPMLabels = createFallbackAMPMLabels(); + + m_didCreateTimeFormat = true; +} + +String LocaleICU::localizedTimeFormatText() +{ + initializeDateTimeFormat(); + return m_localizedTimeFormatText; +} + +String LocaleICU::localizedShortTimeFormatText() +{ + initializeDateTimeFormat(); + return m_localizedShortTimeFormatText; +} + +const Vector<String>& LocaleICU::timeAMPMLabels() +{ + initializeDateTimeFormat(); + return *m_timeAMPMLabels; +} + +#endif + } // namespace WebCore diff --git a/Source/WebCore/platform/text/LocaleICU.h b/Source/WebCore/platform/text/LocaleICU.h index 8c9b39e73..08667806d 100644 --- a/Source/WebCore/platform/text/LocaleICU.h +++ b/Source/WebCore/platform/text/LocaleICU.h @@ -52,6 +52,9 @@ public: // For LocalizedNumber String convertToLocalizedNumber(const String&); String convertFromLocalizedNumber(const String&); +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + String localizedDecimalSeparator(); +#endif // For LocalizedDate double parseLocalizedDate(const String&); @@ -64,6 +67,12 @@ public: unsigned firstDayOfWeek(); #endif +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + String localizedTimeFormatText(); + String localizedShortTimeFormatText(); + const Vector<String>& timeAMPMLabels(); +#endif + private: static PassOwnPtr<LocaleICU> createForCurrentLocale(); explicit LocaleICU(const char*); @@ -79,10 +88,17 @@ private: #if ENABLE(CALENDAR_PICKER) void initializeLocalizedDateFormatText(); - PassOwnPtr<Vector<String> > createLabelVector(const UDateFormat*, UDateFormatSymbolType, int32_t startIndex, int32_t size); void initializeCalendar(); #endif +#if ENABLE(CALENDAR_PICKER) || ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + PassOwnPtr<Vector<String> > createLabelVector(const UDateFormat*, UDateFormatSymbolType, int32_t startIndex, int32_t size); +#endif + +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + void initializeDateTimeFormat(); +#endif + CString m_locale; UNumberFormat* m_numberFormat; UDateFormat* m_shortDateFormat; @@ -106,6 +122,15 @@ private: OwnPtr<Vector<String> > m_weekDayShortLabels; unsigned m_firstDayOfWeek; #endif + +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + UDateFormat* m_mediumTimeFormat; + UDateFormat* m_shortTimeFormat; + String m_localizedTimeFormatText; + String m_localizedShortTimeFormatText; + OwnPtr<Vector<String> > m_timeAMPMLabels; + bool m_didCreateTimeFormat; +#endif }; } diff --git a/Source/WebCore/platform/text/LocaleWin.cpp b/Source/WebCore/platform/text/LocaleWin.cpp index 82f927551..be6685747 100644 --- a/Source/WebCore/platform/text/LocaleWin.cpp +++ b/Source/WebCore/platform/text/LocaleWin.cpp @@ -32,6 +32,9 @@ #include "LocaleWin.h" #include "DateComponents.h" +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#include "DateTimeFormat.h" +#endif #include "LocalizedStrings.h" #include <limits> #include <windows.h> @@ -590,4 +593,81 @@ const Vector<String>& LocaleWin::weekDayShortLabels() } #endif +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +static DateTimeFormat::FieldType mapCharacterToDateTimeFieldType(UChar ch) +{ + switch (ch) { + case 'h': + return DateTimeFormat::FieldTypeHour12; + + case 'H': + return DateTimeFormat::FieldTypeHour23; + + case 'm': + return DateTimeFormat::FieldTypeMinute; + + case 's': + return DateTimeFormat::FieldTypeSecond; + + case 't': + return DateTimeFormat::FieldTypePeriod; + + default: + return DateTimeFormat::FieldTypeLiteral; + } +} + +// This class used for converting Windows time pattern format[1] into LDML[2] +// time format string. +// [1] http://msdn.microsoft.com/en-us/library/windows/desktop/dd318148(v=vs.85).aspx +// [2] LDML http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns +static String convertWindowsTimeFormatToLDML(const String& windowsTimeFormat) +{ + StringBuilder builder; + int counter = 0; + DateTimeFormat::FieldType lastFieldType = DateTimeFormat::FieldTypeLiteral; + for (unsigned index = 0; index < windowsTimeFormat.length(); ++index) { + UChar const ch = windowsTimeFormat[index]; + DateTimeFormat::FieldType fieldType = mapCharacterToDateTimeFieldType(ch); + if (fieldType == DateTimeFormat::FieldTypeLiteral) + builder.append(ch); + else if (fieldType == lastFieldType) { + ++counter; + if (counter == 2 && lastFieldType != DateTimeFormat::FieldTypePeriod) + builder.append(static_cast<UChar>(lastFieldType)); + } else { + if (lastFieldType != DateTimeFormat::FieldTypeLiteral) + builder.append(static_cast<UChar>(lastFieldType)); + builder.append(static_cast<UChar>(fieldType)); + counter = 1; + } + lastFieldType = fieldType; + } + return builder.toString(); +} + +String LocaleWin::timeFormatText() +{ + if (m_timeFormatText.isEmpty()) + m_timeFormatText = convertWindowsTimeFormatToLDML(getLocaleInfoString(LOCALE_STIMEFORMAT)); + return m_timeFormatText; +} + +// Note: To make XP/Vista and Windows 7/later same behavior, we don't use +// LOCALE_SSHORTTIME. +String LocaleWin::shortTimeFormatText() +{ + return timeFormatText(); +} + +const Vector<String>& LocaleWin::timeAMPMLabels() +{ + if (m_timeAMPMLabels.isEmpty()) { + m_timeAMPMLabels.append(getLocaleInfoString(LOCALE_S1159)); + m_timeAMPMLabels.append(getLocaleInfoString(LOCALE_S2359)); + } + return m_timeAMPMLabels; +} +#endif + } diff --git a/Source/WebCore/platform/text/LocaleWin.h b/Source/WebCore/platform/text/LocaleWin.h index 6a75c9945..6f4fd8bb8 100644 --- a/Source/WebCore/platform/text/LocaleWin.h +++ b/Source/WebCore/platform/text/LocaleWin.h @@ -34,6 +34,7 @@ #include <windows.h> #include <wtf/Forward.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -54,6 +55,12 @@ public: unsigned firstDayOfWeek() { return m_firstDayOfWeek; } #endif +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + String timeFormatText(); + String shortTimeFormatText(); + const Vector<String>& timeAMPMLabels(); +#endif + // For testing. double parseDate(const String& format, int baseYear, const String& input); String formatDate(const String& format, int baseYear, int year, int month, int day); @@ -81,7 +88,10 @@ private: Vector<String> m_weekDayShortLabels; unsigned m_firstDayOfWeek; #endif - +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + String m_timeFormatText; + Vector<String> m_timeAMPMLabels; +#endif }; } diff --git a/Source/WebCore/platform/text/LocalizedDate.h b/Source/WebCore/platform/text/LocalizedDate.h index 4db5eac8e..ab6854e53 100644 --- a/Source/WebCore/platform/text/LocalizedDate.h +++ b/Source/WebCore/platform/text/LocalizedDate.h @@ -60,6 +60,22 @@ const Vector<String>& weekDayShortLabels(); // The first day of a week. 0 is Sunday, and 6 is Saturday. unsigned firstDayOfWeek(); + +#endif + +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +// Returns time format in Unicode TR35 LDML[1] containing hour, minute, and +// second with optional period(AM/PM), e.g. "h:mm:ss a" +// [1] LDML http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns +String localizedTimeFormatText(); + +// Returns time format in Unicode TR35 LDML containing hour, and minute +// with optional period(AM/PM), e.g. "h:mm a" +// Note: Some platforms return same value as localizedTimeFormatText(). +String localizedShortTimeFormatText(); + +// Returns localized period field(AM/PM) strings. +const Vector<String>& timeAMPMLabels(); #endif } // namespace WebCore diff --git a/Source/WebCore/platform/text/LocalizedDateICU.cpp b/Source/WebCore/platform/text/LocalizedDateICU.cpp index 10cb6f132..19d6d1581 100644 --- a/Source/WebCore/platform/text/LocalizedDateICU.cpp +++ b/Source/WebCore/platform/text/LocalizedDateICU.cpp @@ -92,4 +92,21 @@ unsigned firstDayOfWeek() } #endif +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +String localizedTimeFormatText() +{ + return LocaleICU::currentLocale()->localizedTimeFormatText(); +} + +String localizedShortTimeFormatText() +{ + return LocaleICU::currentLocale()->localizedShortTimeFormatText(); +} + +const Vector<String>& timeAMPMLabels() +{ + return LocaleICU::currentLocale()->timeAMPMLabels(); +} +#endif + } diff --git a/Source/WebCore/platform/text/LocalizedDateWin.cpp b/Source/WebCore/platform/text/LocalizedDateWin.cpp index bd8f367f3..51c7330a0 100644 --- a/Source/WebCore/platform/text/LocalizedDateWin.cpp +++ b/Source/WebCore/platform/text/LocalizedDateWin.cpp @@ -92,4 +92,21 @@ unsigned firstDayOfWeek() } #endif +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +String localizedTimeFormatText() +{ + return LocaleWin::currentLocale()->timeFormatText(); +} + +String localizedShortTimeFormatText() +{ + return LocaleWin::currentLocale()->shortTimeFormatText(); +} + +const Vector<String>& timeAMPMLabels() +{ + return LocaleWin::currentLocale()->timeAMPMLabels(); +} +#endif + } diff --git a/Source/WebCore/platform/text/LocalizedNumber.h b/Source/WebCore/platform/text/LocalizedNumber.h index 350dac0db..8703b74f4 100644 --- a/Source/WebCore/platform/text/LocalizedNumber.h +++ b/Source/WebCore/platform/text/LocalizedNumber.h @@ -50,6 +50,12 @@ String convertToLocalizedNumber(const String&, unsigned fractionDigits); // responsible to check the format of the resultant string. String convertFromLocalizedNumber(const String&); + +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +// Returns localized decimal separator, e.g. "." for English, "," for French. +String localizedDecimalSeparator(); +#endif + } // namespace WebCore #endif // LocalizedNumber_h diff --git a/Source/WebCore/platform/text/LocalizedNumberICU.cpp b/Source/WebCore/platform/text/LocalizedNumberICU.cpp index d8a3f98bf..3288746f9 100644 --- a/Source/WebCore/platform/text/LocalizedNumberICU.cpp +++ b/Source/WebCore/platform/text/LocalizedNumberICU.cpp @@ -45,4 +45,12 @@ String convertFromLocalizedNumber(const String& localizedNumberString) return LocaleICU::currentLocale()->convertFromLocalizedNumber(localizedNumberString); } +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + +String localizedDecimalSeparator() +{ + return LocaleICU::currentLocale()->localizedDecimalSeparator(); +} + +#endif } // namespace WebCore diff --git a/Source/WebCore/platform/text/LocalizedNumberNone.cpp b/Source/WebCore/platform/text/LocalizedNumberNone.cpp index a1400855d..d40ff2421 100644 --- a/Source/WebCore/platform/text/LocalizedNumberNone.cpp +++ b/Source/WebCore/platform/text/LocalizedNumberNone.cpp @@ -47,4 +47,13 @@ String convertFromLocalizedNumber(const String& localizedNumberString) return localizedNumberString; } +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + +UChar localizedDecimalSeparator() +{ + return '.'; +} + +#endif + } // namespace WebCore diff --git a/Source/WebCore/platform/text/SegmentedString.cpp b/Source/WebCore/platform/text/SegmentedString.cpp index 591e24941..63373ba7a 100644 --- a/Source/WebCore/platform/text/SegmentedString.cpp +++ b/Source/WebCore/platform/text/SegmentedString.cpp @@ -184,7 +184,7 @@ void SegmentedString::advanceSubstring() String SegmentedString::toString() const { - String result; + StringBuilder result; if (m_pushedChar1) { result.append(m_pushedChar1); if (m_pushedChar2) @@ -197,7 +197,7 @@ String SegmentedString::toString() const for (; it != e; ++it) it->appendTo(result); } - return result; + return result.toString(); } void SegmentedString::advance(unsigned count, UChar* consumedCharacters) @@ -222,14 +222,13 @@ void SegmentedString::advanceSlowCase() m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current; } -void SegmentedString::advanceSlowCase(int& lineNumber) +void SegmentedString::advanceAndUpdateLineNumberSlowCase() { if (m_pushedChar1) { m_pushedChar1 = m_pushedChar2; m_pushedChar2 = 0; } else if (m_currentString.m_current) { if (*m_currentString.m_current++ == '\n' && m_currentString.doNotExcludeLineNumbers()) { - ++lineNumber; ++m_currentLine; // Plus 1 because numberOfCharactersConsumed value hasn't incremented yet; it does with m_length decrement below. m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1; diff --git a/Source/WebCore/platform/text/SegmentedString.h b/Source/WebCore/platform/text/SegmentedString.h index 446218388..777a65e7a 100644 --- a/Source/WebCore/platform/text/SegmentedString.h +++ b/Source/WebCore/platform/text/SegmentedString.h @@ -22,6 +22,7 @@ #include "PlatformString.h" #include <wtf/Deque.h> +#include <wtf/text/StringBuilder.h> #include <wtf/text/TextPosition.h> namespace WebCore { @@ -54,15 +55,12 @@ public: int numberOfCharactersConsumed() const { return m_string.length() - m_length; } - void appendTo(String& str) const + void appendTo(StringBuilder& builder) const { - if (m_string.characters() == m_current) { - if (str.isEmpty()) - str = m_string; - else - str.append(m_string); - } else - str.append(String(m_current, m_length)); + if (m_string.characters() == m_current) + builder.append(m_string); + else + builder.append(String(m_current, m_length)); } public: @@ -159,12 +157,11 @@ public: advance(); } - void advancePastNewline(int& lineNumber) + void advancePastNewlineAndUpdateLineNumber() { ASSERT(*current() == '\n'); if (!m_pushedChar1 && m_currentString.m_length > 1) { int newLineFlag = m_currentString.doNotExcludeLineNumbers(); - lineNumber += newLineFlag; m_currentLine += newLineFlag; if (newLineFlag) m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1; @@ -172,7 +169,7 @@ public: m_currentChar = ++m_currentString.m_current; return; } - advanceSlowCase(lineNumber); + advanceAndUpdateLineNumberSlowCase(); } void advancePastNonNewline() @@ -186,11 +183,10 @@ public: advanceSlowCase(); } - void advance(int& lineNumber) + void advanceAndUpdateLineNumber() { if (!m_pushedChar1 && m_currentString.m_length > 1) { int newLineFlag = (*m_currentString.m_current == '\n') & m_currentString.doNotExcludeLineNumbers(); - lineNumber += newLineFlag; m_currentLine += newLineFlag; if (newLineFlag) m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1; @@ -198,7 +194,7 @@ public: m_currentChar = ++m_currentString.m_current; return; } - advanceSlowCase(lineNumber); + advanceAndUpdateLineNumberSlowCase(); } // Writes the consumed characters into consumedCharacters, which must @@ -236,7 +232,7 @@ private: void prepend(const SegmentedSubstring&); void advanceSlowCase(); - void advanceSlowCase(int& lineNumber); + void advanceAndUpdateLineNumberSlowCase(); void advanceSubstring(); const UChar* current() const { return m_currentChar; } diff --git a/Source/WebCore/platform/text/mac/LocaleMac.h b/Source/WebCore/platform/text/mac/LocaleMac.h new file mode 100644 index 000000000..6f1365f79 --- /dev/null +++ b/Source/WebCore/platform/text/mac/LocaleMac.h @@ -0,0 +1,88 @@ +/* + * 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LocaleMac_h +#define LocaleMac_h + +#include <wtf/Forward.h> +#include <wtf/RetainPtr.h> +#include <wtf/Vector.h> +#include <wtf/text/WTFString.h> + +OBJC_CLASS NSDateFormatter; +OBJC_CLASS NSLocale; + +namespace WebCore { + +class DateComponents; + +class LocaleMac { +public: + static PassOwnPtr<LocaleMac> create(const String&); + static LocaleMac* currentLocale(); + ~LocaleMac(); + double parseDate(const String&); + String formatDate(const DateComponents&); + +#if ENABLE(CALENDAR_PICKER) + String dateFormatText(); + const Vector<String>& monthLabels(); + const Vector<String>& weekDayShortLabels(); + unsigned firstDayOfWeek(); +#endif + +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + String timeFormatText(); + String shortTimeFormatText(); + const Vector<String>& timeAMPMLabels(); +#endif + +private: + explicit LocaleMac(const String&); + NSDateFormatter *createShortDateFormatter(); + + RetainPtr<NSLocale> m_locale; +#if ENABLE(CALENDAR_PICKER) + String m_localizedDateFormatText; + Vector<String> m_monthLabels; + Vector<String> m_weekDayShortLabels; +#endif +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + NSDateFormatter *createTimeFormatter(); + NSDateFormatter *createShortTimeFormatter(); + + String m_localizedTimeFormatText; + String m_localizedShortTimeFormatText; + Vector<String> m_timeAMPMLabels; +#endif +}; + +} +#endif diff --git a/Source/WebCore/platform/text/mac/LocalizedDateMac.mm b/Source/WebCore/platform/text/mac/LocaleMac.mm index 08876f9d3..219e95c84 100644 --- a/Source/WebCore/platform/text/mac/LocalizedDateMac.mm +++ b/Source/WebCore/platform/text/mac/LocaleMac.mm @@ -29,12 +29,14 @@ */ #include "config.h" -#include "LocalizedDate.h" +#include "LocaleMac.h" #import <Foundation/NSDateFormatter.h> +#import <Foundation/NSLocale.h> +#include "LocalizedDate.h" #include "LocalizedStrings.h" -#include <limits> #include <wtf/DateMath.h> +#include <wtf/PassOwnPtr.h> #include <wtf/RetainPtr.h> #include <wtf/text/StringBuilder.h> @@ -42,54 +44,56 @@ using namespace std; namespace WebCore { -static NSDateFormatter *createShortDateFormatter() +static NSDateFormatter* createDateTimeFormatter(NSLocale* locale, NSDateFormatterStyle dateStyle, NSDateFormatterStyle timeStyle) { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; - [formatter setDateStyle:NSDateFormatterShortStyle]; - [formatter setTimeStyle:NSDateFormatterNoStyle]; + [formatter setLocale:locale]; + [formatter setDateStyle:dateStyle]; + [formatter setTimeStyle:timeStyle]; [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; [formatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]]; return formatter; } -double parseLocalizedDate(const String& input, DateComponents::Type type) +LocaleMac::LocaleMac(const String& localeIdentifier) + : m_locale([[NSLocale alloc] initWithLocaleIdentifier:localeIdentifier]) { - switch (type) { - case DateComponents::Date: { - RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); - NSDate *date = [formatter.get() dateFromString:input]; - if (!date) - break; - return [date timeIntervalSince1970] * msPerSecond; - } - case DateComponents::DateTime: - case DateComponents::DateTimeLocal: - case DateComponents::Month: - case DateComponents::Time: - case DateComponents::Week: - case DateComponents::Invalid: - break; - } - return numeric_limits<double>::quiet_NaN(); } -String formatLocalizedDate(const DateComponents& dateComponents) +LocaleMac::~LocaleMac() { - switch (dateComponents.type()) { - case DateComponents::Date: { - RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); - NSTimeInterval interval = dateComponents.millisecondsSinceEpoch() / msPerSecond; - return String([formatter.get() stringFromDate:[NSDate dateWithTimeIntervalSince1970:interval]]); - } - case DateComponents::DateTime: - case DateComponents::DateTimeLocal: - case DateComponents::Month: - case DateComponents::Time: - case DateComponents::Week: - case DateComponents::Invalid: - break; - } - return String(); +} + +PassOwnPtr<LocaleMac> LocaleMac::create(const String& localeIdentifier) +{ + return adoptPtr(new LocaleMac(localeIdentifier)); +} + +LocaleMac* LocaleMac::currentLocale() +{ + static LocaleMac* currentLocale = LocaleMac::create([[NSLocale currentLocale] localeIdentifier]).leakPtr(); + return currentLocale; +} + +NSDateFormatter* LocaleMac::createShortDateFormatter() +{ + return createDateTimeFormatter(m_locale.get(), NSDateFormatterShortStyle, NSDateFormatterNoStyle); +} + +double LocaleMac::parseDate(const String& input) +{ + RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); + NSDate *date = [formatter.get() dateFromString:input]; + if (!date) + return std::numeric_limits<double>::quiet_NaN(); + return [date timeIntervalSince1970] * msPerSecond; +} + +String LocaleMac::formatDate(const DateComponents& dateComponents) +{ + RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); + NSTimeInterval interval = dateComponents.millisecondsSinceEpoch() / msPerSecond; + return String([formatter.get() stringFromDate:[NSDate dateWithTimeIntervalSince1970:interval]]); } #if ENABLE(CALENDAR_PICKER) @@ -140,57 +144,55 @@ static String localizeDateFormat(const String& format) return buffer.toString(); } -String localizedDateFormatText() +String LocaleMac::dateFormatText() { - DEFINE_STATIC_LOCAL(String, text, ()); - if (!text.isEmpty()) - return text; + if (!m_localizedDateFormatText.isEmpty()) + return m_localizedDateFormatText; RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); - text = localizeDateFormat(String([formatter.get() dateFormat])); - return text; + m_localizedDateFormatText = localizeDateFormat(String([formatter.get() dateFormat])); + return m_localizedDateFormatText; } -const Vector<String>& monthLabels() +const Vector<String>& LocaleMac::monthLabels() { - DEFINE_STATIC_LOCAL(Vector<String>, labels, ()); - if (!labels.isEmpty()) - return labels; - labels.reserveCapacity(12); + if (!m_monthLabels.isEmpty()) + return m_monthLabels; + m_monthLabels.reserveCapacity(12); RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); NSArray *array = [formatter.get() monthSymbols]; if ([array count] == 12) { for (unsigned i = 0; i < 12; ++i) - labels.append(String([array objectAtIndex:i])); - return labels; + m_monthLabels.append(String([array objectAtIndex:i])); + return m_monthLabels; } for (unsigned i = 0; i < WTF_ARRAY_LENGTH(WTF::monthFullName); ++i) - labels.append(WTF::monthFullName[i]); - return labels; + m_monthLabels.append(WTF::monthFullName[i]); + return m_monthLabels; } -const Vector<String>& weekDayShortLabels() +const Vector<String>& LocaleMac::weekDayShortLabels() { - DEFINE_STATIC_LOCAL(Vector<String>, labels, ()); - if (!labels.isEmpty()) - return labels; - labels.reserveCapacity(7); + if (!m_weekDayShortLabels.isEmpty()) + return m_weekDayShortLabels; + m_weekDayShortLabels.reserveCapacity(7); RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); NSArray *array = [formatter.get() shortWeekdaySymbols]; if ([array count] == 7) { for (unsigned i = 0; i < 7; ++i) - labels.append(String([array objectAtIndex:i])); - return labels; + m_weekDayShortLabels.append(String([array objectAtIndex:i])); + return m_weekDayShortLabels; } for (unsigned i = 0; i < WTF_ARRAY_LENGTH(WTF::weekdayName); ++i) { // weekdayName starts with Monday. - labels.append(WTF::weekdayName[(i + 6) % 7]); + m_weekDayShortLabels.append(WTF::weekdayName[(i + 6) % 7]); } - return labels; + return m_weekDayShortLabels; } -unsigned firstDayOfWeek() +unsigned LocaleMac::firstDayOfWeek() { RetainPtr<NSCalendar> calendar(AdoptNS, [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]); + [calendar.get() setLocale:m_locale.get()]; // The document for NSCalendar - firstWeekday doesn't have an explanation of // firstWeekday value. We can guess it by the document of NSDateComponents - // weekDay, so it can be 1 through 7 and 1 is Sunday. @@ -198,4 +200,44 @@ unsigned firstDayOfWeek() } #endif +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +NSDateFormatter* LocaleMac::createTimeFormatter() +{ + return createDateTimeFormatter(m_locale.get(), NSDateFormatterNoStyle, NSDateFormatterMediumStyle); +} + +NSDateFormatter* LocaleMac::createShortTimeFormatter() +{ + return createDateTimeFormatter(m_locale.get(), NSDateFormatterNoStyle, NSDateFormatterShortStyle); +} + +String LocaleMac::timeFormatText() +{ + if (!m_localizedTimeFormatText.isEmpty()) + return m_localizedTimeFormatText; + RetainPtr<NSDateFormatter> formatter(AdoptNS, createTimeFormatter()); + m_localizedTimeFormatText = String([formatter.get() dateFormat]); + return m_localizedTimeFormatText; +} + +String LocaleMac::shortTimeFormatText() +{ + if (!m_localizedShortTimeFormatText.isEmpty()) + return m_localizedShortTimeFormatText; + RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortTimeFormatter()); + m_localizedShortTimeFormatText = String([formatter.get() dateFormat]); + return m_localizedShortTimeFormatText; +} + +const Vector<String>& LocaleMac::timeAMPMLabels() +{ + if (!m_timeAMPMLabels.isEmpty()) + return m_timeAMPMLabels; + m_timeAMPMLabels.reserveCapacity(2); + RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortTimeFormatter()); + m_timeAMPMLabels.append(String([formatter.get() AMSymbol])); + m_timeAMPMLabels.append(String([formatter.get() PMSymbol])); + return m_timeAMPMLabels; +} +#endif } diff --git a/Source/WebCore/platform/text/mac/LocalizedDateMac.cpp b/Source/WebCore/platform/text/mac/LocalizedDateMac.cpp new file mode 100644 index 000000000..9597fa081 --- /dev/null +++ b/Source/WebCore/platform/text/mac/LocalizedDateMac.cpp @@ -0,0 +1,112 @@ +/* + * 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "LocalizedDate.h" + +#include "LocaleMac.h" +#include <limits> + +using namespace std; + +namespace WebCore { + +double parseLocalizedDate(const String& input, DateComponents::Type type) +{ + switch (type) { + case DateComponents::Date: + return LocaleMac::currentLocale()->parseDate(input); + case DateComponents::DateTime: + case DateComponents::DateTimeLocal: + case DateComponents::Month: + case DateComponents::Time: + case DateComponents::Week: + case DateComponents::Invalid: + break; + } + return numeric_limits<double>::quiet_NaN(); +} + +String formatLocalizedDate(const DateComponents& dateComponents) +{ + switch (dateComponents.type()) { + case DateComponents::Date: + return LocaleMac::currentLocale()->formatDate(dateComponents); + case DateComponents::DateTime: + case DateComponents::DateTimeLocal: + case DateComponents::Month: + case DateComponents::Time: + case DateComponents::Week: + case DateComponents::Invalid: + break; + } + return String(); +} + +#if ENABLE(CALENDAR_PICKER) +String localizedDateFormatText() +{ + return LocaleMac::currentLocale()->dateFormatText(); +} + +const Vector<String>& monthLabels() +{ + return LocaleMac::currentLocale()->monthLabels(); +} + +const Vector<String>& weekDayShortLabels() +{ + return LocaleMac::currentLocale()->weekDayShortLabels(); +} + +unsigned firstDayOfWeek() +{ + return LocaleMac::currentLocale()->firstDayOfWeek(); +} +#endif + +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +String localizedTimeFormatText() +{ + return LocaleMac::currentLocale()->timeFormatText(); +} + +String localizedShortTimeFormatText() +{ + return LocaleMac::currentLocale()->shortTimeFormatText(); +} + +const Vector<String>& timeAMPMLabels() +{ + return LocaleMac::currentLocale()->timeAMPMLabels(); +} +#endif + +} diff --git a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm b/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm index 031362b2b..26ebf3d8e 100644 --- a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm +++ b/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm @@ -116,5 +116,15 @@ String convertFromLocalizedNumber(const String& localizedNumberString) return String(numberToString(doubleValue, buffer)); } +#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + +String localizedDecimalSeparator() +{ + RetainPtr<NSNumberFormatter> formatter = numberFormatterForDisplay(); + return String([formatter.get() decimalSeparator]); +} + +#endif + } // namespace WebCore diff --git a/Source/WebCore/platform/win/LoggingWin.cpp b/Source/WebCore/platform/win/LoggingWin.cpp index 0b0afada7..6d353ed92 100644 --- a/Source/WebCore/platform/win/LoggingWin.cpp +++ b/Source/WebCore/platform/win/LoggingWin.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "Logging.h" +#if !LOG_DISABLED + #include "PlatformString.h" #include <windows.h> #include <wtf/OwnArrayPtr.h> @@ -102,3 +104,5 @@ void initializeLoggingChannelsIfNecessary() } } // namespace WebCore + +#endif // !LOG_DISABLED diff --git a/Source/WebCore/platform/win/PlatformScreenWin.cpp b/Source/WebCore/platform/win/PlatformScreenWin.cpp index e1bbf5968..21bf23c63 100644 --- a/Source/WebCore/platform/win/PlatformScreenWin.cpp +++ b/Source/WebCore/platform/win/PlatformScreenWin.cpp @@ -118,7 +118,7 @@ FloatRect screenAvailableRect(Widget* widget) return monitorInfo.rcWork; } -void screenColorProfile(Widget*, const String&, ColorProfile&) +void screenColorProfile(Widget*, ColorProfile&) { notImplemented(); } diff --git a/Source/WebCore/platform/wx/LoggingWx.cpp b/Source/WebCore/platform/wx/LoggingWx.cpp index 94893e91e..86a47ac16 100644 --- a/Source/WebCore/platform/wx/LoggingWx.cpp +++ b/Source/WebCore/platform/wx/LoggingWx.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "Logging.h" +#if !LOG_DISABLED + #include "PlatformString.h" #include <wtf/Vector.h> #include <wtf/text/CString.h> @@ -62,3 +64,5 @@ void initializeLoggingChannelsIfNecessary() } } + +#endif // !LOG_DISABLED |