diff options
Diffstat (limited to 'Source/WebCore/platform/graphics')
235 files changed, 5036 insertions, 4928 deletions
diff --git a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp index b64723a08..22ffac004 100644 --- a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp +++ b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp @@ -39,6 +39,82 @@ inline static int getValidationResultValue(const ShHandle compiler, ShShaderInfo return value; } +static bool getSymbolInfo(ShHandle compiler, ShShaderInfo symbolType, Vector<ANGLEShaderSymbol>& symbols) +{ + ShShaderInfo symbolMaxNameLengthType; + + switch (symbolType) { + case SH_ACTIVE_ATTRIBUTES: + symbolMaxNameLengthType = SH_ACTIVE_ATTRIBUTE_MAX_LENGTH; + break; + case SH_ACTIVE_UNIFORMS: + symbolMaxNameLengthType = SH_ACTIVE_UNIFORM_MAX_LENGTH; + break; + default: + ASSERT_NOT_REACHED(); + return false; + } + + int numSymbols = getValidationResultValue(compiler, symbolType); + if (numSymbols < 0) + return false; + + int maxNameLength = getValidationResultValue(compiler, symbolMaxNameLengthType); + if (maxNameLength <= 1) + return false; + + int maxMappedNameLength = getValidationResultValue(compiler, SH_MAPPED_NAME_MAX_LENGTH); + if (maxMappedNameLength <= 1) + return false; + + // The maximum allowed symbol name length is 256 characters. + Vector<char, 256> nameBuffer(maxNameLength); + Vector<char, 256> mappedNameBuffer(maxMappedNameLength); + + for (int i = 0; i < numSymbols; ++i) { + ANGLEShaderSymbol symbol; + int nameLength = -1; + switch (symbolType) { + case SH_ACTIVE_ATTRIBUTES: + symbol.symbolType = SHADER_SYMBOL_TYPE_ATTRIBUTE; + ShGetActiveAttrib(compiler, i, &nameLength, &symbol.size, &symbol.dataType, nameBuffer.data(), mappedNameBuffer.data()); + break; + case SH_ACTIVE_UNIFORMS: + symbol.symbolType = SHADER_SYMBOL_TYPE_UNIFORM; + ShGetActiveUniform(compiler, i, &nameLength, &symbol.size, &symbol.dataType, nameBuffer.data(), mappedNameBuffer.data()); + break; + default: + ASSERT_NOT_REACHED(); + return false; + } + if (nameLength <= 0) + return false; + + // The ShGetActive* calls above are guaranteed to produce null-terminated strings for + // nameBuffer and mappedNameBuffer. Also, the character set for symbol names + // is a subset of Latin-1 as specified by the OpenGL ES Shading Language, Section 3.1 and + // WebGL, Section "Characters Outside the GLSL Source Character Set". + + // If the variable is an array, add symbols for each array element + if (symbol.size > 1) { + for (int i = 0; i < symbol.size; i++) { + String name = nameBuffer.data(); + String mappedName = mappedNameBuffer.data(); + name.replace(name.length() - 2, 1, String::number(i)); + mappedName.replace(mappedName.length() - 2, 1, String::number(i)); + symbol.name = name; + symbol.mappedName = mappedName; + symbols.append(symbol); + } + } else { + symbol.name = String(nameBuffer.data()); + symbol.mappedName = String(mappedNameBuffer.data()); + symbols.append(symbol); + } + } + return true; +} + ANGLEWebKitBridge::ANGLEWebKitBridge(ShShaderOutput shaderOutput, ShShaderSpec shaderSpec) : builtCompilers(false) , m_fragmentCompiler(0) @@ -75,7 +151,7 @@ void ANGLEWebKitBridge::setResources(ShBuiltInResources resources) m_resources = resources; } -bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, int extraCompileOptions) +bool ANGLEWebKitBridge::compileShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions) { if (!builtCompilers) { m_fragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, m_shaderSpec, m_shaderOutput, &m_resources); @@ -97,7 +173,7 @@ bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShad const char* const shaderSourceStrings[] = { shaderSource }; - bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | extraCompileOptions); + bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS | extraCompileOptions); if (!validateSuccess) { int logSize = getValidationResultValue(compiler, SH_INFO_LOG_LENGTH); if (logSize > 1) { @@ -118,35 +194,11 @@ bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShad ShGetObjectCode(compiler, translationBuffer.get()); translatedShaderSource = translationBuffer.get(); } - - return true; -} - -bool ANGLEWebKitBridge::getUniforms(ShShaderType shaderType, Vector<ANGLEShaderSymbol> &symbols) -{ - const ShHandle compiler = (shaderType == SH_VERTEX_SHADER ? m_vertexCompiler : m_fragmentCompiler); - - int numUniforms = getValidationResultValue(compiler, SH_ACTIVE_UNIFORMS); - if (numUniforms < 0) + + if (!getSymbolInfo(compiler, SH_ACTIVE_ATTRIBUTES, symbols)) return false; - if (!numUniforms) - return true; - - int maxNameLength = getValidationResultValue(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH); - if (maxNameLength <= 1) + if (!getSymbolInfo(compiler, SH_ACTIVE_UNIFORMS, symbols)) return false; - OwnArrayPtr<char> nameBuffer = adoptArrayPtr(new char[maxNameLength]); - - for (int i = 0; i < numUniforms; ++i) { - ANGLEShaderSymbol symbol; - symbol.symbolType = SHADER_SYMBOL_TYPE_UNIFORM; - int nameLength = -1; - ShGetActiveUniform(compiler, i, &nameLength, &symbol.size, &symbol.dataType, nameBuffer.get(), 0); - if (nameLength <= 0) - return false; - symbol.name = String::fromUTF8(nameBuffer.get(), nameLength); - symbols.append(symbol); - } return true; } diff --git a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h index 19c504eb3..178d3bddc 100644 --- a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h +++ b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h @@ -50,15 +50,17 @@ enum ANGLEShaderSymbolType { struct ANGLEShaderSymbol { ANGLEShaderSymbolType symbolType; String name; + String mappedName; ShDataType dataType; int size; bool isSampler() { - return dataType == SH_SAMPLER_2D + return symbolType == SHADER_SYMBOL_TYPE_UNIFORM + && (dataType == SH_SAMPLER_2D || dataType == SH_SAMPLER_CUBE || dataType == SH_SAMPLER_2D_RECT_ARB - || dataType == SH_SAMPLER_EXTERNAL_OES; + || dataType == SH_SAMPLER_EXTERNAL_OES); } }; @@ -71,12 +73,7 @@ public: ShBuiltInResources getResources() { return m_resources; } void setResources(ShBuiltInResources); - bool validateShaderSource(const char* shaderSource, ANGLEShaderType, String& translatedShaderSource, String& shaderValidationLog, int extraCompileOptions = 0); - - // Get the uniforms for the last validated shader of type ShShaderType. - // For this function to work, you must use the SH_ATTRIBUTES_UNIFORMS compile option during validation. - // Returns false if an unexpected error occurred in ANGLE. - bool getUniforms(ShShaderType, Vector<ANGLEShaderSymbol> &symbols); + bool compileShaderSource(const char* shaderSource, ANGLEShaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions = 0); private: diff --git a/Source/WebCore/platform/graphics/BitmapImage.cpp b/Source/WebCore/platform/graphics/BitmapImage.cpp index d0a2aabd1..def072ee0 100644 --- a/Source/WebCore/platform/graphics/BitmapImage.cpp +++ b/Source/WebCore/platform/graphics/BitmapImage.cpp @@ -580,13 +580,18 @@ void BitmapImage::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const info.addMember(m_source); info.addMember(m_frameTimer); info.addMember(m_frames); - for (unsigned i = 0; i < m_frameCount; ++i) { +} + +void FrameData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Image); #if OS(WINCE) && !PLATFORM(QT) - info.addRawBuffer(m_frames[i].m_frame.get(), m_frames[i].m_frameBytes); + info.addRawBuffer(m_frame.get(), m_frameBytes); +#elif USE(SKIA) + info.addMember(m_frame); #else - info.addRawBuffer(m_frames[i].m_frame, m_frames[i].m_frameBytes); + info.addRawBuffer(m_frame, m_frameBytes); #endif - } } } diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h index 3f23dcedf..8fedc3e50 100644 --- a/Source/WebCore/platform/graphics/BitmapImage.h +++ b/Source/WebCore/platform/graphics/BitmapImage.h @@ -88,6 +88,8 @@ public: // Returns whether there was cached image data to clear. bool clear(bool clearMetadata); + void reportMemoryUsage(MemoryObjectInfo*) const; + NativeImagePtr m_frame; ImageOrientation m_orientation; float m_duration; diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp index 30d8d3d41..423d14726 100644 --- a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp +++ b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp @@ -53,7 +53,7 @@ void DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded(double timestamp) } DisplayRefreshMonitor::DisplayRefreshMonitor(PlatformDisplayID displayID) - : m_timestamp(0) + : m_monotonicAnimationStartTime(0) , m_active(true) , m_scheduled(false) , m_previousFrameDone(true) @@ -91,7 +91,7 @@ bool DisplayRefreshMonitor::removeClient(DisplayRefreshMonitorClient* client) void DisplayRefreshMonitor::displayDidRefresh() { - double timestamp; + double monotonicAnimationStartTime; { MutexLocker lock(m_mutex); if (!m_scheduled) @@ -100,7 +100,7 @@ void DisplayRefreshMonitor::displayDidRefresh() m_unscheduledFireCount = 0; m_scheduled = false; - timestamp = m_timestamp; + monotonicAnimationStartTime = m_monotonicAnimationStartTime; } // The call back can cause all our clients to be unregistered, so we need to protect @@ -110,7 +110,7 @@ void DisplayRefreshMonitor::displayDidRefresh() Vector<DisplayRefreshMonitorClient*> clients; copyToVector(m_clients, clients); for (size_t i = 0; i < clients.size(); ++i) - clients[i]->fireDisplayRefreshIfNeeded(timestamp); + clients[i]->fireDisplayRefreshIfNeeded(monotonicAnimationStartTime); { MutexLocker lock(m_mutex); @@ -136,8 +136,8 @@ DisplayRefreshMonitor* DisplayRefreshMonitorManager::ensureMonitorForClient(Disp m_monitors.add(client->m_displayID, monitor.release()); return result; } - - return it->second.get(); + it->value->addClient(client); + return it->value.get(); } void DisplayRefreshMonitorManager::registerClient(DisplayRefreshMonitorClient* client) @@ -157,7 +157,7 @@ void DisplayRefreshMonitorManager::unregisterClient(DisplayRefreshMonitorClient* if (it == m_monitors.end()) return; - DisplayRefreshMonitor* monitor = it->second.get(); + DisplayRefreshMonitor* monitor = it->value.get(); if (monitor->removeClient(client)) { if (!monitor->hasClients()) m_monitors.remove(it); diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h index 6917d6e7b..ddf4b357a 100644 --- a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h +++ b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h @@ -121,7 +121,7 @@ private: void displayDidRefresh(); static void handleDisplayRefreshedNotificationOnMainThread(void* data); - double m_timestamp; + double m_monotonicAnimationStartTime; bool m_active; bool m_scheduled; bool m_previousFrameDone; diff --git a/Source/WebCore/platform/graphics/Extensions3D.h b/Source/WebCore/platform/graphics/Extensions3D.h index 5f28afb3b..48b26ce12 100644 --- a/Source/WebCore/platform/graphics/Extensions3D.h +++ b/Source/WebCore/platform/graphics/Extensions3D.h @@ -188,6 +188,22 @@ public: virtual void insertEventMarkerEXT(const String&) = 0; virtual void pushGroupMarkerEXT(const String&) = 0; virtual void popGroupMarkerEXT(void) = 0; + + virtual bool isNVIDIA() = 0; + virtual bool isAMD() = 0; + virtual bool isIntel() = 0; + virtual String vendor() = 0; + + // If this method returns false then the system *definitely* does not support multisampling. + // It does not necessarily say the system does support it - callers must attempt to construct + // multisampled renderbuffers and check framebuffer completeness. + // Ports should implement this to return false on configurations where it is known + // that multisampling is not available. + virtual bool maySupportMultisampling() = 0; + + // Some configurations have bugs regarding built-in functions in their OpenGL drivers + // that must be avoided. Ports should implement this flag such configurations. + virtual bool requiresBuiltInFunctionEmulation() = 0; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/FloatSize.h b/Source/WebCore/platform/graphics/FloatSize.h index c029c5a95..2c9cc18e3 100644 --- a/Source/WebCore/platform/graphics/FloatSize.h +++ b/Source/WebCore/platform/graphics/FloatSize.h @@ -121,7 +121,7 @@ public: } #if PLATFORM(QT) - FloatSize(const QSizeF&); + explicit FloatSize(const QSizeF&); operator QSizeF() const; #endif diff --git a/Source/WebCore/platform/graphics/Font.cpp b/Source/WebCore/platform/graphics/Font.cpp index 714fa9a84..1b2e9b8d9 100644 --- a/Source/WebCore/platform/graphics/Font.cpp +++ b/Source/WebCore/platform/graphics/Font.cpp @@ -64,6 +64,8 @@ const uint8_t Font::s_roundingHackCharacterTable[256] = { Font::CodePath Font::s_codePath = Auto; +TypesettingFeatures Font::s_defaultTypesettingFeatures = 0; + // ============================================================================================ // Font Implementation (Cross-Platform Portion) // ============================================================================================ @@ -86,7 +88,7 @@ Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing) } Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMode fontSmoothingMode) - : m_fontList(FontFallbackList::create()) + : m_fontFallbackList(FontFallbackList::create()) , m_letterSpacing(0) , m_wordSpacing(0) , m_isPlatformFont(true) @@ -94,12 +96,12 @@ Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMo m_fontDescription.setUsePrinterFont(isPrinterFont); m_fontDescription.setFontSmoothing(fontSmoothingMode); m_needsTranscoding = fontTranscoder().needsTranscoding(fontDescription()); - m_fontList->setPlatformFont(fontData); + m_fontFallbackList->setPlatformFont(fontData); } Font::Font(const Font& other) : m_fontDescription(other.m_fontDescription) - , m_fontList(other.m_fontList) + , m_fontFallbackList(other.m_fontFallbackList) , m_letterSpacing(other.m_letterSpacing) , m_wordSpacing(other.m_wordSpacing) , m_isPlatformFont(other.m_isPlatformFont) @@ -110,7 +112,7 @@ Font::Font(const Font& other) Font& Font::operator=(const Font& other) { m_fontDescription = other.m_fontDescription; - m_fontList = other.m_fontList; + m_fontFallbackList = other.m_fontFallbackList; m_letterSpacing = other.m_letterSpacing; m_wordSpacing = other.m_wordSpacing; m_isPlatformFont = other.m_isPlatformFont; @@ -125,15 +127,15 @@ bool Font::operator==(const Font& other) const if (loadingCustomFonts() || other.loadingCustomFonts()) return false; - FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0; - FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0; + FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector() : 0; + FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList->fontSelector() : 0; return first == second - && m_fontDescription == other.m_fontDescription - && m_letterSpacing == other.m_letterSpacing - && m_wordSpacing == other.m_wordSpacing - && (m_fontList ? m_fontList->fontSelectorVersion() : 0) == (other.m_fontList ? other.m_fontList->fontSelectorVersion() : 0) - && (m_fontList ? m_fontList->generation() : 0) == (other.m_fontList ? other.m_fontList->generation() : 0); + && m_fontDescription == other.m_fontDescription + && m_letterSpacing == other.m_letterSpacing + && m_wordSpacing == other.m_wordSpacing + && (m_fontFallbackList ? m_fontFallbackList->fontSelectorVersion() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->fontSelectorVersion() : 0) + && (m_fontFallbackList ? m_fontFallbackList->generation() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->generation() : 0); } void Font::update(PassRefPtr<FontSelector> fontSelector) const @@ -143,9 +145,9 @@ void Font::update(PassRefPtr<FontSelector> fontSelector) const // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and // won't stick around long enough to get you in trouble). Still, this is pretty disgusting, // and could eventually be rectified by using RefPtrs for Fonts themselves. - if (!m_fontList) - m_fontList = FontFallbackList::create(); - m_fontList->invalidate(fontSelector); + if (!m_fontFallbackList) + m_fontFallbackList = FontFallbackList::create(); + m_fontFallbackList->invalidate(fontSelector); } void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const @@ -185,7 +187,7 @@ float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFo // If the complex text implementation cannot return fallback fonts, avoid // returning them for simple text as well. static bool returnFallbackFonts = canReturnFallbackFontsForComplexText(); - return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow || (glyphOverflow && glyphOverflow->computeBounds) ? glyphOverflow : 0); + return floatWidthForSimpleText(run, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow || (glyphOverflow && glyphOverflow->computeBounds) ? glyphOverflow : 0); } return floatWidthForComplexText(run, fallbackFonts, glyphOverflow); @@ -202,7 +204,7 @@ float Font::width(const TextRun& run, int& charsConsumed, String& glyphName) con glyphName = ""; if (codePath(run) != Complex) - return floatWidthForSimpleText(run, 0); + return floatWidthForSimpleText(run); return floatWidthForComplexText(run); } @@ -218,7 +220,7 @@ void Font::deleteLayout(TextLayout*) { } -float Font::width(TextLayout&, unsigned, unsigned) +float Font::width(TextLayout&, unsigned, unsigned, HashSet<const SimpleFontData*>*) { ASSERT_NOT_REACHED(); return 0; @@ -289,6 +291,16 @@ Font::CodePath Font::codePath() return s_codePath; } +void Font::setDefaultTypesettingFeatures(TypesettingFeatures typesettingFeatures) +{ + s_defaultTypesettingFeatures = typesettingFeatures; +} + +TypesettingFeatures Font::defaultTypesettingFeatures() +{ + return s_defaultTypesettingFeatures; +} + Font::CodePath Font::codePath(const TextRun& run) const { if (s_codePath != Auto) @@ -302,7 +314,7 @@ Font::CodePath Font::codePath(const TextRun& run) const if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0) return Complex; - if (run.length() > 1 && typesettingFeatures()) + if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this)) return Complex; if (!run.characterScanForCodePath()) diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h index a259dab07..aabcb2e70 100644 --- a/Source/WebCore/platform/graphics/Font.h +++ b/Source/WebCore/platform/graphics/Font.h @@ -51,7 +51,6 @@ class FontMetrics; class FontPlatformData; class FontSelector; class GlyphBuffer; -class GlyphPageTreeNode; class GraphicsContext; class RenderText; class TextLayout; @@ -106,7 +105,7 @@ public: PassOwnPtr<TextLayout> createLayout(RenderText*, float xPos, bool collapseWhiteSpace) const; static void deleteLayout(TextLayout*); - static float width(TextLayout&, unsigned from, unsigned len); + static float width(TextLayout&, unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts = 0); int offsetForPosition(const TextRun&, float position, bool includePartialGlyphs) const; FloatRect selectionRectForText(const TextRun&, const FloatPoint&, int h, int from = 0, int to = -1) const; @@ -125,7 +124,19 @@ public: TypesettingFeatures typesettingFeatures() const { TextRenderingMode textRenderingMode = m_fontDescription.textRenderingMode(); - TypesettingFeatures features = textRenderingMode == OptimizeLegibility || textRenderingMode == GeometricPrecision ? Kerning | Ligatures : 0; + TypesettingFeatures features = s_defaultTypesettingFeatures; + + switch(textRenderingMode) { + case AutoTextRendering: + break; + case OptimizeSpeed: + features &= ~(Kerning | Ligatures); + break; + case GeometricPrecision: + case OptimizeLegibility: + features |= Kerning | Ligatures; + break; + } switch (m_fontDescription.kerning()) { case FontDescription::NoneKerning: @@ -173,7 +184,10 @@ public: const SimpleFontData* primaryFont() const; const FontData* fontDataAt(unsigned) const; - GlyphData glyphDataForCharacter(UChar32, bool mirror, FontDataVariant = AutoVariant) const; + inline GlyphData glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant = AutoVariant) const + { + return glyphDataAndPageForCharacter(c, mirror, variant).first; + } #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) const SimpleFontData* fontDataForCombiningCharacterSequence(const UChar*, size_t length, FontDataVariant) const; #endif @@ -209,7 +223,7 @@ private: void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const; void drawGlyphBuffer(GraphicsContext*, const TextRun&, const GlyphBuffer&, const FloatPoint&) const; void drawEmphasisMarks(GraphicsContext*, const TextRun&, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const; - float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; + float floatWidthForSimpleText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; int offsetForPositionForSimpleText(const TextRun&, float position, bool includePartialGlyphs) const; FloatRect selectionRectForSimpleText(const TextRun&, const FloatPoint&, int h, int from, int to) const; @@ -235,6 +249,9 @@ public: static CodePath codePath(); static CodePath s_codePath; + static void setDefaultTypesettingFeatures(TypesettingFeatures); + static TypesettingFeatures defaultTypesettingFeatures(); + static const uint8_t s_roundingHackCharacterTable[256]; static bool isRoundingHackCharacter(UChar32 c) { @@ -262,20 +279,22 @@ public: static String normalizeSpaces(const UChar*, unsigned length); bool needsTranscoding() const { return m_needsTranscoding; } - FontFallbackList* fontList() const { return m_fontList.get(); } + FontFallbackList* fontList() const { return m_fontFallbackList.get(); } private: bool loadingCustomFonts() const { - return m_fontList && m_fontList->loadingCustomFonts(); + return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); } #if PLATFORM(QT) void initFormatForTextLayout(QTextLayout*) const; #endif + static TypesettingFeatures s_defaultTypesettingFeatures; + FontDescription m_fontDescription; - mutable RefPtr<FontFallbackList> m_fontList; + mutable RefPtr<FontFallbackList> m_fontFallbackList; short m_letterSpacing; short m_wordSpacing; bool m_isPlatformFont; @@ -288,25 +307,25 @@ inline Font::~Font() inline const SimpleFontData* Font::primaryFont() const { - ASSERT(m_fontList); - return m_fontList->primarySimpleFontData(this); + ASSERT(m_fontFallbackList); + return m_fontFallbackList->primarySimpleFontData(this); } inline const FontData* Font::fontDataAt(unsigned index) const { - ASSERT(m_fontList); - return m_fontList->fontDataAt(this, index); + ASSERT(m_fontFallbackList); + return m_fontFallbackList->fontDataAt(this, index); } inline bool Font::isFixedPitch() const { - ASSERT(m_fontList); - return m_fontList->isFixedPitch(this); + ASSERT(m_fontFallbackList); + return m_fontFallbackList->isFixedPitch(this); } inline FontSelector* Font::fontSelector() const { - return m_fontList ? m_fontList->fontSelector() : 0; + return m_fontFallbackList ? m_fontFallbackList->fontSelector() : 0; } inline float Font::tabWidth(const SimpleFontData& fontData, unsigned tabSize, float position) const diff --git a/Source/WebCore/platform/graphics/FontCache.cpp b/Source/WebCore/platform/graphics/FontCache.cpp index 9cab2fa0e..3fea6c235 100644 --- a/Source/WebCore/platform/graphics/FontCache.cpp +++ b/Source/WebCore/platform/graphics/FontCache.cpp @@ -34,7 +34,6 @@ #include "FontFallbackList.h" #include "FontPlatformData.h" #include "FontSelector.h" -#include "GlyphPageTreeNode.h" #include "OpenTypeVerticalData.h" #include "WebKitFontFamilyNames.h" #include <wtf/HashMap.h> @@ -211,7 +210,7 @@ FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fo gFontPlatformDataCache->set(key, result); foundResult = result; } else { - result = it->second; + result = it->value; foundResult = true; } @@ -229,7 +228,7 @@ FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fo } #if ENABLE(OPENTYPE_VERTICAL) -typedef HashMap<FontCache::FontFileKey, OwnPtr<OpenTypeVerticalData> > FontVerticalDataCache; +typedef HashMap<FontCache::FontFileKey, OwnPtr<OpenTypeVerticalData>, WTF::IntHash<FontCache::FontFileKey>, WTF::UnsignedWithZeroKeyHashTraits<FontCache::FontFileKey> > FontVerticalDataCache; FontVerticalDataCache& fontVerticalDataCacheInstance() { @@ -242,7 +241,7 @@ OpenTypeVerticalData* FontCache::getVerticalData(const FontFileKey& key, const F FontVerticalDataCache& fontVerticalDataCache = fontVerticalDataCacheInstance(); FontVerticalDataCache::iterator result = fontVerticalDataCache.find(key); if (result != fontVerticalDataCache.end()) - return result.get()->second.get(); + return result.get()->value.get(); OpenTypeVerticalData* verticalData = new OpenTypeVerticalData(platformData); if (!verticalData->isOpenType()) { @@ -286,7 +285,7 @@ struct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> { } }; -typedef HashMap<FontPlatformData, pair<SimpleFontData*, unsigned>, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache; +typedef HashMap<FontPlatformData, pair<RefPtr<SimpleFontData>, unsigned>, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache; static FontDataCache* gFontDataCache = 0; @@ -297,9 +296,9 @@ const int cTargetInactiveFontData = 200; const int cMaxInactiveFontData = 50; // Pretty Low Threshold const int cTargetInactiveFontData = 30; #endif -static ListHashSet<const SimpleFontData*>* gInactiveFontData = 0; +static ListHashSet<RefPtr<SimpleFontData> >* gInactiveFontData = 0; -SimpleFontData* FontCache::getCachedFontData(const FontDescription& fontDescription, const AtomicString& family, bool checkingAlternateName, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getCachedFontData(const FontDescription& fontDescription, const AtomicString& family, bool checkingAlternateName, ShouldRetain shouldRetain) { FontPlatformData* platformData = getCachedFontPlatformData(fontDescription, family, checkingAlternateName); if (!platformData) @@ -308,7 +307,7 @@ SimpleFontData* FontCache::getCachedFontData(const FontDescription& fontDescript return getCachedFontData(platformData, shouldRetain); } -SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformData, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getCachedFontData(const FontPlatformData* platformData, ShouldRetain shouldRetain) { if (!platformData) return 0; @@ -320,37 +319,37 @@ SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformDat if (!gFontDataCache) { gFontDataCache = new FontDataCache; - gInactiveFontData = new ListHashSet<const SimpleFontData*>; + gInactiveFontData = new ListHashSet<RefPtr<SimpleFontData> >; } FontDataCache::iterator result = gFontDataCache->find(*platformData); if (result == gFontDataCache->end()) { - pair<SimpleFontData*, unsigned> newValue(new SimpleFontData(*platformData), shouldRetain == Retain ? 1 : 0); + pair<RefPtr<SimpleFontData>, unsigned> newValue(SimpleFontData::create(*platformData), shouldRetain == Retain ? 1 : 0); gFontDataCache->set(*platformData, newValue); if (shouldRetain == DoNotRetain) gInactiveFontData->add(newValue.first); - return newValue.first; + return newValue.first.release(); } - if (!result.get()->second.second) { - ASSERT(gInactiveFontData->contains(result.get()->second.first)); - gInactiveFontData->remove(result.get()->second.first); + if (!result.get()->value.second) { + ASSERT(gInactiveFontData->contains(result.get()->value.first)); + gInactiveFontData->remove(result.get()->value.first); } if (shouldRetain == Retain) - result.get()->second.second++; - else if (!result.get()->second.second) { + result.get()->value.second++; + else if (!result.get()->value.second) { // If shouldRetain is DoNotRetain and count is 0, we want to remove the fontData from // gInactiveFontData (above) and re-add here to update LRU position. - gInactiveFontData->add(result.get()->second.first); + gInactiveFontData->add(result.get()->value.first); } - return result.get()->second.first; + return result.get()->value.first; } SimpleFontData* FontCache::getNonRetainedLastResortFallbackFont(const FontDescription& fontDescription) { - return getLastResortFallbackFont(fontDescription, DoNotRetain); + return getLastResortFallbackFont(fontDescription, DoNotRetain).leakRef(); } void FontCache::releaseFontData(const SimpleFontData* fontData) @@ -361,9 +360,9 @@ void FontCache::releaseFontData(const SimpleFontData* fontData) FontDataCache::iterator it = gFontDataCache->find(fontData->platformData()); ASSERT(it != gFontDataCache->end()); - ASSERT(it->second.second); - if (!--it->second.second) - gInactiveFontData->add(fontData); + ASSERT(it->value.second); + if (!--it->value.second) + gInactiveFontData->add(it->value.first); } void FontCache::purgeInactiveFontDataIfNeeded() @@ -383,11 +382,11 @@ void FontCache::purgeInactiveFontData(int count) isPurging = true; - Vector<const SimpleFontData*, 20> fontDataToDelete; - ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontData->end(); - ListHashSet<const SimpleFontData*>::iterator it = gInactiveFontData->begin(); + Vector<RefPtr<SimpleFontData>, 20> fontDataToDelete; + ListHashSet<RefPtr<SimpleFontData> >::iterator end = gInactiveFontData->end(); + ListHashSet<RefPtr<SimpleFontData> >::iterator it = gInactiveFontData->begin(); for (int i = 0; i < count && it != end; ++it, ++i) { - const SimpleFontData* fontData = *it.get(); + RefPtr<SimpleFontData>& fontData = *it.get(); gFontDataCache->remove(fontData->platformData()); // We should not delete SimpleFontData here because deletion can modify gInactiveFontData. See http://trac.webkit.org/changeset/44011 fontDataToDelete.append(fontData); @@ -401,17 +400,15 @@ void FontCache::purgeInactiveFontData(int count) gInactiveFontData->remove(gInactiveFontData->begin()); } - size_t fontDataToDeleteCount = fontDataToDelete.size(); - for (size_t i = 0; i < fontDataToDeleteCount; ++i) - delete fontDataToDelete[i]; + fontDataToDelete.clear(); if (gFontPlatformDataCache) { Vector<FontPlatformDataCacheKey> keysToRemove; keysToRemove.reserveInitialCapacity(gFontPlatformDataCache->size()); FontPlatformDataCache::iterator platformDataEnd = gFontPlatformDataCache->end(); for (FontPlatformDataCache::iterator platformData = gFontPlatformDataCache->begin(); platformData != platformDataEnd; ++platformData) { - if (platformData->second && !gFontDataCache->contains(*platformData->second)) - keysToRemove.append(platformData->first); + if (platformData->value && !gFontDataCache->contains(*platformData->value)) + keysToRemove.append(platformData->key); } size_t keysToRemoveCount = keysToRemove.size(); @@ -425,20 +422,20 @@ void FontCache::purgeInactiveFontData(int count) // Mark & sweep unused verticalData FontVerticalDataCache::iterator verticalDataEnd = fontVerticalDataCache.end(); for (FontVerticalDataCache::iterator verticalData = fontVerticalDataCache.begin(); verticalData != verticalDataEnd; ++verticalData) { - if (verticalData->second) - verticalData->second->m_inFontCache = false; + if (verticalData->value) + verticalData->value->m_inFontCache = false; } FontDataCache::iterator fontDataEnd = gFontDataCache->end(); for (FontDataCache::iterator fontData = gFontDataCache->begin(); fontData != fontDataEnd; ++fontData) { - OpenTypeVerticalData* verticalData = const_cast<OpenTypeVerticalData*>(fontData->second.first->verticalData()); + OpenTypeVerticalData* verticalData = const_cast<OpenTypeVerticalData*>(fontData->value.first->verticalData()); if (verticalData) verticalData->m_inFontCache = true; } Vector<FontFileKey> keysToRemove; keysToRemove.reserveInitialCapacity(fontVerticalDataCache.size()); for (FontVerticalDataCache::iterator verticalData = fontVerticalDataCache.begin(); verticalData != verticalDataEnd; ++verticalData) { - if (!verticalData->second || !verticalData->second->m_inFontCache) - keysToRemove.append(verticalData->first); + if (!verticalData->value || !verticalData->value->m_inFontCache) + keysToRemove.append(verticalData->key); } for (size_t i = 0, count = keysToRemove.size(); i < count; ++i) fontVerticalDataCache.take(keysToRemove[i]); @@ -462,9 +459,9 @@ size_t FontCache::inactiveFontDataCount() return 0; } -const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector) +PassRefPtr<FontData> FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector) { - FontData* result = 0; + RefPtr<FontData> result; int startIndex = familyIndex; const FontFamily* startFamily = &font.fontDescription().family(); @@ -498,14 +495,14 @@ const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontS if (fontSelector) { // Try the user's preferred standard font. - if (FontData* data = fontSelector->getFontData(font.fontDescription(), standardFamily)) - return data; + if (RefPtr<FontData> data = fontSelector->getFontData(font.fontDescription(), standardFamily)) + return data.release(); } // Still no result. Hand back our last resort fallback font. result = getLastResortFallbackFont(font.fontDescription()); } - return result; + return result.release(); } static HashSet<FontSelector*>* gClients; diff --git a/Source/WebCore/platform/graphics/FontCache.h b/Source/WebCore/platform/graphics/FontCache.h index 12fb8a328..3ae533475 100644 --- a/Source/WebCore/platform/graphics/FontCache.h +++ b/Source/WebCore/platform/graphics/FontCache.h @@ -32,6 +32,8 @@ #include <limits.h> #include <wtf/Forward.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> #include <wtf/Vector.h> #include <wtf/text/WTFString.h> #include <wtf/unicode/Unicode.h> @@ -61,11 +63,11 @@ public: enum ShouldRetain { Retain, DoNotRetain }; - const FontData* getFontData(const Font&, int& familyIndex, FontSelector*); + PassRefPtr<FontData> getFontData(const Font&, int& familyIndex, FontSelector*); void releaseFontData(const SimpleFontData*); // This method is implemented by the platform. - const SimpleFontData* getFontDataForCharacters(const Font&, const UChar* characters, int length); + PassRefPtr<SimpleFontData> getFontDataForCharacters(const Font&, const UChar* characters, int length); // Also implemented by the platform. void platformInit(); @@ -85,8 +87,8 @@ public: void getTraitsInFamily(const AtomicString&, Vector<unsigned>&); - SimpleFontData* getCachedFontData(const FontDescription&, const AtomicString&, bool checkingAlternateName = false, ShouldRetain = Retain); - SimpleFontData* getLastResortFallbackFont(const FontDescription&, ShouldRetain = Retain); + PassRefPtr<SimpleFontData> getCachedFontData(const FontDescription&, const AtomicString&, bool checkingAlternateName = false, ShouldRetain = Retain); + PassRefPtr<SimpleFontData> getLastResortFallbackFont(const FontDescription&, ShouldRetain = Retain); SimpleFontData* getNonRetainedLastResortFallbackFont(const FontDescription&); void addClient(FontSelector*); @@ -100,9 +102,9 @@ public: void purgeInactiveFontData(int count = INT_MAX); #if PLATFORM(WIN) - SimpleFontData* fontDataFromDescriptionAndLogFont(const FontDescription&, ShouldRetain, const LOGFONT& font, AtomicString& outFontFamilyName); + PassRefPtr<SimpleFontData> fontDataFromDescriptionAndLogFont(const FontDescription&, ShouldRetain, const LOGFONT&, AtomicString& outFontFamilyName); #elif PLATFORM(CHROMIUM) && OS(WINDOWS) - SimpleFontData* fontDataFromDescriptionAndLogFont(const FontDescription&, ShouldRetain, const LOGFONT& font, wchar_t* outFontFamilyName); + PassRefPtr<SimpleFontData> fontDataFromDescriptionAndLogFont(const FontDescription&, ShouldRetain, const LOGFONT&, wchar_t* outFontFamilyName); #endif #if ENABLE(OPENTYPE_VERTICAL) @@ -139,10 +141,10 @@ private: FontPlatformData* getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName = false); // These methods are implemented by each platform. - SimpleFontData* getSimilarFontPlatformData(const Font&); + PassRefPtr<SimpleFontData> getSimilarFontPlatformData(const Font&); FontPlatformData* createFontPlatformData(const FontDescription&, const AtomicString& family); - SimpleFontData* getCachedFontData(const FontPlatformData*, ShouldRetain = Retain); + PassRefPtr<SimpleFontData> getCachedFontData(const FontPlatformData*, ShouldRetain = Retain); // Don't purge if this count is > 0; int m_purgePreventCount; diff --git a/Source/WebCore/platform/graphics/FontData.h b/Source/WebCore/platform/graphics/FontData.h index 3d35d2aec..6e6e19f98 100644 --- a/Source/WebCore/platform/graphics/FontData.h +++ b/Source/WebCore/platform/graphics/FontData.h @@ -29,13 +29,15 @@ #include <wtf/FastAllocBase.h> #include <wtf/Forward.h> #include <wtf/Noncopyable.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> #include <wtf/unicode/Unicode.h> namespace WebCore { class SimpleFontData; -class FontData { +class FontData : public RefCounted<FontData> { WTF_MAKE_NONCOPYABLE(FontData); WTF_MAKE_FAST_ALLOCATED; public: FontData() diff --git a/Source/WebCore/platform/graphics/FontFallbackList.cpp b/Source/WebCore/platform/graphics/FontFallbackList.cpp index 6d11c09e3..74ab726d5 100644 --- a/Source/WebCore/platform/graphics/FontFallbackList.cpp +++ b/Source/WebCore/platform/graphics/FontFallbackList.cpp @@ -66,9 +66,9 @@ void FontFallbackList::releaseFontData() { unsigned numFonts = m_fontList.size(); for (unsigned i = 0; i < numFonts; ++i) { - if (!m_fontList[i].second) { - ASSERT(!m_fontList[i].first->isSegmented()); - fontCache()->releaseFontData(static_cast<const SimpleFontData*>(m_fontList[i].first)); + if (!m_fontList[i]->isCustomFont()) { + ASSERT(!m_fontList[i]->isSegmented()); + fontCache()->releaseFontData(static_cast<const SimpleFontData*>(m_fontList[i].get())); } } } @@ -91,7 +91,7 @@ void FontFallbackList::determinePitch(const Font* font) const const FontData* FontFallbackList::fontDataAt(const Font* font, unsigned realizedFontIndex) const { if (realizedFontIndex < m_fontList.size()) - return m_fontList[realizedFontIndex].first; // This fallback font is already in our list. + return m_fontList[realizedFontIndex].get(); // This fallback font is already in our list. // Make sure we're not passing in some crazy value here. ASSERT(realizedFontIndex == m_fontList.size()); @@ -104,21 +104,21 @@ const FontData* FontFallbackList::fontDataAt(const Font* font, unsigned realized // in |m_familyIndex|, so that we never scan the same spot in the list twice. getFontData will adjust our // |m_familyIndex| as it scans for the right font to make. ASSERT(fontCache()->generation() == m_generation); - const FontData* result = fontCache()->getFontData(*font, m_familyIndex, m_fontSelector.get()); + RefPtr<FontData> result = fontCache()->getFontData(*font, m_familyIndex, m_fontSelector.get()); if (result) { - m_fontList.append(pair<const FontData*, bool>(result, result->isCustomFont())); + m_fontList.append(result); if (result->isLoading()) m_loadingCustomFonts = true; } - return result; + return result.get(); } void FontFallbackList::setPlatformFont(const FontPlatformData& platformData) { m_familyIndex = cAllFamiliesScanned; ASSERT(fontCache()->generation() == m_generation); - const FontData* fontData = fontCache()->getCachedFontData(&platformData); - m_fontList.append(pair<const FontData*, bool>(fontData, fontData->isCustomFont())); + RefPtr<FontData> fontData = fontCache()->getCachedFontData(&platformData); + m_fontList.append(fontData); } } diff --git a/Source/WebCore/platform/graphics/FontFallbackList.h b/Source/WebCore/platform/graphics/FontFallbackList.h index 12479b2c9..88f1bc796 100644 --- a/Source/WebCore/platform/graphics/FontFallbackList.h +++ b/Source/WebCore/platform/graphics/FontFallbackList.h @@ -39,6 +39,7 @@ class FontSelector; const int cAllFamiliesScanned = -1; class FontFallbackList : public RefCounted<FontFallbackList> { + WTF_MAKE_NONCOPYABLE(FontFallbackList); public: static PassRefPtr<FontFallbackList> create() { return adoptRef(new FontFallbackList()); } @@ -63,10 +64,6 @@ public: const GlyphPages& glyphPages() const { return m_pages; } private: - friend class SVGTextRunRenderingContext; - void setGlyphPageZero(GlyphPageTreeNode* pageZero) { m_pageZero = pageZero; } - void setGlyphPages(const GlyphPages& pages) { m_pages = pages; } - FontFallbackList(); const SimpleFontData* primarySimpleFontData(const Font* f) @@ -83,8 +80,10 @@ private: void setPlatformFont(const FontPlatformData&); void releaseFontData(); - - mutable Vector<pair<const FontData*, bool>, 1> m_fontList; + void setGlyphPageZero(GlyphPageTreeNode* pageZero) { m_pageZero = pageZero; } + void setGlyphPages(const GlyphPages& pages) { m_pages = pages; } + + mutable Vector<RefPtr<FontData>, 1> m_fontList; mutable GlyphPages m_pages; mutable GlyphPageTreeNode* m_pageZero; mutable const SimpleFontData* m_cachedPrimarySimpleFontData; @@ -96,6 +95,7 @@ private: mutable bool m_loadingCustomFonts : 1; friend class Font; + friend class SVGTextRunRenderingContext; }; } diff --git a/Source/WebCore/platform/graphics/FontFastPath.cpp b/Source/WebCore/platform/graphics/FontFastPath.cpp index 3ae0ad581..7ed7a9703 100644 --- a/Source/WebCore/platform/graphics/FontFastPath.cpp +++ b/Source/WebCore/platform/graphics/FontFastPath.cpp @@ -42,9 +42,38 @@ using namespace std; namespace WebCore { -GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const +static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForCharacterWithTextOrientation(UChar32 character, TextOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber) { - return glyphDataAndPageForCharacter(c, mirror, variant).first; + if (orientation == TextOrientationVerticalRight) { + RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData(); + GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber); + GlyphPage* verticalRightPage = verticalRightNode->page(); + if (verticalRightPage) { + GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character); + // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked + // into it. + if (data.glyph != verticalRightData.glyph) + return make_pair(data, page); + // The glyphs are identical, meaning that we should just use the horizontal glyph. + if (verticalRightData.fontData) + return make_pair(verticalRightData, verticalRightPage); + } + } else if (orientation == TextOrientationUpright) { + RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData(); + GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber); + GlyphPage* uprightPage = uprightNode->page(); + if (uprightPage) { + GlyphData uprightData = uprightPage->glyphDataForCharacter(character); + // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright. + if (data.glyph == uprightData.glyph) + return make_pair(data, page); + // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that + // glyph, so we fall back to the upright data and use the horizontal glyph. + if (uprightData.fontData) + return make_pair(uprightData, uprightPage); + } + } + return make_pair(data, page); } std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const @@ -68,13 +97,13 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b unsigned pageNumber = (c / GlyphPage::size); - GlyphPageTreeNode* node = pageNumber ? m_fontList->m_pages.get(pageNumber) : m_fontList->m_pageZero; + GlyphPageTreeNode* node = pageNumber ? m_fontFallbackList->m_pages.get(pageNumber) : m_fontFallbackList->m_pageZero; if (!node) { node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber); if (pageNumber) - m_fontList->m_pages.set(pageNumber, node); + m_fontFallbackList->m_pages.set(pageNumber, node); else - m_fontList->m_pageZero = node; + m_fontFallbackList->m_pageZero = node; } GlyphPage* page = 0; @@ -95,40 +124,9 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b variant = BrokenIdeographVariant; break; } - } else { - if (m_fontDescription.textOrientation() == TextOrientationVerticalRight) { - const SimpleFontData* verticalRightFontData = data.fontData->verticalRightOrientationFontData(); - GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData, pageNumber); - GlyphPage* verticalRightPage = verticalRightNode->page(); - if (verticalRightPage) { - GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(c); - // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked - // into it. - if (data.glyph != verticalRightData.glyph) - return make_pair(data, page); - // The glyphs are identical, meaning that we should just use the horizontal glyph. - if (verticalRightData.fontData) - return make_pair(verticalRightData, verticalRightPage); - } - } else if (m_fontDescription.textOrientation() == TextOrientationUpright) { - const SimpleFontData* uprightFontData = data.fontData->uprightOrientationFontData(); - GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData, pageNumber); - GlyphPage* uprightPage = uprightNode->page(); - if (uprightPage) { - GlyphData uprightData = uprightPage->glyphDataForCharacter(c); - // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright. - if (data.glyph == uprightData.glyph) - return make_pair(data, page); - // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that - // glyph, so we fall back to the upright data and use the horizontal glyph. - if (uprightData.fontData) - return make_pair(uprightData, uprightPage); - } - } + } else + return glyphDataAndPageForCharacterWithTextOrientation(c, m_fontDescription.textOrientation(), data, page, pageNumber); - // Shouldn't be possible to even reach this point. - ASSERT_NOT_REACHED(); - } return make_pair(data, page); } @@ -139,9 +137,9 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b // Proceed with the fallback list. node = node->getChild(fontDataAt(node->level()), pageNumber); if (pageNumber) - m_fontList->m_pages.set(pageNumber, node); + m_fontFallbackList->m_pages.set(pageNumber, node); else - m_fontList->m_pageZero = node; + m_fontFallbackList->m_pageZero = node; } } if (variant != NormalVariant) { @@ -152,11 +150,11 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b if (data.fontData) { // The variantFontData function should not normally return 0. // But if it does, we will just render the capital letter big. - const SimpleFontData* variantFontData = data.fontData->variantFontData(m_fontDescription, variant); + RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(m_fontDescription, variant); if (!variantFontData) return make_pair(data, page); - GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData, pageNumber); + GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber); GlyphPage* variantPage = variantNode->page(); if (variantPage) { GlyphData data = variantPage->glyphDataForCharacter(c); @@ -176,9 +174,9 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b // Proceed with the fallback list. node = node->getChild(fontDataAt(node->level()), pageNumber); if (pageNumber) - m_fontList->m_pages.set(pageNumber, node); + m_fontFallbackList->m_pages.set(pageNumber, node); else - m_fontList->m_pageZero = node; + m_fontFallbackList->m_pageZero = node; } } @@ -198,7 +196,7 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b codeUnits[1] = U16_TRAIL(c); codeUnitsLength = 2; } - const SimpleFontData* characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength); + RefPtr<SimpleFontData> characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength); if (characterFontData) { if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && isCJKIdeographOrSymbol(c)) variant = BrokenIdeographVariant; @@ -207,7 +205,7 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b } if (characterFontData) { // Got the fallback glyph and font. - GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page(); + GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page(); GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData(); // Cache it so we don't have to do system fallback again next time. if (variant == NormalVariant) { @@ -216,12 +214,14 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b // Also, sometimes we cannot map a font for the character on WINCE, but GDI can still // display the character, probably because the font package is not installed correctly. // So we just always set the glyph to be same as the character, and let GDI solve it. - page->setGlyphDataForCharacter(c, c, characterFontData); + page->setGlyphDataForCharacter(c, c, characterFontData.get()); characterFontData->setMaxGlyphPageTreeLevel(max(characterFontData->maxGlyphPageTreeLevel(), node->level())); return make_pair(page->glyphDataForCharacter(c), page); #else page->setGlyphDataForCharacter(c, data.glyph, data.fontData); data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level())); + if (!isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback()) + return glyphDataAndPageForCharacterWithTextOrientation(c, m_fontDescription.textOrientation(), data, fallbackPage, pageNumber); #endif } return make_pair(data, page); @@ -328,7 +328,10 @@ float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int float initialAdvance; WidthIterator it(this, run, 0, false, forTextEmphasis); - it.advance(from); + // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or + // ligatures are enabled. + GlyphBuffer localGlyphBuffer; + it.advance(from, &localGlyphBuffer); float beforeWidth = it.m_runWidthSoFar; it.advance(to, &glyphBuffer); @@ -339,15 +342,13 @@ float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int if (run.rtl()) { float finalRoundingWidth = it.m_finalRoundingWidth; - it.advance(run.length()); + it.advance(run.length(), &localGlyphBuffer); initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth; } else initialAdvance = beforeWidth; - if (run.rtl()) { - for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end) - glyphBuffer.swap(i, end); - } + if (run.rtl()) + glyphBuffer.reverse(0, glyphBuffer.size()); return initialAdvance; } @@ -466,10 +467,11 @@ void Font::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const drawGlyphBuffer(context, run, markBuffer, startPoint); } -float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const +float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { WidthIterator it(this, run, fallbackFonts, glyphOverflow); - it.advance(run.length(), glyphBuffer); + GlyphBuffer glyphBuffer; + it.advance(run.length(), (typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0); if (glyphOverflow) { glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent())); @@ -483,15 +485,16 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const { + GlyphBuffer glyphBuffer; WidthIterator it(this, run); - it.advance(from); + it.advance(from, &glyphBuffer); float beforeWidth = it.m_runWidthSoFar; - it.advance(to); + it.advance(to, &glyphBuffer); float afterWidth = it.m_runWidthSoFar; // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning. if (run.rtl()) { - it.advance(run.length()); + it.advance(run.length(), &glyphBuffer); float totalWidth = it.m_runWidthSoFar; return FloatRect(floorf(point.x() + totalWidth - afterWidth), point.y(), roundf(point.x() + totalWidth - beforeWidth) - floorf(point.x() + totalWidth - afterWidth), h); } @@ -507,11 +510,11 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool inclu GlyphBuffer localGlyphBuffer; unsigned offset; if (run.rtl()) { - delta -= floatWidthForSimpleText(run, 0); + delta -= floatWidthForSimpleText(run); while (1) { offset = it.m_currentCharacter; float w; - if (!it.advanceOneCharacter(w, &localGlyphBuffer)) + if (!it.advanceOneCharacter(w, localGlyphBuffer)) break; delta += w; if (includePartialGlyphs) { @@ -526,7 +529,7 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool inclu while (1) { offset = it.m_currentCharacter; float w; - if (!it.advanceOneCharacter(w, &localGlyphBuffer)) + if (!it.advanceOneCharacter(w, localGlyphBuffer)) break; delta -= w; if (includePartialGlyphs) { diff --git a/Source/WebCore/platform/graphics/FontMetrics.h b/Source/WebCore/platform/graphics/FontMetrics.h index 11b062918..7981d8eea 100644 --- a/Source/WebCore/platform/graphics/FontMetrics.h +++ b/Source/WebCore/platform/graphics/FontMetrics.h @@ -36,6 +36,7 @@ public: , m_lineGap(0) , m_lineSpacing(0) , m_xHeight(0) + , m_hasXHeight(false) { } @@ -72,7 +73,14 @@ public: void setLineSpacing(float lineSpacing) { m_lineSpacing = lineSpacing; } float xHeight() const { return m_xHeight; } - void setXHeight(float xHeight) { m_xHeight = xHeight; } + void setXHeight(float xHeight) + { + m_xHeight = xHeight; + m_hasXHeight = true; + } + + bool hasXHeight() const { return m_hasXHeight && m_xHeight > 0; } + void setHasXHeight(bool hasXHeight) { m_hasXHeight = hasXHeight; } // Integer variants of certain metrics, used for HTML rendering. int ascent(FontBaseline baselineType = AlphabeticBaseline) const @@ -113,6 +121,7 @@ private: m_lineGap = 0; m_lineSpacing = 0; m_xHeight = 0; + m_hasXHeight = false; } unsigned m_unitsPerEm; @@ -121,6 +130,7 @@ private: float m_lineGap; float m_lineSpacing; float m_xHeight; + bool m_hasXHeight; }; static inline float scaleEmToUnits(float x, unsigned unitsPerEm) diff --git a/Source/WebCore/platform/graphics/FontSelector.h b/Source/WebCore/platform/graphics/FontSelector.h index 2c7d1494e..aaaaae2d4 100644 --- a/Source/WebCore/platform/graphics/FontSelector.h +++ b/Source/WebCore/platform/graphics/FontSelector.h @@ -27,6 +27,7 @@ #define FontSelector_h #include <wtf/Forward.h> +#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace WebCore { @@ -38,7 +39,7 @@ class FontSelectorClient; class FontSelector : public RefCounted<FontSelector> { public: virtual ~FontSelector() { } - virtual FontData* getFontData(const FontDescription&, const AtomicString& familyName) = 0; + virtual PassRefPtr<FontData> getFontData(const FontDescription&, const AtomicString& familyName) = 0; virtual void fontCacheInvalidated() { } diff --git a/Source/WebCore/platform/graphics/FontWidthVariant.h b/Source/WebCore/platform/graphics/FontWidthVariant.h index bbc98ee5c..f44329745 100644 --- a/Source/WebCore/platform/graphics/FontWidthVariant.h +++ b/Source/WebCore/platform/graphics/FontWidthVariant.h @@ -28,7 +28,17 @@ namespace WebCore { -enum FontWidthVariant { RegularWidth, HalfWidth, ThirdWidth, QuarterWidth }; +enum FontWidthVariant { + RegularWidth, + HalfWidth, + ThirdWidth, + QuarterWidth, + LastFontWidthVariant = QuarterWidth +}; + +const unsigned FontWidthVariantWidth = 2; + +COMPILE_ASSERT(LastFontWidthVariant >> FontWidthVariantWidth == 0, FontWidthVariantWidth_is_correct); } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/GlyphBuffer.h b/Source/WebCore/platform/graphics/GlyphBuffer.h index 0305ced0f..5feafb140 100644 --- a/Source/WebCore/platform/graphics/GlyphBuffer.h +++ b/Source/WebCore/platform/graphics/GlyphBuffer.h @@ -63,11 +63,32 @@ typedef Glyph GlyphBufferGlyph; // CG uses CGSize instead of FloatSize so that the result of advances() // can be passed directly to CGContextShowGlyphsWithAdvances in FontMac.mm #if USE(CG) || (OS(DARWIN) && (PLATFORM(WX) || PLATFORM(CHROMIUM))) -typedef CGSize GlyphBufferAdvance; +struct GlyphBufferAdvance : CGSize { +public: + GlyphBufferAdvance(CGSize size) : CGSize(size) + { + } + + void setWidth(CGFloat width) { this->CGSize::width = width; } + CGFloat width() const { return this->CGSize::width; } + CGFloat height() const { return this->CGSize::height; } +}; #elif OS(WINCE) // There is no cross-platform code that uses the height of GlyphBufferAdvance, // so we can save memory space on embedded devices by storing only the width -typedef float GlyphBufferAdvance; +struct GlyphBufferAdvance { +public: + GlyphBufferAdvance(float width) + : advance(width) + { + } + + void setWidth(float width) { advance = width; } + float width() const { return advance; } + +private: + float advance; +}; #else typedef FloatSize GlyphBufferAdvance; #endif @@ -94,27 +115,6 @@ public: const SimpleFontData* fontDataAt(int index) const { return m_fontData[index]; } - void swap(int index1, int index2) - { - const SimpleFontData* f = m_fontData[index1]; - m_fontData[index1] = m_fontData[index2]; - m_fontData[index2] = f; - - GlyphBufferGlyph g = m_glyphs[index1]; - m_glyphs[index1] = m_glyphs[index2]; - m_glyphs[index2] = g; - - GlyphBufferAdvance s = m_advances[index1]; - m_advances[index1] = m_advances[index2]; - m_advances[index2] = s; - -#if PLATFORM(WIN) - FloatSize offset = m_offsets[index1]; - m_offsets[index1] = m_offsets[index2]; - m_offsets[index2] = offset; -#endif - } - Glyph glyphAt(int index) const { #if USE(CAIRO) || (PLATFORM(WX) && defined(wxUSE_CAIRO) && wxUSE_CAIRO) @@ -126,13 +126,7 @@ public: float advanceAt(int index) const { -#if USE(CG) || (OS(DARWIN) && (PLATFORM(WX) || PLATFORM(CHROMIUM))) - return m_advances[index].width; -#elif OS(WINCE) - return m_advances[index]; -#else return m_advances[index].width(); -#endif } FloatSize offsetAt(int index) const @@ -192,20 +186,41 @@ public: } #endif + void reverse(int from, int length) + { + for (int i = from, end = from + length - 1; i < end; ++i, --end) + swap(i, end); + } + void expandLastAdvance(float width) { ASSERT(!isEmpty()); GlyphBufferAdvance& lastAdvance = m_advances.last(); -#if USE(CG) || (OS(DARWIN) && (PLATFORM(WX) || PLATFORM(CHROMIUM))) - lastAdvance.width += width; -#elif OS(WINCE) - lastAdvance += width; -#else - lastAdvance += FloatSize(width, 0); -#endif + lastAdvance.setWidth(lastAdvance.width() + width); } private: + void swap(int index1, int index2) + { + const SimpleFontData* f = m_fontData[index1]; + m_fontData[index1] = m_fontData[index2]; + m_fontData[index2] = f; + + GlyphBufferGlyph g = m_glyphs[index1]; + m_glyphs[index1] = m_glyphs[index2]; + m_glyphs[index2] = g; + + GlyphBufferAdvance s = m_advances[index1]; + m_advances[index1] = m_advances[index2]; + m_advances[index2] = s; + +#if PLATFORM(WIN) + FloatSize offset = m_offsets[index1]; + m_offsets[index1] = m_offsets[index2]; + m_offsets[index2] = offset; +#endif + } + Vector<const SimpleFontData*, 2048> m_fontData; Vector<GlyphBufferGlyph, 2048> m_glyphs; Vector<GlyphBufferAdvance, 2048> m_advances; diff --git a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp index 770ce122d..c11657b3d 100644 --- a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp +++ b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp @@ -55,17 +55,17 @@ GlyphPageTreeNode* GlyphPageTreeNode::getRoot(unsigned pageNumber) pageZeroRoot = new GlyphPageTreeNode; } - GlyphPageTreeNode* node = pageNumber ? roots->get(pageNumber) : pageZeroRoot; - if (!node) { - node = new GlyphPageTreeNode; + if (!pageNumber) + return pageZeroRoot; + + if (GlyphPageTreeNode* foundNode = roots->get(pageNumber)) + return foundNode; + + GlyphPageTreeNode* node = new GlyphPageTreeNode; #ifndef NDEBUG - node->m_pageNumber = pageNumber; + node->m_pageNumber = pageNumber; #endif - if (pageNumber) - roots->set(pageNumber, node); - else - pageZeroRoot = node; - } + roots->set(pageNumber, node); return node; } @@ -75,7 +75,7 @@ size_t GlyphPageTreeNode::treeGlyphPageCount() if (roots) { HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end(); for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it) - count += it->second->pageCount(); + count += it->value->pageCount(); } if (pageZeroRoot) @@ -87,9 +87,9 @@ size_t GlyphPageTreeNode::treeGlyphPageCount() size_t GlyphPageTreeNode::pageCount() const { size_t count = m_page && m_page->owner() == this ? 1 : 0; - HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator end = m_children.end(); - for (HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator it = m_children.begin(); it != end; ++it) - count += it->second->pageCount(); + GlyphPageTreeNodeMap::const_iterator end = m_children.end(); + for (GlyphPageTreeNodeMap::const_iterator it = m_children.begin(); it != end; ++it) + count += it->value->pageCount(); return count; } @@ -100,7 +100,7 @@ void GlyphPageTreeNode::pruneTreeCustomFontData(const FontData* fontData) if (roots) { HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end(); for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it) - it->second->pruneCustomFontData(fontData); + it->value->pruneCustomFontData(fontData); } if (pageZeroRoot) @@ -112,19 +112,13 @@ void GlyphPageTreeNode::pruneTreeFontData(const SimpleFontData* fontData) if (roots) { HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end(); for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it) - it->second->pruneFontData(fontData); + it->value->pruneFontData(fontData); } if (pageZeroRoot) pageZeroRoot->pruneFontData(fontData); } -GlyphPageTreeNode::~GlyphPageTreeNode() -{ - deleteAllValues(m_children); - delete m_systemFallbackChild; -} - static bool fill(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) { #if ENABLE(SVG_FONTS) @@ -242,7 +236,7 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu } zeroFilled = true; } - haveGlyphs |= fill(pageToFill, from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData()); + haveGlyphs |= fill(pageToFill, from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData().get()); if (scratchPage) { ASSERT(to <= static_cast<int>(GlyphPage::size)); for (int j = from; j < to; j++) { @@ -323,28 +317,28 @@ GlyphPageTreeNode* GlyphPageTreeNode::getChild(const FontData* fontData, unsigne ASSERT(fontData || !m_isSystemFallback); ASSERT(pageNumber == m_pageNumber); - GlyphPageTreeNode* child = fontData ? m_children.get(fontData) : m_systemFallbackChild; - if (!child) { - child = new GlyphPageTreeNode; - child->m_parent = this; - child->m_level = m_level + 1; - if (fontData && fontData->isCustomFont()) { - for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) - curr->m_customFontCount++; - } + if (GlyphPageTreeNode* foundChild = fontData ? m_children.get(fontData) : m_systemFallbackChild.get()) + return foundChild; + + GlyphPageTreeNode* child = new GlyphPageTreeNode; + child->m_parent = this; + child->m_level = m_level + 1; + if (fontData && fontData->isCustomFont()) { + for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) + curr->m_customFontCount++; + } #ifndef NDEBUG - child->m_pageNumber = m_pageNumber; + child->m_pageNumber = m_pageNumber; #endif - if (fontData) { - m_children.set(fontData, child); - fontData->setMaxGlyphPageTreeLevel(max(fontData->maxGlyphPageTreeLevel(), child->m_level)); - } else { - m_systemFallbackChild = child; - child->m_isSystemFallback = true; - } - child->initializePage(fontData, pageNumber); + if (fontData) { + m_children.set(fontData, adoptPtr(child)); + fontData->setMaxGlyphPageTreeLevel(max(fontData->maxGlyphPageTreeLevel(), child->m_level)); + } else { + m_systemFallbackChild = adoptPtr(child); + child->m_isSystemFallback = true; } + child->initializePage(fontData, pageNumber); return child; } @@ -354,41 +348,33 @@ void GlyphPageTreeNode::pruneCustomFontData(const FontData* fontData) return; // Prune any branch that contains this FontData. - GlyphPageTreeNode* node = m_children.get(fontData); - if (node) { - m_children.remove(fontData); - unsigned fontCount = node->m_customFontCount + 1; - delete node; - for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) - curr->m_customFontCount -= fontCount; + if (OwnPtr<GlyphPageTreeNode> node = m_children.take(fontData)) { + if (unsigned customFontCount = node->m_customFontCount + 1) { + for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) + curr->m_customFontCount -= customFontCount; + } } // Check any branches that remain that still have custom fonts underneath them. if (!m_customFontCount) return; - HashMap<const FontData*, GlyphPageTreeNode*>::iterator end = m_children.end(); - for (HashMap<const FontData*, GlyphPageTreeNode*>::iterator it = m_children.begin(); it != end; ++it) - it->second->pruneCustomFontData(fontData); + + GlyphPageTreeNodeMap::iterator end = m_children.end(); + for (GlyphPageTreeNodeMap::iterator it = m_children.begin(); it != end; ++it) + it->value->pruneCustomFontData(fontData); } void GlyphPageTreeNode::pruneFontData(const SimpleFontData* fontData, unsigned level) { ASSERT(fontData); - if (!fontData) - return; // Prune fall back child (if any) of this font. if (m_systemFallbackChild && m_systemFallbackChild->m_page) m_systemFallbackChild->m_page->clearForFontData(fontData); // Prune any branch that contains this FontData. - HashMap<const FontData*, GlyphPageTreeNode*>::iterator child = m_children.find(fontData); - if (child != m_children.end()) { - GlyphPageTreeNode* node = child->second; - m_children.remove(fontData); - unsigned customFontCount = node->m_customFontCount; - delete node; - if (customFontCount) { + if (OwnPtr<GlyphPageTreeNode> node = m_children.take(fontData)) { + if (unsigned customFontCount = node->m_customFontCount) { for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) curr->m_customFontCount -= customFontCount; } @@ -398,9 +384,9 @@ void GlyphPageTreeNode::pruneFontData(const SimpleFontData* fontData, unsigned l if (level > fontData->maxGlyphPageTreeLevel()) return; - HashMap<const FontData*, GlyphPageTreeNode*>::iterator end = m_children.end(); - for (HashMap<const FontData*, GlyphPageTreeNode*>::iterator it = m_children.begin(); it != end; ++it) - it->second->pruneFontData(fontData, level); + GlyphPageTreeNodeMap::iterator end = m_children.end(); + for (GlyphPageTreeNodeMap::iterator it = m_children.begin(); it != end; ++it) + it->value->pruneFontData(fontData, level); } #ifndef NDEBUG @@ -410,10 +396,10 @@ void GlyphPageTreeNode::pruneFontData(const SimpleFontData* fontData, unsigned l indent.fill('\t', level()); indent.append(0); - HashMap<const FontData*, GlyphPageTreeNode*>::iterator end = m_children.end(); - for (HashMap<const FontData*, GlyphPageTreeNode*>::iterator it = m_children.begin(); it != end; ++it) { - printf("%s\t%p %s\n", indent.data(), it->first, it->first->description().utf8().data()); - it->second->showSubtree(); + GlyphPageTreeNodeMap::iterator end = m_children.end(); + for (GlyphPageTreeNodeMap::iterator it = m_children.begin(); it != end; ++it) { + printf("%s\t%p %s\n", indent.data(), it->key, it->key->description().utf8().data()); + it->value->showSubtree(); } if (m_systemFallbackChild) { printf("%s\t* fallback\n", indent.data()); @@ -431,8 +417,8 @@ void showGlyphPageTrees() showGlyphPageTree(0); HashMap<int, WebCore::GlyphPageTreeNode*>::iterator end = WebCore::GlyphPageTreeNode::roots->end(); for (HashMap<int, WebCore::GlyphPageTreeNode*>::iterator it = WebCore::GlyphPageTreeNode::roots->begin(); it != end; ++it) { - printf("\nPage %d:\n", it->first); - showGlyphPageTree(it->first); + printf("\nPage %d:\n", it->key); + showGlyphPageTree(it->key); } } diff --git a/Source/WebCore/platform/graphics/GlyphPageTreeNode.h b/Source/WebCore/platform/graphics/GlyphPageTreeNode.h index f8a9eea84..5b50a01fc 100644 --- a/Source/WebCore/platform/graphics/GlyphPageTreeNode.h +++ b/Source/WebCore/platform/graphics/GlyphPageTreeNode.h @@ -32,6 +32,7 @@ #include "GlyphPage.h" #include <string.h> #include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/unicode/Unicode.h> @@ -69,23 +70,6 @@ class SimpleFontData; class GlyphPageTreeNode { WTF_MAKE_FAST_ALLOCATED; public: - GlyphPageTreeNode() - : m_parent(0) - , m_level(0) - , m_isSystemFallback(false) - , m_customFontCount(0) - , m_systemFallbackChild(0) -#ifndef NDEBUG - , m_pageNumber(0) -#endif - { - } - - ~GlyphPageTreeNode(); - - static HashMap<int, GlyphPageTreeNode*>* roots; - static GlyphPageTreeNode* pageZeroRoot; - static GlyphPageTreeNode* getRootChild(const FontData* fontData, unsigned pageNumber) { return getRoot(pageNumber)->getChild(fontData, pageNumber); @@ -113,6 +97,17 @@ public: size_t pageCount() const; private: + GlyphPageTreeNode() + : m_parent(0) + , m_level(0) + , m_isSystemFallback(false) + , m_customFontCount(0) +#ifndef NDEBUG + , m_pageNumber(0) +#endif + { + } + static GlyphPageTreeNode* getRoot(unsigned pageNumber); void initializePage(const FontData*, unsigned pageNumber); @@ -120,17 +115,23 @@ private: void showSubtree(); #endif + static HashMap<int, GlyphPageTreeNode*>* roots; + static GlyphPageTreeNode* pageZeroRoot; + + typedef HashMap<const FontData*, OwnPtr<GlyphPageTreeNode> > GlyphPageTreeNodeMap; + + GlyphPageTreeNodeMap m_children; GlyphPageTreeNode* m_parent; RefPtr<GlyphPage> m_page; unsigned m_level : 31; bool m_isSystemFallback : 1; unsigned m_customFontCount; - HashMap<const FontData*, GlyphPageTreeNode*> m_children; - GlyphPageTreeNode* m_systemFallbackChild; + OwnPtr<GlyphPageTreeNode> m_systemFallbackChild; #ifndef NDEBUG unsigned m_pageNumber; + friend void ::showGlyphPageTrees(); friend void ::showGlyphPageTree(unsigned pageNumber); #endif }; diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h index 16947fb32..d4a8c1f69 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.h +++ b/Source/WebCore/platform/graphics/GraphicsContext.h @@ -499,7 +499,7 @@ namespace WebCore { #endif #if PLATFORM(QT) - void pushTransparencyLayerInternal(const QRect&, qreal, QImage&); + void pushTransparencyLayerInternal(const QRect&, qreal, QPixmap&); void takeOwnershipOfPlatformContext(); #endif diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h index 42076ff78..99a21a2d4 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext3D.h +++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h @@ -27,8 +27,8 @@ #define GraphicsContext3D_h #include "IntRect.h" -#include "GraphicsLayer.h" #include "GraphicsTypes3D.h" +#include "PlatformLayer.h" #include <wtf/HashMap.h> #include <wtf/ListHashSet.h> #include <wtf/Noncopyable.h> @@ -395,6 +395,7 @@ public: STENCIL_INDEX8 = 0x8D48, DEPTH_STENCIL = 0x84F9, UNSIGNED_INT_24_8 = 0x84FA, + DEPTH24_STENCIL8 = 0x88F0, RENDERBUFFER_WIDTH = 0x8D42, RENDERBUFFER_HEIGHT = 0x8D43, RENDERBUFFER_INTERNAL_FORMAT = 0x8D44, @@ -964,21 +965,65 @@ public: #endif #if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL) || PLATFORM(BLACKBERRY) + struct SymbolInfo { + SymbolInfo() + : type(0) + , size(0) + { + } + + SymbolInfo(GC3Denum type, int size, const String& mappedName) + : type(type) + , size(size) + , mappedName(mappedName) + { + } + + bool operator==(SymbolInfo& other) const + { + return type == other.type && size == other.size && mappedName == other.mappedName; + } + + GC3Denum type; + int size; + String mappedName; + }; + + typedef HashMap<String, SymbolInfo> ShaderSymbolMap; + struct ShaderSourceEntry { + GC3Denum type; String source; + String translatedSource; String log; bool isValid; + ShaderSymbolMap attributeMap; + ShaderSymbolMap uniformMap; ShaderSourceEntry() - : isValid(0) + : type(VERTEX_SHADER) + , isValid(false) { } + + ShaderSymbolMap& symbolMap(ANGLEShaderSymbolType symbolType) + { + ASSERT(symbolType == SHADER_SYMBOL_TYPE_ATTRIBUTE || symbolType == SHADER_SYMBOL_TYPE_UNIFORM); + if (symbolType == SHADER_SYMBOL_TYPE_ATTRIBUTE) + return attributeMap; + return uniformMap; + } }; - HashMap<Platform3DObject, ShaderSourceEntry> m_shaderSourceMap; + + typedef HashMap<Platform3DObject, ShaderSourceEntry> ShaderSourceMap; + ShaderSourceMap m_shaderSourceMap; + + String mappedSymbolName(Platform3DObject program, ANGLEShaderSymbolType, const String& name); + String originalSymbolName(Platform3DObject program, ANGLEShaderSymbolType, const String& name); ANGLEWebKitBridge m_compiler; #endif -#if PLATFORM(BLACKBERRY) || (PLATFORM(QT) && defined(QT_OPENGL_ES_2)) +#if PLATFORM(BLACKBERRY) || (PLATFORM(QT) && defined(QT_OPENGL_ES_2)) || (PLATFORM(GTK) && USE(OPENGL_ES_2)) friend class Extensions3DOpenGLES; OwnPtr<Extensions3DOpenGLES> m_extensions; #elif !PLATFORM(CHROMIUM) @@ -1027,7 +1072,6 @@ public: friend class GraphicsContext3DPrivate; OwnPtr<GraphicsContext3DPrivate> m_private; #endif - bool systemAllowsMultisamplingOnATICards() const; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.cpp b/Source/WebCore/platform/graphics/GraphicsLayer.cpp index 2ae3fe787..3a32b5145 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayer.cpp +++ b/Source/WebCore/platform/graphics/GraphicsLayer.cpp @@ -80,7 +80,6 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client) , m_acceleratesDrawing(false) , m_maintainsPixelAlignment(false) , m_appliesPageScale(false) - , m_usingTileCache(false) , m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip) , m_contentsOrientation(CompositingCoordinatesTopDown) , m_parent(0) @@ -339,21 +338,39 @@ void GraphicsLayer::resumeAnimations() { } -void GraphicsLayer::updateDebugIndicators() +void GraphicsLayer::getDebugBorderInfo(Color& color, float& width) const { - if (GraphicsLayer::showDebugBorders()) { - if (drawsContent()) { - if (m_usingTileCache) // tile cache layer: dark blue - setDebugBorder(Color(0, 0, 128, 128), 0.5); - else if (m_usingTiledLayer) - setDebugBorder(Color(255, 128, 0, 128), 2); // tiled layer: orange - else - setDebugBorder(Color(0, 128, 32, 128), 2); // normal layer: green - } else if (masksToBounds()) { - setDebugBorder(Color(128, 255, 255, 48), 20); // masking layer: pale blue - } else - setDebugBorder(Color(255, 255, 0, 192), 2); // container: yellow + if (drawsContent()) { + if (m_usingTiledLayer) { + color = Color(255, 128, 0, 128); // tiled layer: orange + width = 2; + return; + } + + color = Color(0, 128, 32, 128); // normal layer: green + width = 2; + return; + } + + if (masksToBounds()) { + color = Color(128, 255, 255, 48); // masking layer: pale blue + width = 20; + return; } + + color = Color(255, 255, 0, 192); // container: yellow + width = 2; +} + +void GraphicsLayer::updateDebugIndicators() +{ + if (!GraphicsLayer::showDebugBorders()) + return; + + Color borderColor; + float width = 0; + getDebugBorderInfo(borderColor, width); + setDebugBorder(borderColor, width); } void GraphicsLayer::setZPosition(float position) @@ -387,9 +404,9 @@ void GraphicsLayer::distributeOpacity(float accumulatedOpacity) } #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL) -GraphicsLayer::GraphicsLayerFactory* GraphicsLayer::s_graphicsLayerFactory = 0; +GraphicsLayer::GraphicsLayerFactoryCallback* GraphicsLayer::s_graphicsLayerFactory = 0; -void GraphicsLayer::setGraphicsLayerFactory(GraphicsLayer::GraphicsLayerFactory factory) +void GraphicsLayer::setGraphicsLayerFactory(GraphicsLayer::GraphicsLayerFactoryCallback factory) { s_graphicsLayerFactory = factory; } @@ -519,7 +536,7 @@ double GraphicsLayer::backingStoreMemoryEstimate() const return static_cast<double>(4 * size().width()) * size().height(); } -static void writeIndent(TextStream& ts, int indent) +void GraphicsLayer::writeIndent(TextStream& ts, int indent) { for (int i = 0; i != indent; ++i) ts << " "; @@ -645,6 +662,8 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeAsTextBe ts << ")\n"; } + dumpAdditionalProperties(ts, indent, behavior); + if (m_children.size()) { writeIndent(ts, indent + 1); ts << "(children " << m_children.size() << "\n"; @@ -673,7 +692,7 @@ void showGraphicsLayerTree(const WebCore::GraphicsLayer* layer) if (!layer) return; - WTF::String output = layer->layerTreeAsText(LayerTreeAsTextDebug); + String output = layer->layerTreeAsText(LayerTreeAsTextDebug | LayerTreeAsTextIncludeVisibleRects); fprintf(stderr, "%s\n", output.utf8().data()); } #endif diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.h b/Source/WebCore/platform/graphics/GraphicsLayer.h index 37ea8d052..e67a17eae 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayer.h +++ b/Source/WebCore/platform/graphics/GraphicsLayer.h @@ -47,6 +47,7 @@ enum LayerTreeAsTextBehaviorFlags { LayerTreeAsTextBehaviorNormal = 0, LayerTreeAsTextDebug = 1 << 0, // Dump extra debugging info like layer addresses. + LayerTreeAsTextIncludeVisibleRects = 1 << 1, }; typedef unsigned LayerTreeAsTextBehavior; @@ -54,6 +55,7 @@ namespace WebCore { class FloatPoint3D; class GraphicsContext; +class GraphicsLayerFactory; class Image; class TextStream; class TiledBacking; @@ -191,6 +193,9 @@ protected: class GraphicsLayer { WTF_MAKE_NONCOPYABLE(GraphicsLayer); WTF_MAKE_FAST_ALLOCATED; public: + static PassOwnPtr<GraphicsLayer> create(GraphicsLayerFactory*, GraphicsLayerClient*); + + // FIXME: Replace all uses of this create function with the one that takes a GraphicsLayerFactory. static PassOwnPtr<GraphicsLayer> create(GraphicsLayerClient*); virtual ~GraphicsLayer(); @@ -241,6 +246,9 @@ public: // The position of the layer (the location of its top-left corner in its parent) const FloatPoint& position() const { return m_position; } virtual void setPosition(const FloatPoint& p) { m_position = p; } + + // For platforms that move underlying platform layers on a different thread for scrolling; just update the GraphicsLayer state. + virtual void syncPosition(const FloatPoint& p) { m_position = p; } // Anchor point: (0, 0) is top left, (1, 1) is bottom right. The anchor point // affects the origin of the transforms. @@ -381,8 +389,8 @@ public: // Some compositing systems may do internal batching to synchronize compositing updates // with updates drawn into the window. These methods flush internal batched state on this layer // and descendant layers, and this layer only. - virtual void syncCompositingState(const FloatRect& /* clipRect */) { } - virtual void syncCompositingStateForThisLayerOnly() { } + virtual void flushCompositingState(const FloatRect& /* clipRect */) { } + virtual void flushCompositingStateForThisLayerOnly() { } // Return a string with a human readable form of the layer tree, If debug is true // pointers for the layers and timing data will be included in the returned string. @@ -398,8 +406,8 @@ public: #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL) // This allows several alternative GraphicsLayer implementations in the same port, // e.g. if a different GraphicsLayer implementation is needed in WebKit1 vs. WebKit2. - typedef PassOwnPtr<GraphicsLayer> GraphicsLayerFactory(GraphicsLayerClient*); - static void setGraphicsLayerFactory(GraphicsLayerFactory); + typedef PassOwnPtr<GraphicsLayer> GraphicsLayerFactoryCallback(GraphicsLayerClient*); + static void setGraphicsLayerFactory(GraphicsLayerFactoryCallback); #endif protected: @@ -431,7 +439,12 @@ protected: GraphicsLayer(GraphicsLayerClient*); + static void writeIndent(TextStream&, int indent); + void dumpProperties(TextStream&, int indent, LayerTreeAsTextBehavior) const; + virtual void dumpAdditionalProperties(TextStream&, int /*indent*/, LayerTreeAsTextBehavior) const { } + + virtual void getDebugBorderInfo(Color&, float& width) const; GraphicsLayerClient* m_client; String m_name; @@ -467,7 +480,6 @@ protected: bool m_acceleratesDrawing : 1; bool m_maintainsPixelAlignment : 1; bool m_appliesPageScale : 1; // Set for the layer which has the page scale applied to it. - bool m_usingTileCache : 1; GraphicsLayerPaintingPhase m_paintingPhase; CompositingCoordinatesOrientation m_contentsOrientation; // affects orientation of layer contents @@ -487,7 +499,7 @@ protected: int m_repaintCount; #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL) - static GraphicsLayer::GraphicsLayerFactory* s_graphicsLayerFactory; + static GraphicsLayer::GraphicsLayerFactoryCallback* s_graphicsLayerFactory; #endif }; diff --git a/Source/WebCore/platform/graphics/GraphicsLayerClient.h b/Source/WebCore/platform/graphics/GraphicsLayerClient.h index 10b116d9d..7efee0e65 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayerClient.h +++ b/Source/WebCore/platform/graphics/GraphicsLayerClient.h @@ -58,14 +58,13 @@ public: virtual ~GraphicsLayerClient() {} virtual bool shouldUseTileCache(const GraphicsLayer*) const { return false; } - virtual bool usingTileCache(const GraphicsLayer*) const { return false; } // Callback for when hardware-accelerated animation started. virtual void notifyAnimationStarted(const GraphicsLayer*, double time) = 0; - // Notification that a layer property changed that requires a subsequent call to syncCompositingState() + // Notification that a layer property changed that requires a subsequent call to flushCompositingState() // to appear on the screen. - virtual void notifySyncRequired(const GraphicsLayer*) = 0; + virtual void notifyFlushRequired(const GraphicsLayer*) = 0; virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip) = 0; virtual void didCommitChangesForLayer(const GraphicsLayer*) const { } diff --git a/Source/WebCore/platform/graphics/GraphicsLayerFactory.h b/Source/WebCore/platform/graphics/GraphicsLayerFactory.h new file mode 100644 index 000000000..c747bb8a6 --- /dev/null +++ b/Source/WebCore/platform/graphics/GraphicsLayerFactory.h @@ -0,0 +1,49 @@ +/* + * 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 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 GraphicsLayerFactory_h +#define GraphicsLayerFactory_h + +#if USE(ACCELERATED_COMPOSITING) + +#include <wtf/Forward.h> + +namespace WebCore { + +class GraphicsLayer; +class GraphicsLayerClient; + +class GraphicsLayerFactory { +public: + virtual ~GraphicsLayerFactory() { } + + virtual PassOwnPtr<GraphicsLayer> createGraphicsLayer(GraphicsLayerClient*) = 0; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // GraphicsLayerFactory_h diff --git a/Source/WebCore/platform/graphics/Image.h b/Source/WebCore/platform/graphics/Image.h index feb6e2bc3..5e700c132 100644 --- a/Source/WebCore/platform/graphics/Image.h +++ b/Source/WebCore/platform/graphics/Image.h @@ -53,6 +53,10 @@ typedef SIZE* LPSIZE; typedef struct HBITMAP__ *HBITMAP; #endif +#if PLATFORM(QT) +#include <QPixmap> +#endif + #if PLATFORM(GTK) typedef struct _GdkPixbuf GdkPixbuf; #endif @@ -154,7 +158,7 @@ public: #endif #if PLATFORM(QT) - static void setPlatformResource(const char* name, const QImage&); + static void setPlatformResource(const char* name, const QPixmap&); #endif virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, diff --git a/Source/WebCore/platform/graphics/ImageBuffer.cpp b/Source/WebCore/platform/graphics/ImageBuffer.cpp index 46f2d14cd..138d078cf 100644 --- a/Source/WebCore/platform/graphics/ImageBuffer.cpp +++ b/Source/WebCore/platform/graphics/ImageBuffer.cpp @@ -28,6 +28,7 @@ #include "ImageBuffer.h" #include "IntRect.h" +#include "PlatformMemoryInstrumentation.h" #include <wtf/MathExtras.h> namespace WebCore { @@ -112,4 +113,11 @@ bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D&, Platform3DObject, GC } #endif +void ImageBuffer::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Image); + info.addMember(m_data); + info.addMember(m_context); +} + } diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h index 06ac56757..fe0aee0f6 100644 --- a/Source/WebCore/platform/graphics/ImageBuffer.h +++ b/Source/WebCore/platform/graphics/ImageBuffer.h @@ -121,6 +121,8 @@ namespace WebCore { bool copyToPlatformTexture(GraphicsContext3D&, Platform3DObject, GC3Denum, bool, bool); + void reportMemoryUsage(MemoryObjectInfo*) const; + private: #if USE(CG) NativeImagePtr copyNativeImage(BackingStoreCopy = CopyBackingStore) const; diff --git a/Source/WebCore/platform/graphics/IntPoint.h b/Source/WebCore/platform/graphics/IntPoint.h index 0af6e8570..0dd1daab1 100644 --- a/Source/WebCore/platform/graphics/IntPoint.h +++ b/Source/WebCore/platform/graphics/IntPoint.h @@ -29,10 +29,6 @@ #include "IntSize.h" #include <wtf/MathExtras.h> -#if PLATFORM(QT) -#include <QDataStream> -#endif - #if USE(CG) || USE(SKIA_ON_MAC_CHROMIUM) typedef struct CGPoint CGPoint; #endif @@ -229,23 +225,6 @@ inline int IntPoint::distanceSquaredToPoint(const IntPoint& point) const return ((*this) - point).diagonalLengthSquared(); } -#if PLATFORM(QT) -inline QDataStream& operator<<(QDataStream& stream, const IntPoint& point) -{ - stream << point.x() << point.y(); - return stream; -} - -inline QDataStream& operator>>(QDataStream& stream, IntPoint& point) -{ - int x, y; - stream >> x >> y; - point.setX(x); - point.setY(y); - return stream; -} -#endif - } // namespace WebCore #endif // IntPoint_h diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp index 47834d5ab..377e8dc7a 100644 --- a/Source/WebCore/platform/graphics/MediaPlayer.cpp +++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp @@ -360,7 +360,7 @@ bool MediaPlayer::load(const KURL& url, const ContentType& contentType, const St // If the MIME type is missing or is not meaningful, try to figure it out from the URL. if (m_contentMIMEType.isEmpty() || m_contentMIMEType == applicationOctetStream() || m_contentMIMEType == textPlain()) { - if (protocolIs(m_url.string(), "data")) + if (m_url.protocolIsData()) m_contentMIMEType = mimeTypeFromDataURL(m_url.string()); else { String lastPathComponent = url.lastPathComponent(); @@ -1078,10 +1078,11 @@ void MediaPlayer::keyMessage(const String& keySystem, const String& sessionId, c m_mediaPlayerClient->mediaPlayerKeyMessage(this, keySystem, sessionId, message, messageLength); } -void MediaPlayer::keyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength) +bool MediaPlayer::keyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength) { if (m_mediaPlayerClient) - m_mediaPlayerClient->mediaPlayerKeyNeeded(this, keySystem, sessionId, initData, initDataLength); + return m_mediaPlayerClient->mediaPlayerKeyNeeded(this, keySystem, sessionId, initData, initDataLength); + return false; } #endif diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h index 60876e638..be93e8701 100644 --- a/Source/WebCore/platform/graphics/MediaPlayer.h +++ b/Source/WebCore/platform/graphics/MediaPlayer.h @@ -44,7 +44,7 @@ #include <wtf/text/StringHash.h> #if USE(ACCELERATED_COMPOSITING) -#include "GraphicsLayer.h" +#include "PlatformLayer.h" #endif OBJC_CLASS AVPlayer; @@ -184,10 +184,10 @@ public: #if ENABLE(ENCRYPTED_MEDIA) enum MediaKeyErrorCode { UnknownError = 1, ClientError, ServiceError, OutputError, HardwareChangeError, DomainError }; - virtual void mediaPlayerKeyAdded(MediaPlayer*, const String& keySystem, const String& sessionId) { } - virtual void mediaPlayerKeyError(MediaPlayer*, const String& keySystem, const String& sessionId, MediaKeyErrorCode errorCode, unsigned short systemCode) { } - virtual void mediaPlayerKeyMessage(MediaPlayer*, const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength) { } - virtual void mediaPlayerKeyNeeded(MediaPlayer*, const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength) { } + virtual void mediaPlayerKeyAdded(MediaPlayer*, const String&, const String&) { } + virtual void mediaPlayerKeyError(MediaPlayer*, const String&, const String&, MediaKeyErrorCode, unsigned short) { } + virtual void mediaPlayerKeyMessage(MediaPlayer*, const String&, const String&, const unsigned char*, unsigned) { } + virtual bool mediaPlayerKeyNeeded(MediaPlayer*, const String&, const String&, const unsigned char*, unsigned) { return false; } #endif virtual String mediaPlayerReferrer() const { return String(); } @@ -412,7 +412,7 @@ public: void keyAdded(const String& keySystem, const String& sessionId); void keyError(const String& keySystem, const String& sessionId, MediaPlayerClient::MediaKeyErrorCode, unsigned short systemCode); void keyMessage(const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength); - void keyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength); + bool keyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength); #endif String referrer() const; diff --git a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h index 87851e44c..c81642f27 100644 --- a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h +++ b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h @@ -179,9 +179,9 @@ public: #endif #if ENABLE(ENCRYPTED_MEDIA) - virtual MediaPlayer::MediaKeyException addKey(const String& keySystem, const unsigned char* key, unsigned keyLength, const unsigned char* initData, unsigned initDataLength, const String& sessionId) { return MediaPlayer::KeySystemNotSupported; } - virtual MediaPlayer::MediaKeyException generateKeyRequest(const String& keySystem, const unsigned char* initData, unsigned initDataLength) { return MediaPlayer::KeySystemNotSupported; } - virtual MediaPlayer::MediaKeyException cancelKeyRequest(const String& keySystem, const String& sessionId) { return MediaPlayer::KeySystemNotSupported; } + virtual MediaPlayer::MediaKeyException addKey(const String&, const unsigned char*, unsigned, const unsigned char*, unsigned, const String&) { return MediaPlayer::KeySystemNotSupported; } + virtual MediaPlayer::MediaKeyException generateKeyRequest(const String&, const unsigned char*, unsigned) { return MediaPlayer::KeySystemNotSupported; } + virtual MediaPlayer::MediaKeyException cancelKeyRequest(const String&, const String&) { return MediaPlayer::KeySystemNotSupported; } #endif }; diff --git a/Source/WebCore/platform/graphics/NativeImagePtr.h b/Source/WebCore/platform/graphics/NativeImagePtr.h index 1fc3fa6c9..c98f8c25a 100644 --- a/Source/WebCore/platform/graphics/NativeImagePtr.h +++ b/Source/WebCore/platform/graphics/NativeImagePtr.h @@ -36,7 +36,7 @@ typedef struct CGImage* CGImageRef; #elif PLATFORM(QT) #include <qglobal.h> QT_BEGIN_NAMESPACE -class QImage; +class QPixmap; QT_END_NAMESPACE #elif USE(CAIRO) #include "NativeImageCairo.h" @@ -48,12 +48,16 @@ class NativeImageSkia; #include "SharedBitmap.h" #endif +namespace WTF { +class MemoryObjectInfo; +} + namespace WebCore { #if USE(CG) typedef CGImageRef NativeImagePtr; #elif PLATFORM(QT) -typedef QImage* NativeImagePtr; +typedef QPixmap* NativeImagePtr; #elif PLATFORM(OPENVG) class TiledImageOpenVG; typedef TiledImageOpenVG* NativeImagePtr; @@ -67,6 +71,7 @@ typedef wxBitmap* NativeImagePtr; typedef WebCore::NativeImageCairo* NativeImagePtr; #elif USE(SKIA) typedef WebCore::NativeImageSkia* NativeImagePtr; +void reportMemoryUsage(const NativeImageSkia* const&, WTF::MemoryObjectInfo*); #elif OS(WINCE) typedef RefPtr<SharedBitmap> NativeImagePtr; #elif PLATFORM(BLACKBERRY) diff --git a/Source/WebCore/platform/graphics/OpenGLESShims.h b/Source/WebCore/platform/graphics/OpenGLESShims.h index 40187004a..bcaf855ea 100644 --- a/Source/WebCore/platform/graphics/OpenGLESShims.h +++ b/Source/WebCore/platform/graphics/OpenGLESShims.h @@ -26,7 +26,7 @@ #ifndef OpenGLESShims_h #define OpenGLESShims_h -#if PLATFORM(BLACKBERRY) || PLATFORM(QT) +#if PLATFORM(BLACKBERRY) || PLATFORM(QT) || PLATFORM(GTK) #define glBindFramebufferEXT glBindFramebuffer #define glFramebufferTexture2DEXT glFramebufferTexture2D #define glBindRenderbufferEXT glBindRenderbuffer diff --git a/Source/WebCore/platform/graphics/Path.cpp b/Source/WebCore/platform/graphics/Path.cpp index 97960f4b6..f2570ffb5 100644 --- a/Source/WebCore/platform/graphics/Path.cpp +++ b/Source/WebCore/platform/graphics/Path.cpp @@ -184,7 +184,7 @@ void Path::addBeziersForRoundedRect(const FloatRect& rect, const FloatSize& topL closeSubpath(); } -#if !USE(CG) +#if !USE(CG) && !PLATFORM(QT) FloatRect Path::fastBoundingRect() const { return boundingRect(); diff --git a/Source/WebCore/platform/graphics/SegmentedFontData.cpp b/Source/WebCore/platform/graphics/SegmentedFontData.cpp index fd9094baa..efb20a8c1 100644 --- a/Source/WebCore/platform/graphics/SegmentedFontData.cpp +++ b/Source/WebCore/platform/graphics/SegmentedFontData.cpp @@ -34,6 +34,7 @@ namespace WebCore { SegmentedFontData::~SegmentedFontData() { + GlyphPageTreeNode::pruneTreeCustomFontData(this); } const SimpleFontData* SegmentedFontData::fontDataForCharacter(UChar32 c) const @@ -41,9 +42,9 @@ const SimpleFontData* SegmentedFontData::fontDataForCharacter(UChar32 c) const Vector<FontDataRange>::const_iterator end = m_ranges.end(); for (Vector<FontDataRange>::const_iterator it = m_ranges.begin(); it != end; ++it) { if (it->from() <= c && it->to() >= c) - return it->fontData(); + return it->fontData().get(); } - return m_ranges[0].fontData(); + return m_ranges[0].fontData().get(); } bool SegmentedFontData::containsCharacter(UChar32 c) const diff --git a/Source/WebCore/platform/graphics/SegmentedFontData.h b/Source/WebCore/platform/graphics/SegmentedFontData.h index 645dc0d5f..45d7d158c 100644 --- a/Source/WebCore/platform/graphics/SegmentedFontData.h +++ b/Source/WebCore/platform/graphics/SegmentedFontData.h @@ -34,7 +34,7 @@ namespace WebCore { class SimpleFontData; struct FontDataRange { - FontDataRange(UChar32 from, UChar32 to, const SimpleFontData* fontData) + FontDataRange(UChar32 from, UChar32 to, PassRefPtr<SimpleFontData> fontData) : m_from(from) , m_to(to) , m_fontData(fontData) @@ -43,16 +43,18 @@ struct FontDataRange { UChar32 from() const { return m_from; } UChar32 to() const { return m_to; } - const SimpleFontData* fontData() const { return m_fontData; } + PassRefPtr<SimpleFontData> fontData() const { return m_fontData; } private: UChar32 m_from; UChar32 m_to; - const SimpleFontData* m_fontData; + RefPtr<SimpleFontData> m_fontData; }; class SegmentedFontData : public FontData { public: + static PassRefPtr<SegmentedFontData> create() { return adoptRef(new SegmentedFontData); } + virtual ~SegmentedFontData(); void appendRange(const FontDataRange& range) { m_ranges.append(range); } @@ -64,6 +66,8 @@ public: #endif private: + SegmentedFontData() { } + virtual const SimpleFontData* fontDataForCharacter(UChar32) const; virtual bool containsCharacters(const UChar*, int length) const; diff --git a/Source/WebCore/platform/graphics/SimpleFontData.cpp b/Source/WebCore/platform/graphics/SimpleFontData.cpp index eae95bdcb..28fa5ab15 100644 --- a/Source/WebCore/platform/graphics/SimpleFontData.cpp +++ b/Source/WebCore/platform/graphics/SimpleFontData.cpp @@ -150,7 +150,9 @@ SimpleFontData::~SimpleFontData() #endif platformDestroy(); - if (!isCustomFont()) + if (isCustomFont()) + GlyphPageTreeNode::pruneTreeCustomFontData(this); + else GlyphPageTreeNode::pruneTreeFontData(this); } @@ -170,36 +172,36 @@ bool SimpleFontData::isSegmented() const return false; } -SimpleFontData* SimpleFontData::verticalRightOrientationFontData() const +PassRefPtr<SimpleFontData> SimpleFontData::verticalRightOrientationFontData() const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->verticalRightOrientation) { FontPlatformData verticalRightPlatformData(m_platformData); verticalRightPlatformData.setOrientation(Horizontal); - m_derivedFontData->verticalRightOrientation = adoptPtr(new SimpleFontData(verticalRightPlatformData, isCustomFont(), false, true)); + m_derivedFontData->verticalRightOrientation = create(verticalRightPlatformData, isCustomFont(), false, true); } - return m_derivedFontData->verticalRightOrientation.get(); + return m_derivedFontData->verticalRightOrientation; } -SimpleFontData* SimpleFontData::uprightOrientationFontData() const +PassRefPtr<SimpleFontData> SimpleFontData::uprightOrientationFontData() const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->uprightOrientation) - m_derivedFontData->uprightOrientation = adoptPtr(new SimpleFontData(m_platformData, isCustomFont(), false, true)); - return m_derivedFontData->uprightOrientation.get(); + m_derivedFontData->uprightOrientation = create(m_platformData, isCustomFont(), false, true); + return m_derivedFontData->uprightOrientation; } -SimpleFontData* SimpleFontData::brokenIdeographFontData() const +PassRefPtr<SimpleFontData> SimpleFontData::brokenIdeographFontData() const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->brokenIdeograph) { - m_derivedFontData->brokenIdeograph = adoptPtr(new SimpleFontData(m_platformData, isCustomFont(), false)); + m_derivedFontData->brokenIdeograph = create(m_platformData, isCustomFont(), false); m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFallback = true; } - return m_derivedFontData->brokenIdeograph.get(); + return m_derivedFontData->brokenIdeograph; } #ifndef NDEBUG diff --git a/Source/WebCore/platform/graphics/SimpleFontData.h b/Source/WebCore/platform/graphics/SimpleFontData.h index 66208837c..db28040fc 100644 --- a/Source/WebCore/platform/graphics/SimpleFontData.h +++ b/Source/WebCore/platform/graphics/SimpleFontData.h @@ -29,6 +29,7 @@ #include "FontMetrics.h" #include "FontPlatformData.h" #include "FloatRect.h" +#include "GlyphBuffer.h" #include "GlyphMetricsMap.h" #include "GlyphPageTreeNode.h" #if ENABLE(OPENTYPE_VERTICAL) @@ -37,8 +38,13 @@ #include "TypesettingFeatures.h" #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> +#include <wtf/UnusedParam.h> #include <wtf/text/StringHash.h> +#if PLATFORM(MAC) +#include "WebCoreSystemInterface.h" +#endif + #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) || (PLATFORM(WX) && OS(DARWIN)) #include <wtf/RetainPtr.h> #endif @@ -79,10 +85,16 @@ public: }; // Used to create platform fonts. - SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false); + static PassRefPtr<SimpleFontData> create(const FontPlatformData& platformData, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false) + { + return adoptRef(new SimpleFontData(platformData, isCustomFont, isLoading, isTextOrientationFallback)); + } // Used to create SVG Fonts. - SimpleFontData(PassOwnPtr<AdditionalFontData>, float fontSize, bool syntheticBold, bool syntheticItalic); + static PassRefPtr<SimpleFontData> create(PassOwnPtr<AdditionalFontData> fontData, float fontSize, bool syntheticBold, bool syntheticItalic) + { + return adoptRef(new SimpleFontData(fontData, fontSize, syntheticBold, syntheticItalic)); + } virtual ~SimpleFontData(); @@ -91,11 +103,11 @@ public: const OpenTypeVerticalData* verticalData() const { return m_verticalData; } #endif - SimpleFontData* smallCapsFontData(const FontDescription&) const; - SimpleFontData* emphasisMarkFontData(const FontDescription&) const; - SimpleFontData* brokenIdeographFontData() const; + PassRefPtr<SimpleFontData> smallCapsFontData(const FontDescription&) const; + PassRefPtr<SimpleFontData> emphasisMarkFontData(const FontDescription&) const; + PassRefPtr<SimpleFontData> brokenIdeographFontData() const; - SimpleFontData* variantFontData(const FontDescription& description, FontDataVariant variant) const + PassRefPtr<SimpleFontData> variantFontData(const FontDescription& description, FontDataVariant variant) const { switch (variant) { case SmallCapsVariant: @@ -112,8 +124,8 @@ public: return const_cast<SimpleFontData*>(this); } - SimpleFontData* verticalRightOrientationFontData() const; - SimpleFontData* uprightOrientationFontData() const; + PassRefPtr<SimpleFontData> verticalRightOrientationFontData() const; + PassRefPtr<SimpleFontData> uprightOrientationFontData() const; bool hasVerticalGlyphs() const { return m_hasVerticalGlyphs; } bool isTextOrientationFallback() const { return m_isTextOrientationFallback; } @@ -178,9 +190,27 @@ public: #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) || (PLATFORM(WX) && OS(DARWIN)) CFDictionaryRef getCFStringAttributes(TypesettingFeatures, FontOrientation) const; +#endif + +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) || (PLATFORM(WX) && OS(DARWIN)) || USE(HARFBUZZ_NG) bool canRenderCombiningCharacterSequence(const UChar*, size_t) const; #endif + bool applyTransforms(GlyphBufferGlyph* glyphs, GlyphBufferAdvance* advances, size_t glyphCount, TypesettingFeatures typesettingFeatures) const + { +#if !PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 + UNUSED_PARAM(glyphs); + UNUSED_PARAM(advances); + UNUSED_PARAM(glyphCount); + UNUSED_PARAM(typesettingFeatures); + ASSERT_NOT_REACHED(); + return false; +#else + wkCTFontTransformOptions options = (typesettingFeatures & Kerning ? wkCTFontTransformApplyPositioning : 0) | (typesettingFeatures & Ligatures ? wkCTFontTransformApplyShaping : 0); + return wkCTFontTransformGlyphs(m_platformData.ctFont(), glyphs, reinterpret_cast<CGSize*>(advances), glyphCount, options); +#endif + } + #if PLATFORM(QT) QRawFont getQtRawFont() const { return m_platformData.rawFont(); } #endif @@ -201,6 +231,10 @@ public: #endif private: + SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false); + + SimpleFontData(PassOwnPtr<AdditionalFontData> , float fontSize, bool syntheticBold, bool syntheticItalic); + void platformInit(); void platformGlyphInit(); void platformCharWidthInit(); @@ -210,7 +244,7 @@ private: void commonInit(); - PassOwnPtr<SimpleFontData> createScaledFontData(const FontDescription&, float scaleFactor) const; + PassRefPtr<SimpleFontData> createScaledFontData(const FontDescription&, float scaleFactor) const; #if (PLATFORM(WIN) && !OS(WINCE)) \ || (OS(WINDOWS) && PLATFORM(WX)) @@ -254,11 +288,11 @@ private: ~DerivedFontData(); bool forCustomFont; - OwnPtr<SimpleFontData> smallCaps; - OwnPtr<SimpleFontData> emphasisMark; - OwnPtr<SimpleFontData> brokenIdeograph; - OwnPtr<SimpleFontData> verticalRightOrientation; - OwnPtr<SimpleFontData> uprightOrientation; + RefPtr<SimpleFontData> smallCaps; + RefPtr<SimpleFontData> emphasisMark; + RefPtr<SimpleFontData> brokenIdeograph; + RefPtr<SimpleFontData> verticalRightOrientation; + RefPtr<SimpleFontData> uprightOrientation; #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) mutable RetainPtr<CFMutableDictionaryRef> compositeFontReferences; #endif @@ -278,6 +312,9 @@ private: #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) || (PLATFORM(WX) && OS(DARWIN)) mutable HashMap<unsigned, RetainPtr<CFDictionaryRef> > m_CFStringAttributes; +#endif + +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) || (PLATFORM(WX) && OS(DARWIN)) || USE(HARFBUZZ_NG) mutable OwnPtr<HashMap<String, bool> > m_combiningCharacterSequenceSupport; #endif diff --git a/Source/WebCore/platform/graphics/TextRun.h b/Source/WebCore/platform/graphics/TextRun.h index 8762d436e..c64f098fe 100644 --- a/Source/WebCore/platform/graphics/TextRun.h +++ b/Source/WebCore/platform/graphics/TextRun.h @@ -59,7 +59,7 @@ public: typedef unsigned RoundingHacks; -#if PLATFORM(MAC) +#if ENABLE(8BIT_TEXTRUN) TextRun(const LChar* c, unsigned len, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding) : m_charactersLength(len) , m_len(len) @@ -123,14 +123,10 @@ public: , m_disableSpacing(false) , m_tabSize(0) { -#if PLATFORM(MAC) +#if ENABLE(8BIT_TEXTRUN) if (m_charactersLength && s.is8Bit()) { - m_data.characters16 = s.characters(); - m_is8Bit = false; -// FIXME: Change this to: -// m_data.characters8 = s.characters8(); -// m_is8Bit = true; -// when other 8 bit rendering changes are landed. + m_data.characters8 = s.characters8(); + m_is8Bit = true; } else { m_data.characters16 = s.characters(); m_is8Bit = false; @@ -147,11 +143,15 @@ public: TextRun result = *this; - if (is8Bit()) +#if ENABLE(8BIT_TEXTRUN) + if (is8Bit()) { result.setText(data8(startOffset), length); - else - result.setText(data16(startOffset), length); - + return result; + } +#else + ASSERT(!is8Bit()); +#endif + result.setText(data16(startOffset), length); return result; } @@ -166,7 +166,9 @@ public: int length() const { return m_len; } int charactersLength() const { return m_charactersLength; } +#if ENABLE(8BIT_TEXTRUN) void setText(const LChar* c, unsigned len) { m_data.characters8 = c; m_len = len; m_is8Bit = true;} +#endif void setText(const UChar* c, unsigned len) { m_data.characters16 = c; m_len = len; m_is8Bit = false;} void setCharactersLength(unsigned charactersLength) { m_charactersLength = charactersLength; } diff --git a/Source/WebCore/platform/graphics/TiledBacking.h b/Source/WebCore/platform/graphics/TiledBacking.h index 70012b117..1c74f09a2 100644 --- a/Source/WebCore/platform/graphics/TiledBacking.h +++ b/Source/WebCore/platform/graphics/TiledBacking.h @@ -32,21 +32,26 @@ class IntRect; class TiledBacking { public: - TiledBacking() - : m_scrollingPerformanceLoggingEnabled(0) - { } virtual ~TiledBacking() { } virtual void visibleRectChanged(const IntRect&) = 0; virtual void setIsInWindow(bool) = 0; - virtual void setCanHaveScrollbars(bool) = 0; - virtual void forceRepaint() = 0; - void setScrollingPerformanceLoggingEnabled(bool flag) { m_scrollingPerformanceLoggingEnabled = flag; } - bool scrollingPerformanceLoggingEnabled() const { return m_scrollingPerformanceLoggingEnabled; } + enum { + CoverageForVisibleArea = 0, + CoverageForVerticalScrolling = 1 << 0, + CoverageForHorizontalScrolling = 1 << 1, + CoverageForScrolling = CoverageForVerticalScrolling | CoverageForHorizontalScrolling + }; + typedef unsigned TileCoverage; + + virtual void setTileCoverage(TileCoverage) = 0; + virtual TileCoverage tileCoverage() const = 0; + + virtual void forceRepaint() = 0; -private: - bool m_scrollingPerformanceLoggingEnabled; + virtual void setScrollingPerformanceLoggingEnabled(bool) = 0; + virtual bool scrollingPerformanceLoggingEnabled() const = 0; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/TiledBackingStore.cpp b/Source/WebCore/platform/graphics/TiledBackingStore.cpp index a19f6a616..c564dbed0 100644 --- a/Source/WebCore/platform/graphics/TiledBackingStore.cpp +++ b/Source/WebCore/platform/graphics/TiledBackingStore.cpp @@ -116,9 +116,9 @@ void TiledBackingStore::updateTileBuffers() Vector<RefPtr<Tile> > dirtyTiles; TileMap::iterator end = m_tiles.end(); for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) { - if (!it->second->isDirty()) + if (!it->value->isDirty()) continue; - dirtyTiles.append(it->second); + dirtyTiles.append(it->value); } if (dirtyTiles.isEmpty()) { @@ -255,10 +255,11 @@ void TiledBackingStore::createTiles() if (visibleRect.isEmpty()) return; - IntRect keepRect; IntRect coverRect; + IntRect keepRect; computeCoverAndKeepRect(visibleRect, coverRect, keepRect); + setCoverRect(coverRect); setKeepRect(keepRect); // Resize tiles at the edge in case the contents size has changed, but only do so @@ -401,13 +402,13 @@ bool TiledBackingStore::resizeEdgeTiles() Vector<Tile::Coordinate> tilesToRemove; TileMap::iterator end = m_tiles.end(); for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) { - Tile::Coordinate tileCoordinate = it->second->coordinate(); - IntRect tileRect = it->second->rect(); + Tile::Coordinate tileCoordinate = it->value->coordinate(); + IntRect tileRect = it->value->rect(); IntRect expectedTileRect = tileRectForCoordinate(tileCoordinate); if (expectedTileRect.isEmpty()) tilesToRemove.append(tileCoordinate); else if (expectedTileRect != tileRect) { - it->second->resize(expectedTileRect.size()); + it->value->resize(expectedTileRect.size()); wasResized = true; } } @@ -426,8 +427,8 @@ void TiledBackingStore::setKeepRect(const IntRect& keepRect) Vector<Tile::Coordinate> toRemove; TileMap::iterator end = m_tiles.end(); for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) { - Tile::Coordinate coordinate = it->second->coordinate(); - FloatRect tileRect = it->second->rect(); + Tile::Coordinate coordinate = it->value->coordinate(); + FloatRect tileRect = it->value->rect(); if (!tileRect.intersects(keepRectF)) toRemove.append(coordinate); } diff --git a/Source/WebCore/platform/graphics/TiledBackingStore.h b/Source/WebCore/platform/graphics/TiledBackingStore.h index 8d662e4c4..b3c365c35 100644 --- a/Source/WebCore/platform/graphics/TiledBackingStore.h +++ b/Source/WebCore/platform/graphics/TiledBackingStore.h @@ -72,6 +72,7 @@ public: Tile::Coordinate tileCoordinateForPoint(const IntPoint&) const; double tileDistance(const IntRect& viewport, const Tile::Coordinate&) const; + IntRect coverRect() const { return m_coverRect; } bool visibleAreaIsCovered() const; void removeAllNonVisibleTiles(); @@ -94,6 +95,7 @@ private: void commitScaleChange(); bool resizeEdgeTiles(); + void setCoverRect(const IntRect& rect) { m_coverRect = rect; } void setKeepRect(const IntRect&); PassRefPtr<Tile> tileAt(const Tile::Coordinate&) const; @@ -125,6 +127,7 @@ private: FloatPoint m_trajectoryVector; IntRect m_visibleRect; + IntRect m_coverRect; IntRect m_keepRect; IntRect m_rect; diff --git a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp index d9a9e6e42..b9a91730b 100644 --- a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp +++ b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp @@ -30,30 +30,7 @@ #if !USE(OPENTYPE_SANITIZER) #include "SharedBuffer.h" - -#if OS(UNIX) -#include <netinet/in.h> -#endif - -#if OS(WINDOWS) -#if CPU(BIG_ENDIAN) -#define ntohs(x) ((uint16_t)(x)) -#define htons(x) ((uint16_t)(x)) -#define ntohl(x) ((uint32_t)(x)) -#define htonl(x) ((uint32_t)(x)) -#elif CPU(MIDDLE_ENDIAN) -#define ntohs(x) ((unit16_t)(x)) -#define htons(x) ((uint16_t)(x)) -#define ntohl(x) ((uint32_t)((((uint32_t)(x) & 0xffff0000) >> 16) | (((uint32_t)(x) & 0xffff) << 16)) -#define htonl(x) ntohl(x) -#else -#define ntohs(x) ((uint16_t)((((uint16_t)(x) & 0xff00) >> 8) | (((uint16_t)(x) & 0x00ff) << 8))) -#define htons(x) ntohs(x) -#define ntohl(x) ((uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | (((uint32_t)(x) & 0x000000ff) << 24))) -#define htonl(x) ntohl(x) -#endif -#endif // OS(WINDOWS) +#include <wtf/ByteOrder.h> namespace WebCore { diff --git a/Source/WebCore/platform/graphics/WidthIterator.cpp b/Source/WebCore/platform/graphics/WidthIterator.cpp index f061ec470..15ca61773 100644 --- a/Source/WebCore/platform/graphics/WidthIterator.cpp +++ b/Source/WebCore/platform/graphics/WidthIterator.cpp @@ -27,7 +27,6 @@ #include "Latin1TextIterator.h" #include "SimpleFontData.h" #include "SurrogatePairAwareTextIterator.h" -#include "TextRun.h" #include <wtf/MathExtras.h> using namespace WTF; @@ -43,6 +42,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const , m_runWidthSoFar(0) , m_isAfterExpansion(!run.allowsLeadingExpansion()) , m_finalRoundingWidth(0) + , m_typesettingFeatures(font->typesettingFeatures()) , m_fallbackFonts(fallbackFonts) , m_accountForGlyphBounds(accountForGlyphBounds) , m_maxGlyphBoundingBoxY(numeric_limits<float>::min()) @@ -84,6 +84,62 @@ GlyphData WidthIterator::glyphDataForCharacter(UChar32 character, bool mirror, i return m_font->glyphDataForCharacter(character, mirror); } +struct OriginalAdvancesForCharacterTreatedAsSpace { +public: + OriginalAdvancesForCharacterTreatedAsSpace(bool isSpace, float advanceBefore, float advanceAt) + : characterIsSpace(isSpace) + , advanceBeforeCharacter(advanceBefore) + , advanceAtCharacter(advanceAt) + { + } + + bool characterIsSpace; + float advanceBeforeCharacter; + float advanceAtCharacter; +}; + +typedef Vector<pair<int, OriginalAdvancesForCharacterTreatedAsSpace>, 64> CharactersTreatedAsSpace; + +static inline float applyFontTransforms(GlyphBuffer* glyphBuffer, bool ltr, int& lastGlyphCount, const SimpleFontData* fontData, TypesettingFeatures typesettingFeatures, CharactersTreatedAsSpace& charactersTreatedAsSpace) +{ + ASSERT(typesettingFeatures & (Kerning | Ligatures)); + + if (!glyphBuffer) + return 0; + + int glyphBufferSize = glyphBuffer->size(); + if (glyphBuffer->size() <= lastGlyphCount + 1) + return 0; + + GlyphBufferAdvance* advances = glyphBuffer->advances(0); + float widthDifference = 0; + for (int i = lastGlyphCount; i < glyphBufferSize; ++i) + widthDifference -= advances[i].width(); + + if (!ltr) + glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount); + + fontData->applyTransforms(glyphBuffer->glyphs(lastGlyphCount), advances + lastGlyphCount, glyphBufferSize - lastGlyphCount, typesettingFeatures); + + if (!ltr) + glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount); + + for (size_t i = 0; i < charactersTreatedAsSpace.size(); ++i) { + int spaceOffset = charactersTreatedAsSpace[i].first; + const OriginalAdvancesForCharacterTreatedAsSpace& originalAdvances = charactersTreatedAsSpace[i].second; + if (spaceOffset && !originalAdvances.characterIsSpace) + glyphBuffer->advances(spaceOffset - 1)->setWidth(originalAdvances.advanceBeforeCharacter); + glyphBuffer->advances(spaceOffset)->setWidth(originalAdvances.advanceAtCharacter); + } + charactersTreatedAsSpace.clear(); + + for (int i = lastGlyphCount; i < glyphBufferSize; ++i) + widthDifference += advances[i].width(); + + lastGlyphCount = glyphBufferSize; + return widthDifference; +} + template <typename TextIterator> inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, GlyphBuffer* glyphBuffer) { @@ -99,10 +155,11 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph const SimpleFontData* primaryFont = m_font->primaryFont(); const SimpleFontData* lastFontData = primaryFont; + int lastGlyphCount = glyphBuffer ? glyphBuffer->size() : 0; UChar32 character = 0; unsigned clusterLength = 0; - + CharactersTreatedAsSpace charactersTreatedAsSpace; while (textIterator.consume(character, clusterLength)) { unsigned advanceLength = clusterLength; const GlyphData& glyphData = glyphDataForCharacter(character, rtl, textIterator.currentCharacter(), advanceLength); @@ -132,6 +189,9 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph } if (fontData != lastFontData && width) { + if (shouldApplyFontTransforms()) + m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, m_typesettingFeatures, charactersTreatedAsSpace); + lastFontData = fontData; if (m_fallbackFonts && fontData != primaryFont) { // FIXME: This does a little extra work that could be avoided if @@ -187,6 +247,10 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph m_isAfterExpansion = false; } + if (shouldApplyFontTransforms() && glyphBuffer && Font::treatAsSpace(character)) + charactersTreatedAsSpace.append(make_pair(glyphBuffer->size(), + OriginalAdvancesForCharacterTreatedAsSpace(character == ' ', glyphBuffer->size() ? glyphBuffer->advanceAt(glyphBuffer->size() - 1) : 0, width))); + if (m_accountForGlyphBounds) { bounds = fontData->boundsForGlyph(glyph); if (!textIterator.currentCharacter()) @@ -239,6 +303,9 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph } } + if (shouldApplyFontTransforms()) + m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, m_typesettingFeatures, charactersTreatedAsSpace); + unsigned consumedCharacters = textIterator.currentCharacter() - m_currentCharacter; m_currentCharacter = textIterator.currentCharacter(); m_runWidthSoFar += widthSinceLastRounding; @@ -265,15 +332,15 @@ unsigned WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) return advanceInternal(textIterator, glyphBuffer); } -bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer) +bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer& glyphBuffer) { - int oldSize = glyphBuffer->size(); - advance(m_currentCharacter + 1, glyphBuffer); + int oldSize = glyphBuffer.size(); + advance(m_currentCharacter + 1, &glyphBuffer); float w = 0; - for (int i = oldSize; i < glyphBuffer->size(); ++i) - w += glyphBuffer->advanceAt(i); + for (int i = oldSize; i < glyphBuffer.size(); ++i) + w += glyphBuffer.advanceAt(i); width = w; - return glyphBuffer->size() > oldSize; + return glyphBuffer.size() > oldSize; } } diff --git a/Source/WebCore/platform/graphics/WidthIterator.h b/Source/WebCore/platform/graphics/WidthIterator.h index ce475dafa..1996a0978 100644 --- a/Source/WebCore/platform/graphics/WidthIterator.h +++ b/Source/WebCore/platform/graphics/WidthIterator.h @@ -22,7 +22,9 @@ #ifndef WidthIterator_h #define WidthIterator_h +#include "Font.h" #include "SVGGlyph.h" +#include "TextRun.h" #include <wtf/HashSet.h> #include <wtf/Vector.h> #include <wtf/unicode/Unicode.h> @@ -40,8 +42,8 @@ struct WidthIterator { public: WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool accountForGlyphBounds = false, bool forTextEmphasis = false); - unsigned advance(int to, GlyphBuffer* = 0); - bool advanceOneCharacter(float& width, GlyphBuffer* = 0); + unsigned advance(int to, GlyphBuffer*); + bool advanceOneCharacter(float& width, GlyphBuffer&); float maxGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_maxGlyphBoundingBoxY; } float minGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_minGlyphBoundingBoxY; } @@ -57,6 +59,18 @@ public: Vector<SVGGlyph::ArabicForm>& arabicForms() { return m_arabicForms; } #endif + static bool supportsTypesettingFeatures(const Font& font) + { +#if !PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 + return !font.typesettingFeatures(); +#else + if (!font.isPrinterFont()) + return !font.typesettingFeatures(); + + return !(font.typesettingFeatures() & ~(Kerning | Ligatures)); +#endif + } + const Font* m_font; const TextRun& m_run; @@ -78,6 +92,9 @@ private: template <typename TextIterator> inline unsigned advanceInternal(TextIterator&, GlyphBuffer*); + bool shouldApplyFontTransforms() const { return m_run.length() > 1 && (m_typesettingFeatures & (Kerning | Ligatures)); } + + TypesettingFeatures m_typesettingFeatures; HashSet<const SimpleFontData*>* m_fallbackFonts; bool m_accountForGlyphBounds; float m_maxGlyphBoundingBoxY; diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp index fc2a2177c..8ee5baf59 100644 --- a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp +++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp @@ -33,9 +33,9 @@ #include "Frame.h" #include "FrameView.h" #include "GraphicsContext.h" -#include "GraphicsLayer.h" #include "KURL.h" #include "Logging.h" +#include "PlatformLayer.h" #include "SoftLinking.h" #include "TimeRanges.h" #include <CoreMedia/CoreMedia.h> diff --git a/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp b/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp index 81d862981..75faa0caa 100644 --- a/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp +++ b/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp @@ -156,7 +156,7 @@ private: virtual GraphicsLayer::CompositingCoordinatesOrientation platformCALayerContentsOrientation() const { return GraphicsLayer::CompositingCoordinatesBottomUp; } virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& inClip) { } virtual bool platformCALayerShowDebugBorders() const { return false; } - virtual bool platformCALayerShowRepaintCounter() const { return false; } + virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const { return false; } virtual int platformCALayerIncrementRepaintCount() { return 0; } virtual bool platformCALayerContentsOpaque() const { return false; } @@ -915,7 +915,7 @@ AVFWrapper* AVFWrapper::avfWrapperForCallbackContext(void* context) if (it == map().end()) return 0; - return it->second; + return it->value; } void AVFWrapper::scheduleDisconnectAndDelete() diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h index d44a30c73..e70db1a98 100644 --- a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h +++ b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h @@ -29,8 +29,9 @@ #if ENABLE(VIDEO) && USE(AVFOUNDATION) #include "MediaPlayerPrivateAVFoundation.h" +#include <wtf/HashMap.h> -OBJC_CLASS AVAsset; +OBJC_CLASS AVURLAsset; OBJC_CLASS AVPlayer; OBJC_CLASS AVPlayerItem; OBJC_CLASS AVPlayerItemVideoOutput; @@ -38,6 +39,11 @@ OBJC_CLASS AVPlayerLayer; OBJC_CLASS AVAssetImageGenerator; OBJC_CLASS WebCoreAVFMovieObserver; +#if ENABLE(ENCRYPTED_MEDIA) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +OBJC_CLASS WebCoreAVFLoaderDelegate; +OBJC_CLASS AVAssetResourceLoadingRequest; +#endif + #ifndef __OBJC__ typedef struct objc_object *id; #endif @@ -56,6 +62,10 @@ public: void setAsset(id); virtual void tracksChanged(); +#if ENABLE(ENCRYPTED_MEDIA) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + bool shouldWaitForLoadingOfResource(AVAssetResourceLoadingRequest*); +#endif + private: MediaPlayerPrivateAVFoundationObjC(MediaPlayer*); @@ -63,6 +73,10 @@ private: static PassOwnPtr<MediaPlayerPrivateInterface> create(MediaPlayer*); static void getSupportedTypes(HashSet<String>& types); static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs, const KURL&); +#if ENABLE(ENCRYPTED_MEDIA) + static MediaPlayer::SupportsType extendedSupportsType(const String& type, const String& codecs, const String& keySystem, const KURL&); +#endif + static bool isAvailable(); virtual void cancelLoad(); @@ -124,7 +138,13 @@ private: void paintWithVideoOutput(GraphicsContext*, const IntRect&); #endif - RetainPtr<AVAsset> m_avAsset; +#if ENABLE(ENCRYPTED_MEDIA) + virtual MediaPlayer::MediaKeyException addKey(const String&, const unsigned char*, unsigned, const unsigned char*, unsigned, const String&); + virtual MediaPlayer::MediaKeyException generateKeyRequest(const String&, const unsigned char*, unsigned); + virtual MediaPlayer::MediaKeyException cancelKeyRequest(const String&, const String&); +#endif + + RetainPtr<AVURLAsset> m_avAsset; RetainPtr<AVPlayer> m_avPlayer; RetainPtr<AVPlayerItem> m_avPlayerItem; RetainPtr<AVPlayerLayer> m_videoLayer; @@ -139,6 +159,12 @@ private: RetainPtr<AVPlayerItemVideoOutput> m_videoOutput; RetainPtr<CVPixelBufferRef> m_lastImage; #endif + +#if ENABLE(ENCRYPTED_MEDIA) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + RetainPtr<WebCoreAVFLoaderDelegate> m_loaderDelegate; + HashMap<String, RetainPtr<AVAssetResourceLoadingRequest> > m_keyURIToRequestMap; + HashMap<String, RetainPtr<AVAssetResourceLoadingRequest> > m_sessionIDToRequestMap; +#endif }; } diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm index cf75d0cf6..5d9ddd9cb 100644 --- a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm +++ b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm @@ -30,6 +30,7 @@ #import "MediaPlayerPrivateAVFoundationObjC.h" #import "BlockExceptions.h" +#import "DataView.h" #import "FloatConversion.h" #import "FrameView.h" #import "FloatConversion.h" @@ -39,9 +40,13 @@ #import "SecurityOrigin.h" #import "SoftLinking.h" #import "TimeRanges.h" +#import "UUID.h" #import "WebCoreSystemInterface.h" #import <objc/objc-runtime.h> #import <wtf/UnusedParam.h> +#import <wtf/Uint8Array.h> +#import <wtf/Uint16Array.h> +#import <wtf/Uint32Array.h> #import <CoreMedia/CoreMedia.h> #import <AVFoundation/AVFoundation.h> @@ -112,6 +117,25 @@ enum MediaPlayerAVFoundationObservationContext { -(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context; @end +#if ENABLE(ENCRYPTED_MEDIA) +@interface WebCoreAVFLoaderDelegate : NSObject<AVAssetResourceLoaderDelegate> { + MediaPlayerPrivateAVFoundationObjC* m_callback; +} +- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback; +- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest; +@end + +static dispatch_queue_t globalLoaderDelegateQueue() +{ + static dispatch_queue_t globalQueue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + globalQueue = dispatch_queue_create("WebCoreAVFLoaderDelegate queue", DISPATCH_QUEUE_SERIAL); + }); + return globalQueue; +} +#endif + namespace WebCore { static NSArray *assetMetadataKeyNames(); @@ -132,7 +156,11 @@ PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivateAVFoundationObjC::crea void MediaPlayerPrivateAVFoundationObjC::registerMediaEngine(MediaEngineRegistrar registrar) { if (isAvailable()) +#if ENABLE(ENCRYPTED_MEDIA) + registrar(create, getSupportedTypes, extendedSupportsType, 0, 0, 0); +#else registrar(create, getSupportedTypes, supportsType, 0, 0, 0); +#endif } MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC(MediaPlayer* player) @@ -140,6 +168,9 @@ MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC(MediaPlay , m_objcObserver(AdoptNS, [[WebCoreAVFMovieObserver alloc] initWithCallback:this]) , m_videoFrameHasDrawn(false) , m_haveCheckedPlayability(false) +#if ENABLE(ENCRYPTED_MEDIA) + , m_loaderDelegate(AdoptNS, [[WebCoreAVFLoaderDelegate alloc] initWithCallback:this]) +#endif { } @@ -304,6 +335,10 @@ void MediaPlayerPrivateAVFoundationObjC::createAVAssetForURL(const String& url) NSURL *cocoaURL = KURL(ParsedURLString, url); m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:cocoaURL options:options.get()]); +#if ENABLE(ENCRYPTED_MEDIA) + [[m_avAsset.get() resourceLoader] setDelegate:m_loaderDelegate.get() queue:globalLoaderDelegateQueue()]; +#endif + m_haveCheckedPlayability = false; setDelayCallbacks(false); @@ -725,6 +760,59 @@ MediaPlayer::SupportsType MediaPlayerPrivateAVFoundationObjC::supportsType(const return [AVURLAsset isPlayableExtendedMIMEType:typeString] ? MediaPlayer::IsSupported : MediaPlayer::MayBeSupported;; } +#if ENABLE(ENCRYPTED_MEDIA) +static bool keySystemIsSupported(const String& keySystem) +{ + if (equalIgnoringCase(keySystem, "com.apple.lskd") || equalIgnoringCase(keySystem, "com.apple.lskd.1_0")) + return true; + + return false; +} + +MediaPlayer::SupportsType MediaPlayerPrivateAVFoundationObjC::extendedSupportsType(const String& type, const String& codecs, const String& keySystem, const KURL& url) +{ + // From: <http://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1b/encrypted-media/encrypted-media.html#dom-canplaytype> + // In addition to the steps in the current specification, this method must run the following steps: + + // 1. Check whether the Key System is supported with the specified container and codec type(s) by following the steps for the first matching condition from the following list: + // If keySystem is null, continue to the next step. + if (keySystem.isNull() || keySystem.isEmpty()) + return supportsType(type, codecs, url); + + // If keySystem contains an unrecognized or unsupported Key System, return the empty string + if (!keySystemIsSupported(keySystem)) + return MediaPlayer::IsNotSupported; + + // If the Key System specified by keySystem does not support decrypting the container and/or codec specified in the rest of the type string. + // (AVFoundation does not provide an API which would allow us to determine this, so this is a no-op) + + // 2. Return "maybe" or "probably" as appropriate per the existing specification of canPlayType(). + return supportsType(type, codecs, url); +} + +bool MediaPlayerPrivateAVFoundationObjC::shouldWaitForLoadingOfResource(AVAssetResourceLoadingRequest* avRequest) +{ + String keyURI = [[[avRequest request] URL] absoluteString]; + + // Create an initData with the following layout: + // [4 bytes: keyURI size], [keyURI size bytes: keyURI] + unsigned keyURISize = keyURI.length() * sizeof(UChar); + RefPtr<ArrayBuffer> initDataBuffer = ArrayBuffer::create(4 + keyURISize, 1); + RefPtr<DataView> initDataView = DataView::create(initDataBuffer, 0, initDataBuffer->byteLength()); + ExceptionCode ec = 0; + initDataView->setUint32(0, keyURISize, true, ec); + + RefPtr<Uint16Array> keyURIArray = Uint16Array::create(initDataBuffer, 4, keyURI.length()); + keyURIArray->setRange(keyURI.characters(), keyURI.length() / sizeof(unsigned char), 0); + + if (!player()->keyNeeded("com.apple.lskd", emptyString(), static_cast<const unsigned char*>(initDataBuffer->data()), initDataBuffer->byteLength())) + return false; + + m_keyURIToRequestMap.set(keyURI, avRequest); + return true; +} +#endif + bool MediaPlayerPrivateAVFoundationObjC::isAvailable() { return AVFoundationLibrary() && CoreMediaLibrary(); @@ -897,6 +985,133 @@ void MediaPlayerPrivateAVFoundationObjC::paintWithVideoOutput(GraphicsContext* c #endif +#if ENABLE(ENCRYPTED_MEDIA) + +static bool extractKeyURIKeyIDAndCertificateFromInitData(Uint8Array* initData, String& keyURI, String& keyID, RefPtr<Uint8Array>& certificate) +{ + // initData should have the following layout: + // [4 bytes: keyURI length][N bytes: keyURI][4 bytes: contentID length], [N bytes: contentID], [4 bytes: certificate length][N bytes: certificate] + if (initData->byteLength() < 4) + return false; + + RefPtr<ArrayBuffer> initDataBuffer = initData->buffer(); + + // Use a DataView to read uint32 values from the buffer, as Uint32Array requires the reads be aligned on 4-byte boundaries. + RefPtr<DataView> initDataView = DataView::create(initDataBuffer, 0, initDataBuffer->byteLength()); + uint32_t offset = 0; + ExceptionCode ec = 0; + + uint32_t keyURILength = initDataView->getUint32(offset, true, ec); + offset += 4; + if (ec || offset + keyURILength > initData->length()) + return false; + + RefPtr<Uint16Array> keyURIArray = Uint16Array::create(initDataBuffer, offset, keyURILength); + if (!keyURIArray) + return false; + + keyURI = String(keyURIArray->data(), keyURILength / sizeof(unsigned short)); + offset += keyURILength; + + uint32_t keyIDLength = initDataView->getUint32(offset, true, ec); + offset += 4; + if (ec || offset + keyIDLength > initData->length()) + return false; + + RefPtr<Uint16Array> keyIDArray = Uint16Array::create(initDataBuffer, offset, keyIDLength); + if (!keyIDArray) + return false; + + keyID = String(keyIDArray->data(), keyIDLength / sizeof(unsigned short)); + offset += keyIDLength; + + uint32_t certificateLength = initDataView->getUint32(offset, true, ec); + offset += 4; + if (ec || offset + certificateLength > initData->length()) + return false; + + certificate = Uint8Array::create(initDataBuffer, offset, certificateLength); + if (!certificate) + return false; + + return true; +} + +MediaPlayer::MediaKeyException MediaPlayerPrivateAVFoundationObjC::generateKeyRequest(const String& keySystem, const unsigned char* initDataPtr, unsigned initDataLength) +{ + if (!keySystemIsSupported(keySystem)) + return MediaPlayer::KeySystemNotSupported; + + RefPtr<Uint8Array> initData = Uint8Array::create(initDataPtr, initDataLength); + String keyURI; + String keyID; + RefPtr<Uint8Array> certificate; + if (!extractKeyURIKeyIDAndCertificateFromInitData(initData.get(), keyURI, keyID, certificate)) + return MediaPlayer::InvalidPlayerState; + + if (!m_keyURIToRequestMap.contains(keyURI)) + return MediaPlayer::InvalidPlayerState; + + String sessionID = createCanonicalUUIDString(); + + RetainPtr<AVAssetResourceLoadingRequest> avRequest = m_keyURIToRequestMap.get(keyURI); + + RetainPtr<NSData> certificateData = adoptNS([[NSData alloc] initWithBytes:certificate->baseAddress() length:certificate->byteLength()]); + NSString* assetStr = keyID; + RetainPtr<NSData> assetID = [NSData dataWithBytes: [assetStr cStringUsingEncoding:NSUTF8StringEncoding] length:[assetStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; + NSError* error = 0; + RetainPtr<NSData> keyRequest = [avRequest.get() streamingContentKeyRequestDataForApp:certificateData.get() contentIdentifier:assetID.get() options:nil error:&error]; + + if (!keyRequest) { + NSError* underlyingError = [[error userInfo] objectForKey:NSUnderlyingErrorKey]; + player()->keyError(keySystem, sessionID, MediaPlayerClient::DomainError, [underlyingError code]); + return MediaPlayer::NoError; + } + + RefPtr<ArrayBuffer> keyRequestBuffer = ArrayBuffer::create([keyRequest.get() bytes], [keyRequest.get() length]); + RefPtr<Uint8Array> keyRequestArray = Uint8Array::create(keyRequestBuffer, 0, keyRequestBuffer->byteLength()); + player()->keyMessage(keySystem, sessionID, keyRequestArray->data(), keyRequestArray->byteLength()); + + // Move ownership of the AVAssetResourceLoadingRequestfrom the keyIDToRequestMap to the sessionIDToRequestMap: + m_sessionIDToRequestMap.set(sessionID, avRequest); + m_keyURIToRequestMap.remove(keyURI); + + return MediaPlayer::NoError; +} + +MediaPlayer::MediaKeyException MediaPlayerPrivateAVFoundationObjC::addKey(const String& keySystem, const unsigned char* keyPtr, unsigned keyLength, const unsigned char* initDataPtr, unsigned initDataLength, const String& sessionID) +{ + if (!keySystemIsSupported(keySystem)) + return MediaPlayer::KeySystemNotSupported; + + if (!m_sessionIDToRequestMap.contains(sessionID)) + return MediaPlayer::InvalidPlayerState; + + RetainPtr<AVAssetResourceLoadingRequest> avRequest = m_sessionIDToRequestMap.get(sessionID); + RetainPtr<NSData> keyData = adoptNS([[NSData alloc] initWithBytes:keyPtr length:keyLength]); + [avRequest.get() finishLoadingWithResponse:nil data:keyData.get() redirect:nil]; + m_sessionIDToRequestMap.remove(sessionID); + + player()->keyAdded(keySystem, sessionID); + + UNUSED_PARAM(initDataPtr); + UNUSED_PARAM(initDataLength); + return MediaPlayer::NoError; +} + +MediaPlayer::MediaKeyException MediaPlayerPrivateAVFoundationObjC::cancelKeyRequest(const String& keySystem, const String& sessionID) +{ + if (!keySystemIsSupported(keySystem)) + return MediaPlayer::KeySystemNotSupported; + + if (!m_sessionIDToRequestMap.contains(sessionID)) + return MediaPlayer::InvalidPlayerState; + + m_sessionIDToRequestMap.remove(sessionID); + return MediaPlayer::NoError; +} +#endif + NSArray* assetMetadataKeyNames() { static NSArray* keys; @@ -1024,4 +1239,26 @@ NSArray* itemKVOProperties() @end +#if ENABLE(ENCRYPTED_MEDIA) +@implementation WebCoreAVFLoaderDelegate + +- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback +{ + m_callback = callback; + return [super init]; +} + +- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest +{ + UNUSED_PARAM(resourceLoader); + dispatch_async(dispatch_get_main_queue(), ^{ + if (!m_callback->shouldWaitForLoadingOfResource(loadingRequest)) + [loadingRequest finishLoadingWithError:nil]; + }); + return TRUE; +} + +@end +#endif + #endif diff --git a/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp index b85afc345..0281aa1e5 100644 --- a/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp @@ -84,7 +84,7 @@ void DisplayRefreshMonitor::displayLinkFired() m_previousFrameDone = false; - m_timestamp = currentTime(); + m_monotonicAnimationStartTime = monotonicallyIncreasingTime(); callOnMainThread(handleDisplayRefreshedNotificationOnMainThread, this); m_mutex.unlock(); diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp index d3002cfd1..95e023d14 100644 --- a/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp @@ -130,6 +130,7 @@ GraphicsContext3D::~GraphicsContext3D() ::glDeleteFramebuffers(1, &m_fbo); } + m_compositingLayer = 0; // Must release compositing layer before destroying the context. BlackBerry::Platform::Graphics::destroyWebGLContext(m_context); } @@ -233,46 +234,46 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) void GraphicsContext3D::logFrameBufferStatus(int line) { - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "Checking FrameBuffer status at line %d: ", line); + BBLOG(BlackBerry::Platform::LogLevelInfo, "Checking FrameBuffer status at line %d: ", line); switch (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)) { case GL_FRAMEBUFFER_COMPLETE: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "COMPLETE | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "COMPLETE | "); break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE ATTACHMENT | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE ATTACHMENT | "); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "MISSING ATTACHMENT | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "MISSING ATTACHMENT | "); break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE DIMENSIONS | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE DIMENSIONS | "); break; case GL_FRAMEBUFFER_UNSUPPORTED: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "UNSUPPORTED | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "UNSUPPORTED | "); break; case FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE MULTISAMPLE | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE MULTISAMPLE | "); break; } switch (glGetError()) { case GL_NO_ERROR: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "NO ERROR"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "NO ERROR"); break; case GL_INVALID_ENUM: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INVALID ENUM"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INVALID ENUM"); break; case GL_INVALID_VALUE: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INVALID VALUE"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INVALID VALUE"); break; case GL_INVALID_OPERATION: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INVALID OPERATION"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INVALID OPERATION"); break; case GL_OUT_OF_MEMORY: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "OUT OF MEMORY"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "OUT OF MEMORY"); break; } - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "\n"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "\n"); } void GraphicsContext3D::readPixelsIMG(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp index 195070d3a..c1a703acd 100644 --- a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp @@ -48,6 +48,7 @@ #include "FloatConversion.h" #include "FloatRect.h" +#include "GraphicsLayerFactory.h" #include "Image.h" #include "LayerAnimation.h" #include "LayerWebKitThread.h" @@ -79,6 +80,14 @@ static void clearLayerBackgroundColor(LayerWebKitThread& layer) layer.setBackgroundColor(Color::transparent); } +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) +{ + if (!factory) + return adoptPtr(new GraphicsLayerBlackBerry(client)); + + return factory->createGraphicsLayer(client); +} + PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return adoptPtr(new GraphicsLayerBlackBerry(client)); diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h index d8d6b6ae9..5c861264e 100644 --- a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h +++ b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h @@ -116,10 +116,10 @@ public: virtual void setDebugBackgroundColor(const Color&); virtual void setDebugBorder(const Color&, float borderWidth); - void notifySyncRequired() + void notifyFlushRequired() { if (m_client) - m_client->notifySyncRequired(this); + m_client->notifyFlushRequired(this); } void notifyAnimationStarted(double time) diff --git a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp index 706d6ab67..454af1a0c 100644 --- a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp +++ b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp @@ -197,8 +197,8 @@ FloatQuad LayerCompositingThread::getTransformedHolePunchRect() const drawRect.move(-location.x(), -location.y()); #if DEBUG_VIDEO_CLIPPING - IntRect drawRectInWebKitDocumentCoordination = m_layerRenderer->toWebKitDocumentCoordinates(m_drawRect); - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "LayerCompositingThread::getTransformedHolePunchRect() - drawRect=(x=%d,y=%d,width=%d,height=%d) clipRect=(x=%d,y=%d,width=%d,height=%d) clippedRect=(x=%d,y=%d,width=%d,height=%d).", + IntRect drawRectInWebKitDocumentCoordination = m_layerRenderer->toWebKitDocumentCoordinates(m_drawRect); + BBLOG(BlackBerry::Platform::LogLevelInfo, "LayerCompositingThread::getTransformedHolePunchRect() - drawRect=(x=%d,y=%d,width=%d,height=%d) clipRect=(x=%d,y=%d,width=%d,height=%d) clippedRect=(x=%d,y=%d,width=%d,height=%d).", drawRectInWebKitDocumentCoordination.x(), drawRectInWebKitDocumentCoordination.y(), drawRectInWebKitDocumentCoordination.width(), drawRectInWebKitDocumentCoordination.height(), m_holePunchClipRect.x(), m_holePunchClipRect.y(), m_holePunchClipRect.width(), m_holePunchClipRect.height(), drawRect.x(), drawRect.y(), drawRect.width(), drawRect.height()); diff --git a/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp b/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp index 83eacacc0..cd2801e2d 100644 --- a/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp +++ b/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp @@ -370,8 +370,8 @@ void LayerTiler::layerVisibilityChanged(LayerCompositingThread*, bool visible) } for (TileMap::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { - TileIndex index = (*it).first; - LayerTile* tile = (*it).second; + TileIndex index = (*it).key; + LayerTile* tile = (*it).value; tile->setVisible(false); } } @@ -385,21 +385,21 @@ void LayerTiler::uploadTexturesIfNeeded(LayerCompositingThread*) TileJobsMap::const_iterator tileJobsIterEnd = tileJobsMap.end(); for (TileJobsMap::const_iterator tileJobsIter = tileJobsMap.begin(); tileJobsIter != tileJobsIterEnd; ++tileJobsIter) { - IntPoint origin = originOfTile(tileJobsIter->first); + IntPoint origin = originOfTile(tileJobsIter->key); - LayerTile* tile = m_tiles.get(tileJobsIter->first); + LayerTile* tile = m_tiles.get(tileJobsIter->key); if (!tile) { if (origin.x() >= m_requiredTextureSize.width() || origin.y() >= m_requiredTextureSize.height()) continue; tile = new LayerTile(); - m_tiles.add(tileJobsIter->first, tile); + m_tiles.add(tileJobsIter->key, tile); } IntRect tileRect(origin, tileSize()); tileRect.setWidth(min(m_requiredTextureSize.width() - tileRect.x(), tileRect.width())); tileRect.setHeight(min(m_requiredTextureSize.height() - tileRect.y(), tileRect.height())); - performTileJob(tile, *tileJobsIter->second, tileRect); + performTileJob(tile, *tileJobsIter->value, tileRect); } m_textureJobs.clear(); @@ -442,11 +442,11 @@ void LayerTiler::addTileJob(const TileIndex& index, const TextureJob& job, TileJ return; // In this case we leave the previous job. - if (job.m_type == TextureJob::DirtyContents && result.iterator->second->m_type == TextureJob::DiscardContents) + if (job.m_type == TextureJob::DirtyContents && result.iterator->value->m_type == TextureJob::DiscardContents) return; // Override the previous job. - result.iterator->second = &job; + result.iterator->value = &job; } void LayerTiler::performTileJob(LayerTile* tile, const TextureJob& job, const IntRect& tileRect) @@ -631,7 +631,7 @@ void LayerTiler::deleteTextures(LayerCompositingThread*) // touching some WebKit thread state. if (m_tiles.size()) { for (TileMap::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) - (*it).second->discardContents(); + (*it).value->discardContents(); m_tiles.clear(); m_contentsDirty = true; @@ -648,7 +648,7 @@ void LayerTiler::pruneTextures() // Prune tiles that are no longer needed. Vector<TileIndex> tilesToDelete; for (TileMap::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { - TileIndex index = (*it).first; + TileIndex index = (*it).key; IntPoint origin = originOfTile(index); if (origin.x() >= m_requiredTextureSize.width() || origin.y() >= m_requiredTextureSize.height()) @@ -730,7 +730,7 @@ void LayerTiler::bindContentsTexture(LayerCompositingThread*) if (m_tiles.size() != 1) return; - const LayerTile* tile = m_tiles.begin()->second; + const LayerTile* tile = m_tiles.begin()->value; ASSERT(tile->hasTexture()); if (!tile->hasTexture()) diff --git a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp index 42b8bed58..142991cf5 100644 --- a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp +++ b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp @@ -195,11 +195,11 @@ void LayerWebKitThread::setDrawable(bool isDrawable) void LayerWebKitThread::setNeedsCommit() { - // Call notifySyncRequired(), which in this implementation plumbs through to + // Call notifyFlushRequired(), which in this implementation plumbs through to // call scheduleRootLayerCommit() on the WebView, which will cause us to commit // changes done on the WebKit thread for display on the Compositing thread. if (m_owner) - m_owner->notifySyncRequired(); + m_owner->notifyFlushRequired(); } void LayerWebKitThread::notifyAnimationStarted(double time) diff --git a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp index 867d8158c..ea3c89550 100644 --- a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp @@ -21,6 +21,7 @@ #if ENABLE(VIDEO) #include "MediaPlayerPrivateBlackBerry.h" +#include "AuthenticationChallengeManager.h" #include "CookieManager.h" #include "Credential.h" #include "CredentialStorage.h" @@ -41,7 +42,6 @@ #include <BlackBerryPlatformSettings.h> #include <FrameLoaderClientBlackBerry.h> #include <set> -#include <string> #include <wtf/text/CString.h> #if USE(ACCELERATED_COMPOSITING) @@ -66,15 +66,15 @@ void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) registrar(create, getSupportedTypes, supportsType, 0, 0, 0); } -void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types) +void MediaPlayerPrivate::getSupportedTypes(HashSet<WTF::String>& types) { - set<string> supported = PlatformPlayer::allSupportedMimeTypes(); - set<string>::iterator i = supported.begin(); + set<BlackBerry::Platform::String> supported = PlatformPlayer::allSupportedMimeTypes(); + set<BlackBerry::Platform::String>::iterator i = supported.begin(); for (; i != supported.end(); i++) - types.add(i->c_str()); + types.add(*i); } -MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs, const KURL&) +MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const WTF::String& type, const WTF::String& codecs, const KURL&) { if (type.isNull() || type.isEmpty()) { LOG(Media, "MediaPlayer does not support type; type is null or empty."); @@ -95,9 +95,9 @@ void MediaPlayerPrivate::notifyAppActivatedEvent(bool activated) PlatformPlayer::notifyAppActivatedEvent(activated); } -void MediaPlayerPrivate::setCertificatePath(const String& caPath) +void MediaPlayerPrivate::setCertificatePath(const WTF::String& caPath) { - PlatformPlayer::setCertificatePath(string(caPath.utf8().data())); + PlatformPlayer::setCertificatePath(caPath); } MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) @@ -114,6 +114,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_userDrivenSeekTimer(this, &MediaPlayerPrivate::userDrivenSeekTimerFired) , m_lastSeekTime(0) , m_lastSeekTimePending(false) + , m_isAuthenticationChallenging(false) , m_waitMetadataTimer(this, &MediaPlayerPrivate::waitMetadataTimerFired) , m_waitMetadataPopDialogCounter(0) { @@ -121,6 +122,9 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) MediaPlayerPrivate::~MediaPlayerPrivate() { + if (m_isAuthenticationChallenging) + AuthenticationChallengeManager::instance()->cancelAuthenticationChallenge(this); + if (isFullscreen()) { m_webCorePlayer->mediaPlayerClient()->mediaPlayerExitFullscreen(); } @@ -133,14 +137,14 @@ MediaPlayerPrivate::~MediaPlayerPrivate() deleteGuardedObject(m_platformPlayer); } -void MediaPlayerPrivate::load(const String& url) +void MediaPlayerPrivate::load(const WTF::String& url) { - String modifiedUrl(url); + WTF::String modifiedUrl(url); if (modifiedUrl.startsWith("local://")) { KURL kurl = KURL(KURL(), modifiedUrl); kurl.setProtocol("file"); - String tempPath(BlackBerry::Platform::Settings::instance()->applicationLocalDirectory().c_str()); + WTF::String tempPath(BlackBerry::Platform::Settings::instance()->applicationLocalDirectory().c_str()); tempPath.append(kurl.path()); kurl.setPath(tempPath); modifiedUrl = kurl.string(); @@ -160,7 +164,7 @@ void MediaPlayerPrivate::load(const String& url) m_platformPlayer = PlatformPlayer::create(this, tabId, false, modifiedUrl.utf8().data()); #endif - String cookiePairs; + WTF::String cookiePairs; if (!url.isEmpty()) cookiePairs = cookieManager().getCookie(KURL(ParsedURLString, url.utf8().data()), WithHttpOnlyCookies); if (!cookiePairs.isEmpty() && cookiePairs.utf8().data()) @@ -691,7 +695,7 @@ void MediaPlayerPrivate::onBuffering(bool flag) static ProtectionSpace generateProtectionSpaceFromMMRAuthChallenge(const MMRAuthChallenge& authChallenge) { - KURL url(ParsedURLString, String(authChallenge.url().c_str())); + KURL url(ParsedURLString, WTF::String(authChallenge.url().c_str())); ASSERT(url.isValid()); return ProtectionSpace(url.host(), url.port(), @@ -702,7 +706,7 @@ static ProtectionSpace generateProtectionSpaceFromMMRAuthChallenge(const MMRAuth void MediaPlayerPrivate::onAuthenticationNeeded(MMRAuthChallenge& authChallenge) { - KURL url(ParsedURLString, String(authChallenge.url().c_str())); + KURL url(ParsedURLString, WTF::String(authChallenge.url().c_str())); if (!url.isValid()) return; @@ -713,12 +717,18 @@ void MediaPlayerPrivate::onAuthenticationNeeded(MMRAuthChallenge& authChallenge) return; } - if (frameView() && frameView()->hostWindow()) - frameView()->hostWindow()->platformPageClient()->authenticationChallenge(url, protectionSpace, credential, this); + if (!frameView() || !frameView()->hostWindow()) + return; + + m_isAuthenticationChallenging = true; + AuthenticationChallengeManager::instance()->authenticationChallenge(url, protectionSpace, credential, + this, frameView()->hostWindow()->platformPageClient()); } void MediaPlayerPrivate::notifyChallengeResult(const KURL& url, const ProtectionSpace& protectionSpace, AuthenticationChallengeResult result, const Credential& credential) { + m_isAuthenticationChallenging = false; + if (result != AuthenticationChallengeSuccess || !url.isValid()) return; @@ -729,7 +739,7 @@ void MediaPlayerPrivate::notifyChallengeResult(const KURL& url, const Protection void MediaPlayerPrivate::onAuthenticationAccepted(const MMRAuthChallenge& authChallenge) const { - KURL url(ParsedURLString, String(authChallenge.url().c_str())); + KURL url(ParsedURLString, WTF::String(authChallenge.url().c_str())); if (!url.isValid()) return; @@ -794,9 +804,9 @@ static WebMediaStreamDescriptor toWebMediaStreamDescriptor(MediaStreamDescriptor return WebMediaStreamDescriptor(d->label().utf8().data(), audioSources, videoSources); } -WebMediaStreamDescriptor MediaPlayerPrivate::lookupMediaStream(const string& url) +WebMediaStreamDescriptor MediaPlayerPrivate::lookupMediaStream(const BlackBerry::Platform::String& url) { - MediaStreamDescriptor* descriptor = MediaStreamRegistry::registry().lookupMediaStreamDescriptor(String::fromUTF8(url.c_str())); + MediaStreamDescriptor* descriptor = MediaStreamRegistry::registry().lookupMediaStreamDescriptor(WTF::String::fromUTF8(url.c_str())); if (!descriptor) return WebMediaStreamDescriptor(); diff --git a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h index 2629e04f6..7b6654dce 100644 --- a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h +++ b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h @@ -39,12 +39,12 @@ public: static PassOwnPtr<MediaPlayerPrivateInterface> create(MediaPlayer*); static void registerMediaEngine(MediaEngineRegistrar); - static void getSupportedTypes(HashSet<String>&); - static MediaPlayer::SupportsType supportsType(const String&, const String&, const KURL&); + static void getSupportedTypes(HashSet<WTF::String>&); + static MediaPlayer::SupportsType supportsType(const WTF::String&, const WTF::String&, const KURL&); static void notifyAppActivatedEvent(bool); - static void setCertificatePath(const String&); + static void setCertificatePath(const WTF::String&); - virtual void load(const String& url); + virtual void load(const WTF::String& url); virtual void cancelLoad(); virtual void prepareToPlay(); @@ -143,15 +143,15 @@ public: virtual bool isTabVisible() const; virtual int showErrorDialog(BlackBerry::Platform::PlatformPlayer::Error); virtual BlackBerry::Platform::Graphics::Window* platformWindow(); - virtual BlackBerry::Platform::WebMediaStreamDescriptor lookupMediaStream(const std::string& url); + virtual BlackBerry::Platform::WebMediaStreamDescriptor lookupMediaStream(const BlackBerry::Platform::String& url); private: MediaPlayerPrivate(MediaPlayer*); void updateStates(); - String userAgent(const String&) const; + WTF::String userAgent(const WTF::String&) const; - virtual String engineDescription() const { return "BlackBerry"; } + virtual WTF::String engineDescription() const { return "BlackBerry"; } MediaPlayer* m_webCorePlayer; BlackBerry::Platform::PlatformPlayer* m_platformPlayer; @@ -174,6 +174,7 @@ private: Timer<MediaPlayerPrivate> m_userDrivenSeekTimer; float m_lastSeekTime; bool m_lastSeekTimePending; + bool m_isAuthenticationChallenging; void waitMetadataTimerFired(Timer<MediaPlayerPrivate>*); Timer<MediaPlayerPrivate> m_waitMetadataTimer; int m_waitMetadataPopDialogCounter; diff --git a/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp b/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp index 5b6bb8736..d65c4dadd 100644 --- a/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp +++ b/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp @@ -202,10 +202,10 @@ void TextureCacheCompositingThread::setMemoryUsage(size_t memoryUsage) PassRefPtr<Texture> TextureCacheCompositingThread::textureForTiledContents(const SkBitmap& contents, const IntRect& tileRect, const TileIndex& index, bool isOpaque) { HashMap<ContentsKey, TextureMap>::iterator it = m_cache.add(key(contents), TextureMap()).iterator; - TextureMap& map = (*it).second; + TextureMap& map = (*it).value; TextureMap::iterator jt = map.add(index, RefPtr<Texture>()).iterator; - RefPtr<Texture> texture = (*jt).second; + RefPtr<Texture> texture = (*jt).value; if (!texture) { texture = createTexture(); #if DEBUG_TEXTURE_MEMORY_USAGE @@ -244,7 +244,7 @@ PassRefPtr<Texture> TextureCacheCompositingThread::textureForColor(const Color& #endif m_colors.set(color, texture); } else - texture = (*it).second; + texture = (*it).value; // Color textures can't be evicted, so no need for TextureProtector. diff --git a/Source/WebCore/platform/graphics/blackberry/VideoLayerWebKitThread.cpp b/Source/WebCore/platform/graphics/blackberry/VideoLayerWebKitThread.cpp index 7492871d2..1fec120d2 100644 --- a/Source/WebCore/platform/graphics/blackberry/VideoLayerWebKitThread.cpp +++ b/Source/WebCore/platform/graphics/blackberry/VideoLayerWebKitThread.cpp @@ -65,7 +65,7 @@ void VideoLayerWebKitThread::setHolePunchRect(const IntRect& rect) { m_holePunchRect = rect; #if DEBUG_VIDEO_CLIPPING - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "VideoLayerWebKitThread m_holePunchRect=(x=%d,y=%d,width=%d,height=%d).", m_holePunchRect.x(), m_holePunchRect.y(), m_holePunchRect.width(), m_holePunchRect.height()); + BBLOG(BlackBerry::Platform::LogLevelInfo, "VideoLayerWebKitThread m_holePunchRect=(x=%d,y=%d,width=%d,height=%d).", m_holePunchRect.x(), m_holePunchRect.y(), m_holePunchRect.width(), m_holePunchRect.height()); #endif setNeedsCommit(); } @@ -95,7 +95,7 @@ void VideoLayerWebKitThread::boundsChanged() m_holePunchClipRect = holePunchRect(); #if DEBUG_VIDEO_CLIPPING - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "VideoLayerWebKitThread m_holePunchClipRect=(x=%d,y=%d,width=%d,height=%d).", m_holePunchClipRect.x(), m_holePunchClipRect.y(), m_holePunchClipRect.width(), m_holePunchClipRect.height()); + BBLOG(BlackBerry::Platform::LogLevelInfo, "VideoLayerWebKitThread m_holePunchClipRect=(x=%d,y=%d,width=%d,height=%d).", m_holePunchClipRect.x(), m_holePunchClipRect.y(), m_holePunchClipRect.width(), m_holePunchClipRect.height()); #endif } diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp index dcdb586d0..3ec8343a9 100644 --- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp +++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp @@ -32,10 +32,12 @@ #include "Animation.h" #include "FloatConversion.h" #include "FloatRect.h" +#include "GraphicsLayerFactory.h" #include "PlatformCALayer.h" #include "RotateTransformOperation.h" #include "ScaleTransformOperation.h" #include "SystemTime.h" +#include "TextStream.h" #include "TransformState.h" #include "TranslateTransformOperation.h" #include <QuartzCore/CATransform3D.h> @@ -255,6 +257,14 @@ static inline bool supportsAcceleratedFilterAnimations() } #endif +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) +{ + if (!factory) + return adoptPtr(new GraphicsLayerCA(client)); + + return factory->createGraphicsLayer(client); +} + PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return adoptPtr(new GraphicsLayerCA(client)); @@ -265,12 +275,13 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) , m_contentsLayerPurpose(NoContentsLayer) , m_contentsLayerHasBackgroundColor(false) , m_allowTiledLayer(true) + , m_isPageTileCacheLayer(false) , m_uncommittedChanges(0) { PlatformCALayer::LayerType layerType = PlatformCALayer::LayerTypeWebLayer; if (client && client->shouldUseTileCache(this)) { - layerType = PlatformCALayer::LayerTypeTileCacheLayer; - m_usingTileCache = true; + layerType = PlatformCALayer::LayerTypePageTileCacheLayer; + m_isPageTileCacheLayer = true; } m_layer = PlatformCALayer::create(layerType, this); @@ -477,7 +488,7 @@ void GraphicsLayerCA::moveOrCopyAnimations(MoveOrCopy operation, PlatformCALayer // Look for running animations affecting this property. AnimationsMap::const_iterator end = m_runningAnimations.end(); for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) { - const Vector<LayerPropertyAnimation>& propertyAnimations = it->second; + const Vector<LayerPropertyAnimation>& propertyAnimations = it->value; size_t numAnimations = propertyAnimations.size(); for (size_t i = 0; i < numAnimations; ++i) { const LayerPropertyAnimation& currAnimation = propertyAnimations[i]; @@ -719,7 +730,7 @@ void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOff AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName); if (it != m_animationsToProcess.end()) { - AnimationProcessingAction& processingInfo = it->second; + AnimationProcessingAction& processingInfo = it->value; // If an animation is scheduled to be removed, don't change the remove to a pause. if (processingInfo.action != Remove) processingInfo.action = Pause; @@ -854,7 +865,7 @@ void GraphicsLayerCA::layerDidDisplay(PlatformLayer* layer) if (layerCloneMap) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* currClone = it->second.get(); + PlatformCALayer* currClone = it->value.get(); if (!currClone) continue; @@ -884,13 +895,13 @@ FloatPoint GraphicsLayerCA::computePositionRelativeToBase(float& pageScale) cons return FloatPoint(); } -void GraphicsLayerCA::syncCompositingState(const FloatRect& clipRect) +void GraphicsLayerCA::flushCompositingState(const FloatRect& clipRect) { TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(clipRect)); recursiveCommitChanges(state); } -void GraphicsLayerCA::syncCompositingStateForThisLayerOnly() +void GraphicsLayerCA::flushCompositingStateForThisLayerOnly() { float pageScaleFactor; FloatPoint offset = computePositionRelativeToBase(pageScaleFactor); @@ -903,44 +914,72 @@ TiledBacking* GraphicsLayerCA::tiledBacking() return m_layer->tiledBacking(); } -void GraphicsLayerCA::recursiveCommitChanges(const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale) +void GraphicsLayerCA::computeVisibleRect(TransformState& state) { - // Save the state before sending down to kids and restore it after - TransformState localState = state; - - TransformState::TransformAccumulation accumulation = preserves3D() ? TransformState::AccumulateTransform : TransformState::FlattenTransform; - localState.move(m_position.x(), m_position.y(), accumulation); + bool preserve3D = preserves3D() || (parent() ? parent()->preserves3D() : false); + TransformState::TransformAccumulation accumulation = preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform; + + TransformationMatrix layerTransform; + layerTransform.translate(m_position.x(), m_position.y()); if (!transform().isIdentity()) { - TransformationMatrix transformWithAnchorPoint; FloatPoint3D absoluteAnchorPoint(anchorPoint()); absoluteAnchorPoint.scale(size().width(), size().height(), 1); - transformWithAnchorPoint.translate3d(absoluteAnchorPoint.x(), absoluteAnchorPoint.y(), absoluteAnchorPoint.z()); - transformWithAnchorPoint.multiply(transform()); - transformWithAnchorPoint.translate3d(-absoluteAnchorPoint.x(), -absoluteAnchorPoint.y(), -absoluteAnchorPoint.z()); - localState.applyTransform(transformWithAnchorPoint, accumulation); + layerTransform.translate3d(absoluteAnchorPoint.x(), absoluteAnchorPoint.y(), absoluteAnchorPoint.z()); + layerTransform.multiply(transform()); + layerTransform.translate3d(-absoluteAnchorPoint.x(), -absoluteAnchorPoint.y(), -absoluteAnchorPoint.z()); + } + + if (GraphicsLayer* parentLayer = parent()) { + if (!parentLayer->childrenTransform().isIdentity()) { + FloatPoint3D parentAnchorPoint(parentLayer->anchorPoint()); + parentAnchorPoint.scale(parentLayer->size().width(), parentLayer->size().height(), 1); + + layerTransform.translateRight3d(-parentAnchorPoint.x(), -parentAnchorPoint.y(), -parentAnchorPoint.z()); + layerTransform = parentLayer->childrenTransform() * layerTransform; + layerTransform.translateRight3d(parentAnchorPoint.x(), parentAnchorPoint.y(), parentAnchorPoint.z()); + } } + + state.applyTransform(layerTransform, accumulation); - FloatRect clipRectForChildren = localState.lastPlanarQuad().boundingBox(); - FloatRect clipRectForSelf; + FloatRect clipRectForChildren = state.mappedQuad().boundingBox(); + FloatRect clipRectForSelf(0, 0, m_size.width(), m_size.height()); + clipRectForSelf.intersect(clipRectForChildren); if (masksToBounds()) { ASSERT(accumulation == TransformState::FlattenTransform); - // Replace the quad in the TransformState with one that is clipped to this layer's bounds - clipRectForSelf = FloatRect(0, 0, m_size.width(), m_size.height()); - clipRectForSelf.intersect(clipRectForChildren); - localState.setQuad(clipRectForSelf); + state.setQuad(clipRectForSelf); } + m_visibleRect = clipRectForSelf; +} + +void GraphicsLayerCA::recursiveCommitChanges(const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale) +{ + TransformState localState = state; + computeVisibleRect(localState); + #ifdef VISIBLE_TILE_WASH - if (m_visibleTileWashLayer) { - if (clipRectForSelf.isEmpty()) { - clipRectForSelf = FloatRect(0, 0, m_size.width(), m_size.height()); - clipRectForSelf.intersect(clipRectForChildren); - } - m_visibleTileWashLayer->setFrame(clipRectForSelf); + // Use having a transform as a key to making the tile wash layer. If every layer gets a wash, + // they start to obscure useful information. + if ((!m_transform.isIdentity() || m_usingTiledLayer) && !m_visibleTileWashLayer) { + static Color washFillColor(255, 0, 0, 50); + static Color washBorderColor(255, 0, 0, 100); + + m_visibleTileWashLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); + String name = String::format("Visible Tile Wash Layer %p", m_visibleTileWashLayer->platformLayer()); + m_visibleTileWashLayer->setName(name); + m_visibleTileWashLayer->setAnchorPoint(FloatPoint3D(0, 0, 0)); + m_visibleTileWashLayer->setBorderColor(washBorderColor); + m_visibleTileWashLayer->setBorderWidth(8); + m_visibleTileWashLayer->setBackgroundColor(washFillColor); + noteSublayersChanged(); } + + if (m_visibleTileWashLayer) + m_visibleTileWashLayer->setFrame(m_visibleRect); #endif bool hadChanges = m_uncommittedChanges; @@ -963,9 +1002,6 @@ void GraphicsLayerCA::recursiveCommitChanges(const TransformState& state, float const Vector<GraphicsLayer*>& childLayers = children(); size_t numChildren = childLayers.size(); - if (!childrenTransform().isIdentity()) - localState.applyTransform(childrenTransform(), accumulation); - for (size_t i = 0; i < numChildren; ++i) { GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); curChild->recursiveCommitChanges(localState, pageScaleFactor, baseRelativePosition, affectedByPageScale); @@ -983,6 +1019,16 @@ void GraphicsLayerCA::recursiveCommitChanges(const TransformState& state, float client()->didCommitChangesForLayer(this); } +bool GraphicsLayerCA::platformCALayerShowRepaintCounter(PlatformCALayer* platformLayer) const +{ + // The repaint counters are painted into the TileCache tiles (which have no corresponding platform layer), + // so we don't want to overpaint the repaint counter when called with the TileCache's own layer. + if (m_isPageTileCacheLayer && platformLayer) + return false; + + return showRepaintCounter(); +} + void GraphicsLayerCA::platformCALayerPaintContents(GraphicsContext& context, const IntRect& clip) { paintGraphicsLayerContents(context, clip); @@ -990,14 +1036,14 @@ void GraphicsLayerCA::platformCALayerPaintContents(GraphicsContext& context, con void GraphicsLayerCA::platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects) { - ASSERT(m_layer->layerType() == PlatformCALayer::LayerTypeTileCacheLayer); + ASSERT(m_layer->usesTileCacheLayer()); for (size_t i = 0; i < dirtyRects.size(); ++i) setNeedsDisplayInRect(dirtyRects[i]); // Ensure that the layout is up to date before any individual tiles are painted by telling the client - // that it needs to sync its layer state, which will end up scheduling the layer flusher. - client()->notifySyncRequired(this); + // that it needs to flush its layer state, which will end up scheduling the layer flusher. + client()->notifyFlushRequired(this); } float GraphicsLayerCA::platformCALayerDeviceScaleFactor() @@ -1196,10 +1242,10 @@ void GraphicsLayerCA::updateGeometry(float pageScaleFactor, const FloatPoint& po if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* clone = it->second.get(); + PlatformCALayer* clone = it->value.get(); FloatPoint clonePosition = layerPosition; - if (m_replicaLayer && isReplicatedRootClone(it->first)) { + if (m_replicaLayer && isReplicatedRootClone(it->key)) { // Maintain the special-case position for the root of a clone subtree, // which we set up in replicatedLayerRoot(). clonePosition = positionForCloneRootLayer(); @@ -1223,10 +1269,10 @@ void GraphicsLayerCA::updateGeometry(float pageScaleFactor, const FloatPoint& po if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* clone = it->second.get(); + PlatformCALayer* clone = it->value.get(); FloatPoint clonePosition = adjustedPosition; - if (!m_structuralLayer && m_replicaLayer && isReplicatedRootClone(it->first)) { + if (!m_structuralLayer && m_replicaLayer && isReplicatedRootClone(it->key)) { // Maintain the special-case position for the root of a clone subtree, // which we set up in replicatedLayerRoot(). clonePosition = positionForCloneRootLayer(); @@ -1246,8 +1292,8 @@ void GraphicsLayerCA::updateTransform() if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* currLayer = it->second.get(); - if (m_replicaLayer && isReplicatedRootClone(it->first)) { + PlatformCALayer* currLayer = it->value.get(); + if (m_replicaLayer && isReplicatedRootClone(it->key)) { // Maintain the special-case transform for the root of a clone subtree, // which we set up in replicatedLayerRoot(). currLayer->setTransform(TransformationMatrix()); @@ -1264,7 +1310,7 @@ void GraphicsLayerCA::updateChildrenTransform() if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setSublayerTransform(m_childrenTransform); + it->value->setSublayerTransform(m_childrenTransform); } } @@ -1275,7 +1321,7 @@ void GraphicsLayerCA::updateMasksToBounds() if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setMasksToBounds(m_masksToBounds); + it->value->setMasksToBounds(m_masksToBounds); } updateDebugIndicators(); @@ -1293,7 +1339,7 @@ void GraphicsLayerCA::updateContentsVisibility() if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setContents(0); + it->value->setContents(0); } } } @@ -1305,7 +1351,7 @@ void GraphicsLayerCA::updateContentsOpaque() if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setOpaque(m_contentsOpaque); + it->value->setOpaque(m_contentsOpaque); } } @@ -1317,7 +1363,7 @@ void GraphicsLayerCA::updateBackfaceVisibility() if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setDoubleSided(m_backfaceVisibility); + it->value->setDoubleSided(m_backfaceVisibility); } } @@ -1326,7 +1372,7 @@ void GraphicsLayerCA::updateBackfaceVisibility() if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setDoubleSided(m_backfaceVisibility); + it->value->setDoubleSided(m_backfaceVisibility); } } @@ -1338,10 +1384,10 @@ void GraphicsLayerCA::updateFilters() if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second->setFilters(m_filters); + it->value->setFilters(m_filters); } } } @@ -1430,7 +1476,7 @@ void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose, floa if (m_layerClones) { LayerMap::const_iterator end = m_layerClones->end(); for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) { - PlatformCALayer* currLayer = it->second.get(); + PlatformCALayer* currLayer = it->value.get(); currLayer->setPosition(point); currLayer->setAnchorPoint(anchorPoint); currLayer->setTransform(TransformationMatrix()); @@ -1475,7 +1521,7 @@ void GraphicsLayerCA::updateLayerDrawsContent(float pageScaleFactor, const Float if (m_layerClones) { LayerMap::const_iterator end = m_layerClones->end(); for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) - it->second->setContents(0); + it->value->setContents(0); } } updateDebugIndicators(); @@ -1488,7 +1534,7 @@ void GraphicsLayerCA::updateAcceleratesDrawing() void GraphicsLayerCA::updateLayerBackgroundColor() { - if (m_layer->layerType() == PlatformCALayer::LayerTypeTileCacheLayer) { + if (m_isPageTileCacheLayer) { m_layer->setBackgroundColor(m_backgroundColor); return; } @@ -1526,7 +1572,7 @@ void GraphicsLayerCA::updateContentsImage() if (m_contentsLayerClones) { LayerMap::const_iterator end = m_contentsLayerClones->end(); for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) - it->second->setContents(m_contentsLayer->contents()); + it->value->setContents(m_contentsLayer->contents()); } updateContentsRect(); @@ -1570,8 +1616,8 @@ void GraphicsLayerCA::updateContentsRect() if (m_contentsLayerClones) { LayerMap::const_iterator end = m_contentsLayerClones->end(); for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) { - it->second->setPosition(point); - it->second->setBounds(rect); + it->value->setPosition(point); + it->value->setBounds(rect); } } } @@ -1586,8 +1632,8 @@ void GraphicsLayerCA::updateMaskLayer() if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->first).get() : 0; - it->second->setMask(maskClone); + PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->key).get() : 0; + it->value->setMask(maskClone); } } } @@ -1651,13 +1697,13 @@ void GraphicsLayerCA::updateLayerAnimations() if (m_animationsToProcess.size()) { AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end(); for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) { - const String& currAnimationName = it->first; + const String& currAnimationName = it->key; AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName); if (animationIt == m_runningAnimations.end()) continue; - const AnimationProcessingAction& processingInfo = it->second; - const Vector<LayerPropertyAnimation>& animations = animationIt->second; + const AnimationProcessingAction& processingInfo = it->value; + const Vector<LayerPropertyAnimation>& animations = animationIt->value; for (size_t i = 0; i < animations.size(); ++i) { const LayerPropertyAnimation& currAnimation = animations[i]; switch (processingInfo.action) { @@ -1689,7 +1735,7 @@ void GraphicsLayerCA::updateLayerAnimations() animations.append(pendingAnimation); m_runningAnimations.add(pendingAnimation.m_name, animations); } else { - Vector<LayerPropertyAnimation>& animations = it->second; + Vector<LayerPropertyAnimation>& animations = it->value; animations.append(pendingAnimation); } } @@ -1714,11 +1760,11 @@ void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation* caAnim, AnimatedP LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { // Skip immediate replicas, since they move with the original. - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second->removeAnimationForKey(animationID); - it->second->addAnimationForKey(animationID, caAnim); + it->value->removeAnimationForKey(animationID); + it->value->addAnimationForKey(animationID, caAnim); } } } @@ -1753,10 +1799,10 @@ bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, co LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { // Skip immediate replicas, since they move with the original. - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second ->removeAnimationForKey(animationID); + it->value->removeAnimationForKey(animationID); } } return true; @@ -1785,9 +1831,9 @@ void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { // Skip immediate replicas, since they move with the original. - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second->addAnimationForKey(animationID, newAnim.get()); + it->value->addAnimationForKey(animationID, newAnim.get()); } } } @@ -2311,8 +2357,8 @@ void GraphicsLayerCA::suspendAnimations(double time) if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - it->second->setSpeed(0); - it->second->setTimeOffset(t); + it->value->setSpeed(0); + it->value->setTimeOffset(t); } } } @@ -2326,8 +2372,8 @@ void GraphicsLayerCA::resumeAnimations() if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - it->second->setSpeed(1); - it->second->setTimeOffset(0); + it->value->setSpeed(1); + it->value->setTimeOffset(0); } } } @@ -2382,6 +2428,25 @@ void GraphicsLayerCA::setDebugBackgroundColor(const Color& color) m_layer->setBackgroundColor(Color::transparent); } +void GraphicsLayerCA::getDebugBorderInfo(Color& color, float& width) const +{ + if (m_isPageTileCacheLayer) { + color = Color(0, 0, 128, 128); // tile cache layer: dark blue + width = 0.5; + return; + } + + GraphicsLayer::getDebugBorderInfo(color, width); +} + +void GraphicsLayerCA::dumpAdditionalProperties(TextStream& textStream, int indent, LayerTreeAsTextBehavior behavior) const +{ + if (behavior & LayerTreeAsTextIncludeVisibleRects) { + writeIndent(textStream, indent + 1); + textStream << "(visible rect " << m_visibleRect.x() << ", " << m_visibleRect.y() << " " << m_visibleRect.width() << " x " << m_visibleRect.height() << ")\n"; + } +} + void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) { if (color.isValid()) { @@ -2419,7 +2484,7 @@ FloatSize GraphicsLayerCA::constrainedSize() const bool GraphicsLayerCA::requiresTiledLayer(float pageScaleFactor) const { - if (!m_drawsContent || !m_allowTiledLayer || m_layer->layerType() == PlatformCALayer::LayerTypeTileCacheLayer) + if (!m_drawsContent || !m_allowTiledLayer || m_isPageTileCacheLayer) return false; // FIXME: catch zero-size height or width here (or earlier)? @@ -2428,34 +2493,13 @@ bool GraphicsLayerCA::requiresTiledLayer(float pageScaleFactor) const void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer, float pageScaleFactor, const FloatPoint& positionRelativeToBase) { - ASSERT(m_layer->layerType() != PlatformCALayer::LayerTypeTileCacheLayer); + ASSERT(m_layer->layerType() != PlatformCALayer::LayerTypePageTileCacheLayer); ASSERT(useTiledLayer != m_usingTiledLayer); RefPtr<PlatformCALayer> oldLayer = m_layer; m_layer = PlatformCALayer::create(useTiledLayer ? PlatformCALayer::LayerTypeWebTiledLayer : PlatformCALayer::LayerTypeWebLayer, this); m_usingTiledLayer = useTiledLayer; -#ifdef VISIBLE_TILE_WASH - if (useTiledLayer) { - if (!m_visibleTileWashLayer) { - static Color washFillColor(255, 0, 0, 50); - static Color washBorderColor(255, 0, 0, 100); - - m_visibleTileWashLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); - String name = String::format("Visible Tile Wash Layer %p", m_visibleTileWashLayer->platformLayer()); - m_visibleTileWashLayer->setName(name); - m_visibleTileWashLayer->setAnchorPoint(FloatPoint3D(0, 0, 0)); - m_visibleTileWashLayer->setBorderColor(washBorderColor); - m_visibleTileWashLayer->setBorderWidth(8); - m_visibleTileWashLayer->setBackgroundColor(washFillColor); - } - } else { - if (m_visibleTileWashLayer) - m_visibleTileWashLayer->removeFromSuperlayer(); - m_visibleTileWashLayer = 0; - } -#endif - m_layer->adoptSublayers(oldLayer.get()); #ifdef VISIBLE_TILE_WASH @@ -2537,13 +2581,13 @@ PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, Pl LayerMap::AddResult addResult = clones->add(cloneID, dummy); if (!addResult.isNewEntry) { // Value was not added, so it exists already. - resultLayer = addResult.iterator->second.get(); + resultLayer = addResult.iterator->value.get(); } else { resultLayer = cloneLayer(sourceLayer, cloneLevel); #ifndef NDEBUG resultLayer->setName(String::format("Clone %d of layer %p", cloneID[0U], sourceLayer->platformLayer())); #endif - addResult.iterator->second = resultLayer; + addResult.iterator->value = resultLayer; } return resultLayer; @@ -2577,7 +2621,7 @@ void GraphicsLayerCA::removeCloneLayers() FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const { - // This can get called during a sync when we've just removed the m_replicaLayer. + // This can get called during a flush when we've just removed the m_replicaLayer. if (!m_replicaLayer) return FloatPoint(); @@ -2735,9 +2779,9 @@ void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity) if (layerCloneMap) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second->setOpacity(m_opacity); + it->value->setOpacity(m_opacity); } } } @@ -2749,10 +2793,10 @@ void GraphicsLayerCA::updateOpacityOnLayer() if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second->setOpacity(m_opacity); + it->value->setOpacity(m_opacity); } } @@ -2834,7 +2878,7 @@ void GraphicsLayerCA::noteSublayersChanged() void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags) { if (!m_uncommittedChanges && m_client) - m_client->notifySyncRequired(this); + m_client->notifyFlushRequired(this); m_uncommittedChanges |= flags; } diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h index d5b4c2c61..b8da5776a 100644 --- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h +++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h @@ -38,7 +38,7 @@ #include <wtf/text/StringHash.h> // Enable this to add a light red wash over the visible portion of Tiled Layers, as computed -// by syncCompositingState(). +// by flushCompositingState(). // #define VISIBLE_TILE_WASH namespace WebCore { @@ -131,8 +131,8 @@ public: void recursiveCommitChanges(const TransformState&, float pageScaleFactor = 1, const FloatPoint& positionRelativeToBase = FloatPoint(), bool affectedByPageScale = false); - virtual void syncCompositingState(const FloatRect&); - virtual void syncCompositingStateForThisLayerOnly(); + virtual void flushCompositingState(const FloatRect&); + virtual void flushCompositingStateForThisLayerOnly(); virtual TiledBacking* tiledBacking() OVERRIDE; @@ -153,7 +153,7 @@ private: virtual CompositingCoordinatesOrientation platformCALayerContentsOrientation() const { return contentsOrientation(); } virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& clip); virtual bool platformCALayerShowDebugBorders() const { return showDebugBorders(); } - virtual bool platformCALayerShowRepaintCounter() const { return showRepaintCounter(); } + virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const; virtual int platformCALayerIncrementRepaintCount() { return incrementRepaintCount(); } virtual bool platformCALayerContentsOpaque() const { return contentsOpaque(); } @@ -228,8 +228,12 @@ private: virtual void setReplicatedByLayer(GraphicsLayer*); + virtual void getDebugBorderInfo(Color&, float& width) const; + virtual void dumpAdditionalProperties(TextStream&, int indent, LayerTreeAsTextBehavior) const; + void computePixelAlignment(float pixelAlignmentScale, const FloatPoint& positionRelativeToBase, FloatPoint& position, FloatSize&, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset) const; + void computeVisibleRect(TransformState&); // Used to track the path down the tree for replica layers. struct ReplicaState { @@ -391,6 +395,7 @@ private: #ifdef VISIBLE_TILE_WASH RefPtr<PlatformCALayer> m_visibleTileWashLayer; #endif + FloatRect m_visibleRect; enum ContentsLayerPurpose { NoContentsLayer = 0, @@ -403,6 +408,7 @@ private: ContentsLayerPurpose m_contentsLayerPurpose; bool m_contentsLayerHasBackgroundColor : 1; bool m_allowTiledLayer : 1; + bool m_isPageTileCacheLayer : 1; RetainPtr<CGImageRef> m_uncorrectedContentsImage; RetainPtr<CGImageRef> m_pendingContentsImage; diff --git a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h index e412a1d85..520711681 100644 --- a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h +++ b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h @@ -60,6 +60,7 @@ public: LayerTypeTransformLayer, LayerTypeWebTiledLayer, LayerTypeTileCacheLayer, + LayerTypePageTileCacheLayer, LayerTypeRootLayer, LayerTypeCustom }; @@ -79,6 +80,8 @@ public: PlatformLayer* platformLayer() const; + bool usesTileCacheLayer() const { return m_layerType == LayerTypePageTileCacheLayer || m_layerType == LayerTypeTileCacheLayer; } + PlatformCALayer* rootLayer() const; // A list of sublayers that GraphicsLayerCA should maintain as the first sublayers. diff --git a/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h b/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h index 316606173..185d6358c 100644 --- a/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h +++ b/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h @@ -52,7 +52,7 @@ public: virtual GraphicsLayer::CompositingCoordinatesOrientation platformCALayerContentsOrientation() const = 0; virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& inClip) = 0; virtual bool platformCALayerShowDebugBorders() const = 0; - virtual bool platformCALayerShowRepaintCounter() const = 0; + virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const = 0; virtual int platformCALayerIncrementRepaintCount() = 0; virtual bool platformCALayerContentsOpaque() const = 0; diff --git a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm index d50886801..915a60be6 100644 --- a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm +++ b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm @@ -35,6 +35,7 @@ #import "GraphicsContext.h" #import "GraphicsLayerCA.h" #import "LengthFunctions.h" +#import "TiledBacking.h" #import "WebLayer.h" #import "WebTiledLayer.h" #import "WebTileCacheLayer.h" @@ -193,6 +194,7 @@ PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformLayer* layer, Plat layerClass = [WebTiledLayer class]; break; case LayerTypeTileCacheLayer: + case LayerTypePageTileCacheLayer: layerClass = [WebTileCacheLayer class]; break; case LayerTypeCustom: @@ -218,7 +220,7 @@ PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformLayer* layer, Plat [tiledLayer setContentsGravity:@"bottomLeft"]; } - if (m_layerType == LayerTypeTileCacheLayer) { + if (usesTileCacheLayer()) { m_customSublayers = adoptPtr(new PlatformCALayerList(1)); CALayer* tileCacheTileContainerLayer = [static_cast<WebTileCacheLayer *>(m_layer.get()) tileContainerLayer]; (*m_customSublayers)[0] = PlatformCALayer::create(tileCacheTileContainerLayer, 0); @@ -238,7 +240,7 @@ PlatformCALayer::~PlatformCALayer() // Remove the owner pointer from the delegate in case there is a pending animationStarted event. [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil]; - if (m_layerType == LayerTypeTileCacheLayer) + if (usesTileCacheLayer()) [static_cast<WebTileCacheLayer *>(m_layer.get()) invalidate]; } @@ -931,7 +933,7 @@ void PlatformCALayer::setContentsScale(float value) TiledBacking* PlatformCALayer::tiledBacking() { - if (m_layerType != LayerTypeTileCacheLayer) + if (!usesTileCacheLayer()) return 0; WebTileCacheLayer *tileCacheLayer = static_cast<WebTileCacheLayer *>(m_layer.get()); diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.h b/Source/WebCore/platform/graphics/ca/mac/TileCache.h index a7d33fbe5..76387e8aa 100644 --- a/Source/WebCore/platform/graphics/ca/mac/TileCache.h +++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.h @@ -65,6 +65,9 @@ public: bool acceleratesDrawing() const { return m_acceleratesDrawing; } void setAcceleratesDrawing(bool); + void setTilesOpaque(bool); + bool tilesAreOpaque() const { return m_tilesAreOpaque; } + CALayer *tileContainerLayer() const { return m_tileContainerLayer.get(); } void setTileDebugBorderWidth(float); @@ -81,8 +84,11 @@ private: // TiledBacking member functions. virtual void visibleRectChanged(const IntRect&) OVERRIDE; virtual void setIsInWindow(bool) OVERRIDE; - virtual void setCanHaveScrollbars(bool) OVERRIDE; + virtual void setTileCoverage(TileCoverage) OVERRIDE; + virtual TileCoverage tileCoverage() const OVERRIDE { return m_tileCoverage; } virtual void forceRepaint() OVERRIDE; + virtual void setScrollingPerformanceLoggingEnabled(bool flag) OVERRIDE { m_scrollingPerformanceLoggingEnabled = flag; } + virtual bool scrollingPerformanceLoggingEnabled() const OVERRIDE { return m_scrollingPerformanceLoggingEnabled; } IntRect bounds() const; @@ -115,9 +121,11 @@ private: CGFloat m_scale; CGFloat m_deviceScaleFactor; + TileCoverage m_tileCoverage; bool m_isInWindow; - bool m_canHaveScrollbars; + bool m_scrollingPerformanceLoggingEnabled; bool m_acceleratesDrawing; + bool m_tilesAreOpaque; RetainPtr<CGColorRef> m_tileDebugBorderColor; float m_tileDebugBorderWidth; diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm index 6ba528089..b12b14d11 100644 --- a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm +++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm @@ -57,9 +57,11 @@ TileCache::TileCache(WebTileCacheLayer* tileCacheLayer, const IntSize& tileSize) , m_tileRevalidationTimer(this, &TileCache::tileRevalidationTimerFired) , m_scale(1) , m_deviceScaleFactor(1) - , m_isInWindow(true) - , m_canHaveScrollbars(true) + , m_tileCoverage(CoverageForVisibleArea) + , m_isInWindow(false) + , m_scrollingPerformanceLoggingEnabled(false) , m_acceleratesDrawing(false) + , m_tilesAreOpaque(false) , m_tileDebugBorderWidth(0) { [CATransaction begin]; @@ -76,7 +78,7 @@ TileCache::~TileCache() ASSERT(isMainThread()); for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { - WebTileLayer* tileLayer = it->second.get(); + WebTileLayer* tileLayer = it->value.get(); [tileLayer setTileCache:0]; } } @@ -96,7 +98,7 @@ void TileCache::tileCacheLayerBoundsChanged() void TileCache::setNeedsDisplay() { for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) - [it->second.get() setNeedsDisplay]; + [it->value.get() setNeedsDisplay]; } void TileCache::setNeedsDisplayInRect(const IntRect& rect) @@ -177,9 +179,9 @@ void TileCache::setScale(CGFloat scale) revalidateTiles(); for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { - [it->second.get() setContentsScale:deviceScaleFactor]; + [it->value.get() setContentsScale:deviceScaleFactor]; - IntRect tileRect = rectForTileIndex(it->first); + IntRect tileRect = rectForTileIndex(it->key); FloatRect scaledTileRect = tileRect; scaledTileRect.scale(1 / m_scale); @@ -199,12 +201,25 @@ void TileCache::setAcceleratesDrawing(bool acceleratesDrawing) m_acceleratesDrawing = acceleratesDrawing; for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) - [it->second.get() setAcceleratesDrawing:m_acceleratesDrawing]; + [it->value.get() setAcceleratesDrawing:m_acceleratesDrawing]; #else UNUSED_PARAM(acceleratesDrawing); #endif } +void TileCache::setTilesOpaque(bool opaque) +{ + if (opaque == m_tilesAreOpaque) + return; + + m_tilesAreOpaque = opaque; + + for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { + WebTileLayer* tileLayer = it->value.get(); + [tileLayer setOpaque:opaque]; + } +} + void TileCache::visibleRectChanged(const IntRect& visibleRect) { if (m_visibleRect == visibleRect) @@ -222,18 +237,17 @@ void TileCache::setIsInWindow(bool isInWindow) m_isInWindow = isInWindow; if (!m_isInWindow) { - // Schedule a timeout to drop tiles that are outside of the visible rect in 4 seconds. const double tileRevalidationTimeout = 4; scheduleTileRevalidation(tileRevalidationTimeout); } } -void TileCache::setCanHaveScrollbars(bool canHaveScrollbars) +void TileCache::setTileCoverage(TileCoverage coverage) { - if (m_canHaveScrollbars == canHaveScrollbars) + if (coverage == m_tileCoverage) return; - m_canHaveScrollbars = canHaveScrollbars; + m_tileCoverage = coverage; scheduleTileRevalidation(0); } @@ -249,7 +263,7 @@ void TileCache::setTileDebugBorderWidth(float borderWidth) m_tileDebugBorderWidth = borderWidth; for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) - [it->second.get() setBorderWidth:m_tileDebugBorderWidth]; + [it->value.get() setBorderWidth:m_tileDebugBorderWidth]; } void TileCache::setTileDebugBorderColor(CGColorRef borderColor) @@ -259,7 +273,7 @@ void TileCache::setTileDebugBorderColor(CGColorRef borderColor) m_tileDebugBorderColor = borderColor; for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) - [it->second.get() setBorderColor:m_tileDebugBorderColor.get()]; + [it->value.get() setBorderColor:m_tileDebugBorderColor.get()]; } IntRect TileCache::bounds() const @@ -297,12 +311,15 @@ IntRect TileCache::tileCoverageRect() const // If the page is not in a window (for example if it's in a background tab), we limit the tile coverage rect to the visible rect. // Furthermore, if the page can't have scrollbars (for example if its body element has overflow:hidden) it's very unlikely that the // page will ever be scrolled so we limit the tile coverage rect as well. - if (m_isInWindow && m_canHaveScrollbars) { + if (m_isInWindow) { // Inflate the coverage rect so that it covers 2x of the visible width and 3x of the visible height. // These values were chosen because it's more common to have tall pages and to scroll vertically, // so we keep more tiles above and below the current area. - tileCoverageRect.inflateX(tileCoverageRect.width() / 2); - tileCoverageRect.inflateY(tileCoverageRect.height()); + if (m_tileCoverage && CoverageForHorizontalScrolling) + tileCoverageRect.inflateX(tileCoverageRect.width() / 2); + + if (m_tileCoverage && CoverageForVerticalScrolling) + tileCoverageRect.inflateY(tileCoverageRect.height()); } return tileCoverageRect; @@ -365,9 +382,9 @@ void TileCache::revalidateTiles() Vector<TileIndex> tilesToRemove; for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { - const TileIndex& tileIndex = it->first; + const TileIndex& tileIndex = it->key; - WebTileLayer* tileLayer = it->second.get(); + WebTileLayer* tileLayer = it->value.get(); if (!rectForTileIndex(tileIndex).intersects(tileCoverageRect)) { // Remove this layer. @@ -395,7 +412,7 @@ void TileCache::revalidateTiles() TileIndex tileIndex(x, y); IntRect tileRect = rectForTileIndex(tileIndex); - RetainPtr<WebTileLayer>& tileLayer = m_tiles.add(tileIndex, 0).iterator->second; + RetainPtr<WebTileLayer>& tileLayer = m_tiles.add(tileIndex, 0).iterator->value; if (!tileLayer) { tileLayer = createTileLayer(tileRect); [m_tileContainerLayer.get() addSublayer:tileLayer.get()]; @@ -415,7 +432,7 @@ void TileCache::revalidateTiles() m_tileCoverageRect = IntRect(); for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { - const TileIndex& tileIndex = it->first; + const TileIndex& tileIndex = it->key; m_tileCoverageRect.unite(rectForTileIndex(tileIndex)); } @@ -439,7 +456,7 @@ RetainPtr<WebTileLayer> TileCache::createTileLayer(const IntRect& tileRect) [layer.get() setBorderColor:m_tileDebugBorderColor.get()]; [layer.get() setBorderWidth:m_tileDebugBorderWidth]; [layer.get() setEdgeAntialiasingMask:0]; - [layer.get() setOpaque:YES]; + [layer.get() setOpaque:m_tilesAreOpaque]; #ifndef NDEBUG [layer.get() setName:@"Tile"]; #endif @@ -463,7 +480,7 @@ bool TileCache::shouldShowRepaintCounters() const if (!layerContents) return false; - return layerContents->platformCALayerShowRepaintCounter(); + return layerContents->platformCALayerShowRepaintCounter(0); } void TileCache::drawRepaintCounter(WebTileLayer *layer, CGContextRef context) diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm index 72ae6fbd4..c6aab8aff 100644 --- a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm +++ b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm @@ -78,6 +78,16 @@ using namespace WebCore; _tileCache->tileCacheLayerBoundsChanged(); } +- (void)setOpaque:(BOOL)opaque +{ + _tileCache->setTilesOpaque(opaque); +} + +- (BOOL)isOpaque +{ + return _tileCache->tilesAreOpaque(); +} + - (void)setNeedsDisplay { _tileCache->setNeedsDisplay(); @@ -127,7 +137,8 @@ using namespace WebCore; - (void)setBorderWidth:(CGFloat)borderWidth { - _tileCache->setTileDebugBorderWidth(borderWidth); + // Tiles adjoin, so halve the border width. + _tileCache->setTileDebugBorderWidth(borderWidth / 2); } @end diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm b/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm index df88b623d..f81cd68c8 100644 --- a/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm +++ b/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm @@ -51,7 +51,7 @@ using namespace WebCore; if (_tileCache) { _tileCache->drawLayer(self, context); - if (_tileCache->scrollingPerformanceLoggingEnabled()) + if (static_cast<TiledBacking*>(_tileCache)->scrollingPerformanceLoggingEnabled()) [self logFilledFreshTile]; } } diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp index 48b20d0b8..70168b210 100644 --- a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp +++ b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp @@ -167,7 +167,7 @@ void PlatformCALayer::animationStarted(CFTimeInterval beginTime) HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator end = m_animations.end(); for (HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator it = m_animations.begin(); it != end; ++it) - it->second->setActualStartTimeIfNeeded(cacfBeginTime); + it->value->setActualStartTimeIfNeeded(cacfBeginTime); if (m_owner) m_owner->platformCALayerAnimationStarted(beginTime); @@ -177,8 +177,8 @@ static void resubmitAllAnimations(PlatformCALayer* layer) { HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator end = layer->animations().end(); for (HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator it = layer->animations().begin(); it != end; ++it) { - RetainPtr<CFStringRef> s(AdoptCF, it->first.createCFString()); - CACFLayerAddAnimation(layer->platformLayer(), s.get(), it->second->platformAnimation()); + RetainPtr<CFStringRef> s(AdoptCF, it->key.createCFString()); + CACFLayerAddAnimation(layer->platformLayer(), s.get(), it->value->platformAnimation()); } } @@ -328,7 +328,7 @@ PassRefPtr<PlatformCAAnimation> PlatformCALayer::animationForKey(const String& k if (it == m_animations.end()) return 0; - return it->second; + return it->value; } PlatformCALayer* PlatformCALayer::mask() const diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp index de89ae1ce..c430cf284 100644 --- a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp +++ b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp @@ -96,7 +96,7 @@ void PlatformCALayerWinInternal::displayCallback(CACFLayerRef caLayer, CGContext } #endif - if (owner()->owner()->platformCALayerShowRepaintCounter()) { + if (owner()->owner()->platformCALayerShowRepaintCounter(owner())) { FontCachePurgePreventer fontCachePurgePreventer; String text = String::number(owner()->owner()->platformCALayerIncrementRepaintCount()); @@ -165,14 +165,14 @@ void PlatformCALayerWinInternal::setNeedsDisplay(const FloatRect* dirtyRect) for (int i = 0; i < numTileLayers; ++i) CACFLayerSetNeedsDisplay(tileAtIndex(i), dirtyRect ? &rect : 0); - if (m_owner->owner() && m_owner->owner()->platformCALayerShowRepaintCounter()) { + if (m_owner->owner() && m_owner->owner()->platformCALayerShowRepaintCounter(m_owner)) { CGRect layerBounds = m_owner->bounds(); CGRect indicatorRect = CGRectMake(layerBounds.origin.x, layerBounds.origin.y, 80, 25); CACFLayerSetNeedsDisplay(tileAtIndex(0), &indicatorRect); } } else if (owner()->layerType() == PlatformCALayer::LayerTypeWebLayer) { if (owner() && owner()->owner()) { - if (owner()->owner()->platformCALayerShowRepaintCounter()) { + if (owner()->owner()->platformCALayerShowRepaintCounter(owner())) { FloatRect layerBounds = owner()->bounds(); FloatRect repaintCounterRect = layerBounds; diff --git a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp index e9fa5be8d..83fac1fda 100644 --- a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp @@ -97,7 +97,16 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo context->setCompositeOperation(CompositeCopy); else context->setCompositeOperation(op); - context->platformContext()->drawSurfaceToContext(nativeImage->surface(), dstRect, srcRect, context); + +#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) + cairo_surface_t* surface = nativeImage->surface(); + IntSize scaledSize(cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface)); + FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(srcRect, scaledSize); +#else + FloatRect adjustedSrcRect(srcRect); +#endif + + context->platformContext()->drawSurfaceToContext(nativeImage->surface(), dstRect, adjustedSrcRect, context); context->restore(); diff --git a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp index d6e43eb98..9a0fd305a 100644 --- a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -35,9 +35,9 @@ #include "GlyphBuffer.h" #include "Gradient.h" #include "GraphicsContext.h" -#include "PlatformContextCairo.h" #include "ImageBuffer.h" #include "Pattern.h" +#include "PlatformContextCairo.h" #include "ShadowBlur.h" #include "SimpleFontData.h" diff --git a/Source/WebCore/platform/graphics/cairo/GLContext.cpp b/Source/WebCore/platform/graphics/cairo/GLContext.cpp index 3b804f602..2cb0ab3cc 100644 --- a/Source/WebCore/platform/graphics/cairo/GLContext.cpp +++ b/Source/WebCore/platform/graphics/cairo/GLContext.cpp @@ -21,10 +21,12 @@ #if USE(OPENGL) +#include "GLContextEGL.h" +#include "GLContextGLX.h" #include <wtf/MainThread.h> -#if USE(GLX) -#include "GLContextGLX.h" +#if PLATFORM(X11) +#include <X11/Xlib.h> #endif namespace WebCore { @@ -36,22 +38,106 @@ GLContext* GLContext::sharingContext() return sharing.get(); } +#if PLATFORM(X11) +// We do not want to call glXMakeContextCurrent using different Display pointers, +// because it might lead to crashes in some drivers (fglrx). We use a shared display +// pointer here. +static Display* gSharedX11Display = 0; +Display* GLContext::sharedX11Display() +{ + if (!gSharedX11Display) + gSharedX11Display = XOpenDisplay(0); + return gSharedX11Display; +} + +void GLContext::cleanupSharedX11Display() +{ + if (!gSharedX11Display) + return; + XCloseDisplay(gSharedX11Display); + gSharedX11Display = 0; +} +#endif // PLATFORM(X11) + +// Because of driver bugs, exiting the program when there are active pbuffers +// can crash the X server (this has been observed with the official Nvidia drivers). +// We need to ensure that we clean everything up on exit. There are several reasons +// that GraphicsContext3Ds will still be alive at exit, including user error (memory +// leaks) and the page cache. In any case, we don't want the X server to crash. +typedef Vector<GLContext*> ActiveContextList; +static ActiveContextList& activeContextList() +{ + DEFINE_STATIC_LOCAL(ActiveContextList, activeContexts, ()); + return activeContexts; +} + +void GLContext::addActiveContext(GLContext* context) +{ + static bool addedAtExitHandler = false; + if (!addedAtExitHandler) { + atexit(&GLContext::cleanupActiveContextsAtExit); + addedAtExitHandler = true; + } + activeContextList().append(context); +} + +static bool gCleaningUpAtExit = false; + +void GLContext::removeActiveContext(GLContext* context) +{ + // If we are cleaning up the context list at exit, don't bother removing the context + // from the list, since we don't want to modify the list while it's being iterated. + if (gCleaningUpAtExit) + return; + + ActiveContextList& contextList = activeContextList(); + size_t i = contextList.find(context); + if (i != notFound) + contextList.remove(i); +} + +void GLContext::cleanupActiveContextsAtExit() +{ + gCleaningUpAtExit = true; + + ActiveContextList& contextList = activeContextList(); + for (size_t i = 0; i < contextList.size(); ++i) + delete contextList[i]; + +#if PLATFORM(X11) + cleanupSharedX11Display(); +#endif +} + + + PassOwnPtr<GLContext> GLContext::createContextForWindow(uint64_t windowHandle, GLContext* sharingContext) { #if USE(GLX) - return GLContextGLX::createContext(windowHandle, sharingContext); + if (OwnPtr<GLContext> glxContext = GLContextGLX::createContext(windowHandle, sharingContext)) + return glxContext.release(); +#endif +#if USE(EGL) + if (OwnPtr<GLContext> eglContext = GLContextEGL::createContext(windowHandle, sharingContext)) + return eglContext.release(); #endif return nullptr; } GLContext::GLContext() { + addActiveContext(this); } -PassOwnPtr<GLContext> GLContext::createOffscreenContext(GLContext* sharing) +PassOwnPtr<GLContext> GLContext::createOffscreenContext(GLContext* sharingContext) { #if USE(GLX) - return GLContextGLX::createContext(0, sharing); + if (OwnPtr<GLContext> glxContext = GLContextGLX::createContext(0, sharingContext)) + return glxContext.release(); +#endif +#if USE(EGL) + if (OwnPtr<GLContext> eglContext = GLContextEGL::createContext(0, sharingContext)) + return eglContext.release(); #endif return nullptr; } @@ -64,6 +150,7 @@ GLContext::~GLContext() { if (this == gCurrentContext) gCurrentContext = 0; + removeActiveContext(this); } bool GLContext::makeContextCurrent() diff --git a/Source/WebCore/platform/graphics/cairo/GLContext.h b/Source/WebCore/platform/graphics/cairo/GLContext.h index c23a46cf1..1a8807222 100644 --- a/Source/WebCore/platform/graphics/cairo/GLContext.h +++ b/Source/WebCore/platform/graphics/cairo/GLContext.h @@ -25,6 +25,10 @@ #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> +#if PLATFORM(X11) +typedef struct _XDisplay Display; +#endif + namespace WebCore { class GLContext { @@ -39,9 +43,19 @@ public: virtual ~GLContext(); virtual bool makeContextCurrent(); virtual void swapBuffers() = 0; + virtual void waitNative() = 0; virtual bool canRenderToDefaultFramebuffer() = 0; virtual IntSize defaultFrameBufferSize() = 0; +#if PLATFORM(X11) + static Display* sharedX11Display(); + static void cleanupSharedX11Display(); +#endif + + static void addActiveContext(GLContext*); + static void removeActiveContext(GLContext*); + static void cleanupActiveContextsAtExit(); + #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 dc12f6c5d..7033fa6da 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp @@ -30,12 +30,10 @@ #if USE(3D_GRAPHICS) -#include "Extensions3DOpenGL.h" #include "GraphicsContext3DPrivate.h" #include "Image.h" #include "ImageSource.h" #include "NotImplemented.h" -#include "OpenGLShims.h" #include "PlatformContextCairo.h" #include "RefPtrCairo.h" #include "ShaderLang.h" @@ -44,6 +42,13 @@ #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> +#if USE(OPENGL_ES_2) +#include "Extensions3DOpenGLES.h" +#else +#include "Extensions3DOpenGL.h" +#include "OpenGLShims.h" +#endif + namespace WebCore { PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) @@ -55,7 +60,9 @@ PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attri static bool initialized = false; static bool success = true; if (!initialized) { +#if !USE(OPENGL_ES_2) success = initializeOpenGLShims(); +#endif initialized = true; } if (!success) @@ -90,26 +97,26 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, H ::glBindTexture(GL_TEXTURE_2D, m_texture); ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ::glBindTexture(GL_TEXTURE_2D, 0); // Create an FBO. - ::glGenFramebuffersEXT(1, &m_fbo); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + ::glGenFramebuffers(1, &m_fbo); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); m_boundFBO = m_fbo; if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) - ::glGenRenderbuffersEXT(1, &m_depthStencilBuffer); + ::glGenRenderbuffers(1, &m_depthStencilBuffer); // Create a multisample FBO. if (m_attrs.antialias) { - ::glGenFramebuffersEXT(1, &m_multisampleFBO); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glGenFramebuffers(1, &m_multisampleFBO); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); m_boundFBO = m_multisampleFBO; - ::glGenRenderbuffersEXT(1, &m_multisampleColorBuffer); + ::glGenRenderbuffers(1, &m_multisampleColorBuffer); if (m_attrs.stencil || m_attrs.depth) - ::glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); + ::glGenRenderbuffers(1, &m_multisampleDepthStencilBuffer); } } @@ -129,8 +136,11 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, H ANGLEResources.MaxDrawBuffers = 1; m_compiler.setResources(ANGLEResources); +#if !USE(OPENGL_ES_2) ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); ::glEnable(GL_POINT_SPRITE); +#endif + ::glClearColor(0, 0, 0, 0); } @@ -142,20 +152,15 @@ GraphicsContext3D::~GraphicsContext3D() makeContextCurrent(); ::glDeleteTextures(1, &m_texture); if (m_attrs.antialias) { - ::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer); + ::glDeleteRenderbuffers(1, &m_multisampleColorBuffer); if (m_attrs.stencil || m_attrs.depth) - ::glDeleteRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); - ::glDeleteFramebuffersEXT(1, &m_multisampleFBO); + ::glDeleteRenderbuffers(1, &m_multisampleDepthStencilBuffer); + ::glDeleteFramebuffers(1, &m_multisampleFBO); } else { if (m_attrs.stencil || m_attrs.depth) - ::glDeleteRenderbuffersEXT(1, &m_depthStencilBuffer); + ::glDeleteRenderbuffers(1, &m_depthStencilBuffer); } - ::glDeleteFramebuffersEXT(1, &m_fbo); -} - -void GraphicsContext3D::releaseShaderCompiler() -{ - notImplemented(); + ::glDeleteFramebuffers(1, &m_fbo); } bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) @@ -258,7 +263,11 @@ PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() bool GraphicsContext3D::isGLES2Compliant() const { +#if USE(OPENGL_ES_2) + return true; +#else return false; +#endif } #if USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp index d88242f96..294169e0e 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp @@ -24,10 +24,16 @@ #include "HostWindow.h" #include "NotImplemented.h" -#include "OpenGLShims.h" #include "PlatformContextCairo.h" #include <wtf/OwnArrayPtr.h> +#if USE(OPENGL_ES_2) +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#else +#include "OpenGLShims.h" +#endif + #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) && USE(TEXTURE_MAPPER_GL) #include <texmap/TextureMapperGL.h> #endif @@ -125,7 +131,7 @@ void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper* textureMapper m_context->makeContextCurrent(); m_context->resolveMultisamplingIfNecessary(); - glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_context->m_boundFBO); + ::glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_context->m_boundFBO); if (previousActiveContext && previousActiveContext != m_glContext) previousActiveContext->makeContextCurrent(); diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 3edbb88aa..89093d58c 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -41,9 +41,9 @@ #include "FloatRect.h" #include "Font.h" #include "GraphicsContextPlatformPrivateCairo.h" -#include "OwnPtrCairo.h" #include "IntRect.h" #include "NotImplemented.h" +#include "OwnPtrCairo.h" #include "Path.h" #include "Pattern.h" #include "PlatformContextCairo.h" diff --git a/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp b/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp index c73dd028e..bebc4a321 100644 --- a/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp @@ -26,8 +26,8 @@ #include "AffineTransform.h" #include "TransformationMatrix.h" -#include "IntRect.h" #include "FloatRect.h" +#include "IntRect.h" #include <cairo.h> diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index a89ae94f5..14142f6cd 100644 --- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -1130,6 +1130,32 @@ bool GraphicsContext::supportsTransparencyLayers() return true; } +static void applyShadowOffsetWorkaroundIfNeeded(const GraphicsContext& context, CGFloat& xOffset, CGFloat& yOffset) +{ +#if !PLATFORM(IOS) + if (context.isAcceleratedContext()) + return; + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 + if (wkCGContextDrawsWithCorrectShadowOffsets(context.platformContext())) + return; +#endif + + // Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated + // to the desired integer. Also see: <rdar://problem/10056277> + static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128); + if (xOffset > 0) + xOffset += extraShadowOffset; + else if (xOffset < 0) + xOffset -= extraShadowOffset; + + if (yOffset > 0) + yOffset += extraShadowOffset; + else if (yOffset < 0) + yOffset -= extraShadowOffset; +#endif +} + void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) @@ -1163,23 +1189,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp blurRadius = min(blurRadius, narrowPrecisionToCGFloat(1000.0)); - -#if !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 - if (!isAcceleratedContext()) { - // Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated - // to the desired integer. Also see: <rdar://problem/10056277> - static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128); - if (xOffset > 0) - xOffset += extraShadowOffset; - else if (xOffset < 0) - xOffset -= extraShadowOffset; - - if (yOffset > 0) - yOffset += extraShadowOffset; - else if (yOffset < 0) - yOffset -= extraShadowOffset; - } -#endif + applyShadowOffsetWorkaroundIfNeeded(*this, xOffset, yOffset); // Check for an invalid color, as this means that the color was not set for the shadow // and we should therefore just use the default shadow color. diff --git a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp index 65bce5232..063efc65c 100644 --- a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp +++ b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp @@ -194,6 +194,18 @@ bool ImageSource::isSizeAvailable() return result; } +static ImageOrientation orientationFromProperties(CFDictionaryRef imageProperties) +{ + ASSERT(imageProperties); + CFNumberRef orientationProperty = (CFNumberRef)CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation); + if (!orientationProperty) + return DefaultImageOrientation; + + int exifValue; + CFNumberGetValue(orientationProperty, kCFNumberIntType, &exifValue); + return ImageOrientation::fromEXIFValue(exifValue); +} + IntSize ImageSource::frameSizeAtIndex(size_t index, RespectImageOrientationEnum shouldRespectOrientation) const { RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata))); @@ -209,7 +221,7 @@ IntSize ImageSource::frameSizeAtIndex(size_t index, RespectImageOrientationEnum if (num) CFNumberGetValue(num, kCFNumberIntType, &h); - if ((shouldRespectOrientation == RespectImageOrientation) && orientationAtIndex(index).usesWidthAsHeight()) + if ((shouldRespectOrientation == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight()) return IntSize(h, w); return IntSize(w, h); @@ -221,13 +233,7 @@ ImageOrientation ImageSource::orientationAtIndex(size_t index) const if (!properties) return DefaultImageOrientation; - CFNumberRef orientationProperty = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyOrientation); - if (!orientationProperty) - return DefaultImageOrientation; - - int exifValue; - CFNumberGetValue(orientationProperty, kCFNumberIntType, &exifValue); - return ImageOrientation::fromEXIFValue(exifValue); + return orientationFromProperties(properties.get()); } IntSize ImageSource::size(RespectImageOrientationEnum shouldRespectOrientation) const diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.cpp index 1250e4e87..b89d995f1 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.cpp +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.cpp @@ -51,6 +51,8 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, , m_canvas(0) , m_context(context) , m_bytesAllocated(0) + , m_didRecordDrawCommand(false) + , m_framesPending(0) , m_next(0) , m_prev(0) { @@ -106,6 +108,16 @@ SkDeferredCanvas* Canvas2DLayerBridge::deferredCanvas() return 0; } +void Canvas2DLayerBridge::limitPendingFrames() +{ + if (m_didRecordDrawCommand) { + m_framesPending++; + m_didRecordDrawCommand = false; + if (m_framesPending > 1) + flush(); + } +} + void Canvas2DLayerBridge::prepareForDraw() { ASSERT(deferredCanvas()); @@ -122,9 +134,20 @@ void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, delta); } +size_t Canvas2DLayerBridge::storageAllocatedForRecording() +{ + return deferredCanvas()->storageAllocatedForRecording(); +} + void Canvas2DLayerBridge::flushedDrawCommands() { - storageAllocatedForRecordingChanged(deferredCanvas()->storageAllocatedForRecording()); + storageAllocatedForRecordingChanged(storageAllocatedForRecording()); + m_framesPending = 0; +} + +void Canvas2DLayerBridge::skippedPendingDrawCommands() +{ + flushedDrawCommands(); } size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree) @@ -140,7 +163,8 @@ size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree) void Canvas2DLayerBridge::flush() { ASSERT(deferredCanvas()); - m_canvas->flush(); + if (deferredCanvas()->hasPendingCommands()) + m_canvas->flush(); } SkCanvas* Canvas2DLayerBridge::skCanvas(SkDevice* device) @@ -196,8 +220,10 @@ void Canvas2DLayerBridge::contextAcquired() { if (m_deferralMode == NonDeferred && !m_useDoubleBuffering) m_layer->willModifyTexture(); - else if (m_deferralMode == Deferred) + else if (m_deferralMode == Deferred) { Canvas2DLayerManager::get().layerDidDraw(this); + m_didRecordDrawCommand = true; + } } unsigned Canvas2DLayerBridge::backBufferTexture() diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.h index 8199159c9..996917493 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.h +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.h @@ -62,11 +62,14 @@ public: virtual void prepareForDraw() OVERRIDE; virtual void storageAllocatedForRecordingChanged(size_t) OVERRIDE; virtual void flushedDrawCommands() OVERRIDE; + virtual void skippedPendingDrawCommands() OVERRIDE; // Methods used by Canvas2DLayerManager virtual size_t freeMemoryIfPossible(size_t); // virtual for mocking virtual void flush(); // virtual for mocking + virtual size_t storageAllocatedForRecording(); // virtual for faking size_t bytesAllocated() const {return m_bytesAllocated;} + void limitPendingFrames(); SkCanvas* skCanvas(SkDevice*); WebKit::WebLayer* layer(); @@ -87,6 +90,8 @@ protected: OwnPtr<WebKit::WebExternalTextureLayer> m_layer; RefPtr<GraphicsContext3D> m_context; size_t m_bytesAllocated; + bool m_didRecordDrawCommand; + int m_framesPending; friend class WTF::DoublyLinkedListNode<Canvas2DLayerBridge>; Canvas2DLayerBridge* m_next; diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.cpp index 7ffadf7a9..7e7adb994 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.cpp +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.cpp @@ -25,8 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Canvas2DLayerManager.h" +#include <public/Platform.h> #include <wtf/StdLibExtras.h> +using WebKit::WebThread; + namespace { enum { DefaultMaxBytesAllocated = 64*1024*1024, @@ -40,6 +43,7 @@ Canvas2DLayerManager::Canvas2DLayerManager() : m_bytesAllocated(0) , m_maxBytesAllocated(DefaultMaxBytesAllocated) , m_targetBytesAllocated(DefaultTargetBytesAllocated) + , m_taskObserverActive(false) { } @@ -47,6 +51,7 @@ Canvas2DLayerManager::~Canvas2DLayerManager() { ASSERT(!m_bytesAllocated); ASSERT(!m_layerList.head()); + ASSERT(!m_taskObserverActive); } void Canvas2DLayerManager::init(size_t maxBytesAllocated, size_t targetBytesAllocated) @@ -62,6 +67,20 @@ Canvas2DLayerManager& Canvas2DLayerManager::get() return manager; } +void Canvas2DLayerManager::willProcessTask() +{ +} + +void Canvas2DLayerManager::didProcessTask() +{ + // Called after the script action for the current frame has been processed. + ASSERT(m_taskObserverActive); + WebKit::Platform::current()->currentThread()->removeTaskObserver(this); + m_taskObserverActive = false; + for (Canvas2DLayerBridge* layer = m_layerList.head(); layer; layer = layer->next()) + layer->limitPendingFrames(); +} + void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer) { if (isInList(layer)) { @@ -70,7 +89,13 @@ void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer) m_layerList.push(layer); // Set as MRU } } else - addLayerToList(layer); + addLayerToList(layer); + + if (!m_taskObserverActive) { + m_taskObserverActive = true; + // Schedule a call to didProcessTask() after completion of the current script task. + WebKit::Platform::current()->currentThread()->addTaskObserver(this); + } } void Canvas2DLayerManager::addLayerToList(Canvas2DLayerBridge* layer) diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.h index 373729b69..55d7ce455 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.h +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.h @@ -26,12 +26,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define Canvas2DLayerManager_h #include "Canvas2DLayerBridge.h" +#include <public/WebThread.h> class Canvas2DLayerManagerTest; namespace WebCore { -class Canvas2DLayerManager { +class Canvas2DLayerManager : public WebKit::WebThread::TaskObserver { public: static Canvas2DLayerManager& get(); void init(size_t maxBytesAllocated, size_t targetBytesAllocated); @@ -48,10 +49,13 @@ private: bool isInList(Canvas2DLayerBridge*); void addLayerToList(Canvas2DLayerBridge*); void removeLayerFromList(Canvas2DLayerBridge*); + virtual void willProcessTask() OVERRIDE; + virtual void didProcessTask() OVERRIDE; size_t m_bytesAllocated; size_t m_maxBytesAllocated; size_t m_targetBytesAllocated; + bool m_taskObserverActive; DoublyLinkedList<Canvas2DLayerBridge> m_layerList; friend class ::Canvas2DLayerManagerTest; // for unit testing diff --git a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm index a10956366..15341ca43 100644 --- a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm +++ b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm @@ -89,17 +89,6 @@ WTF::String hashKeyFromNSFont(NSFont* srcFont) return WTF::String::format("%s %x", [[srcFont fontName] UTF8String], traits); } -ATSFontContainerRef fontContainerRefFromNSFont(NSFont* srcFont) -{ - ATSFontRef fontRef = CTFontGetPlatformFont(toCTFontRef(srcFont), 0); - if (!fontRef) - return kATSFontContainerRefUnspecified; - ATSFontContainerRef fontContainer = kATSFontContainerRefUnspecified; - if (ATSFontGetContainer(fontRef, 0, &fontContainer) != noErr) - return kATSFontContainerRefUnspecified; - return fontContainer; -} - // The only way we can tell that an in-process font has failed to load // is if CTFontCopyGraphicsFont() returns the LastResort font. bool isLastResortFont(CGFontRef cgFont) diff --git a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h index edd6c135c..174056589 100644 --- a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h +++ b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h @@ -137,6 +137,15 @@ public: virtual void pushGroupMarkerEXT(const String&); virtual void popGroupMarkerEXT(void); + // Some helper methods to detect GPU functionality + virtual bool isNVIDIA() { return false; } + virtual bool isAMD() { return false; } + virtual bool isIntel() { return false; } + virtual String vendor() { return ""; } + + virtual bool maySupportMultisampling() { return true; } + virtual bool requiresBuiltInFunctionEmulation() { return false; } + private: // Instances of this class are strictly owned by the GraphicsContext3D implementation and do not // need to be instantiated by any other code. diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp index 01d08645a..eba224a83 100644 --- a/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp @@ -97,20 +97,30 @@ void FontCache::platformInit() { } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { - // FIXME: We do not use fontconfig on Android, so use simple logic for now. - // https://bugs.webkit.org/show_bug.cgi?id=67587 - AtomicString atomicFamily("Arial"); - return getCachedFontData(getCachedFontPlatformData(font.fontDescription(), atomicFamily, DoNotRetain), DoNotRetain); + if (!length) + return 0; + + SkUnichar skiaChar; + if (U16_IS_LEAD(characters[0])) { + ASSERT(length >= 2); + skiaChar = U16_GET_SUPPLEMENTARY(characters[0], characters[1]); + } else + skiaChar = characters[0]; + + SkString skiaFamilyName; + if (!SkGetFallbackFamilyNameForChar(skiaChar, &skiaFamilyName) || skiaFamilyName.isEmpty()) + return 0; + return getCachedFontData(getCachedFontPlatformData(font.fontDescription(), AtomicString(skiaFamilyName.c_str()), DoNotRetain), DoNotRetain); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) { DEFINE_STATIC_LOCAL(const AtomicString, serif, ("Serif")); DEFINE_STATIC_LOCAL(const AtomicString, monospace, ("Monospace")); diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp index 9f8998cda..18e304388 100644 --- a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp @@ -223,10 +223,10 @@ static bool LookupAltName(const String& name, String& altName) return false; static int systemCp = ::GetACP(); - int fontCp = iter->second->codePage; + int fontCp = iter->value->codePage; if ((isAscii && systemCp == fontCp) || (!isAscii && systemCp != fontCp)) { - altName = String(iter->second->name); + altName = String(iter->value->name); return true; } @@ -277,7 +277,7 @@ static bool fontContainsCharacter(const FontPlatformData* fontData, HashMap<const wchar_t*, icu::UnicodeSet*>::iterator it = fontCmapCache->find(family); if (it != fontCmapCache->end()) - return it->second->contains(character); + return it->value->contains(character); HFONT hfont = fontData->hfont(); HWndDC hdc(0); @@ -318,12 +318,12 @@ static bool fontContainsCharacter(const FontPlatformData* fontData, } // Tries the given font and save it |outFontFamilyName| if it succeeds. -SimpleFontData* FontCache::fontDataFromDescriptionAndLogFont(const FontDescription& fontDescription, ShouldRetain shouldRetain, const LOGFONT& font, wchar_t* outFontFamilyName) +PassRefPtr<SimpleFontData> FontCache::fontDataFromDescriptionAndLogFont(const FontDescription& fontDescription, ShouldRetain shouldRetain, const LOGFONT& font, wchar_t* outFontFamilyName) { - SimpleFontData* fontData = getCachedFontData(fontDescription, font.lfFaceName, false, shouldRetain); + RefPtr<SimpleFontData> fontData = getCachedFontData(fontDescription, font.lfFaceName, false, shouldRetain); if (fontData) memcpy(outFontFamilyName, font.lfFaceName, sizeof(font.lfFaceName)); - return fontData; + return fontData.release(); } static LONG toGDIFontWeight(FontWeight fontWeight) @@ -406,7 +406,7 @@ struct GetLastResortFallbackFontProcData { const FontDescription* m_fontDescription; FontCache::ShouldRetain m_shouldRetain; wchar_t* m_fontName; - SimpleFontData* m_fontData; + RefPtr<SimpleFontData> m_fontData; }; static int CALLBACK getLastResortFallbackFontProc(const LOGFONT* logFont, const TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam) @@ -423,7 +423,7 @@ void FontCache::platformInit() // Given the desired base font, this will create a SimpleFontData for a specific // font that can be used to render the given range of characters. -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { // FIXME: Consider passing fontDescription.dominantScript() // to GetFallbackFamily here. @@ -508,12 +508,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) { FontDescription::GenericFamilyType generic = description.genericFamily(); @@ -530,9 +530,9 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc else if (generic == FontDescription::MonospaceFamily) fontStr = courierStr; - SimpleFontData* simpleFont = getCachedFontData(description, fontStr, false, shouldRetain); + RefPtr<SimpleFontData> simpleFont = getCachedFontData(description, fontStr, false, shouldRetain); if (simpleFont) - return simpleFont; + return simpleFont.release(); // Fall back to system fonts as Win Safari does because this function must // return a valid font. Once we find a valid system font, we save its name @@ -546,7 +546,7 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc LOGFONT defaultGUILogFont; GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont); if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, defaultGUILogFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); } // Fall back to Non-client metrics fonts. @@ -554,15 +554,15 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc nonClientMetrics.cbSize = sizeof(nonClientMetrics); if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) { if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfMessageFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfMenuFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfStatusFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfCaptionFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfSmCaptionFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); } // Fall back to all the fonts installed in this PC. When a font has a @@ -576,7 +576,7 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc EnumFontFamilies(dc, 0, getLastResortFallbackFontProc, reinterpret_cast<LPARAM>(&procData)); if (procData.m_fontData) - return procData.m_fontData; + return procData.m_fontData.release(); } ASSERT_NOT_REACHED(); diff --git a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp index df941cb90..10f1fd078 100644 --- a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp @@ -415,7 +415,7 @@ bool getDerivedFontData(const UChar* family, // check it against what we actually want (as is done in // FontCacheWin.cpp) FontDataCache::AddResult entry = fontDataCache.add(fontKey, FontData()); - derived = &entry.iterator->second; + derived = &entry.iterator->value; derived->hfont = CreateFontIndirect(logfont); // GetAscent may return kUndefinedAscent, but we still want to // cache it so that we won't have to call CreateFontIndirect once @@ -423,7 +423,7 @@ bool getDerivedFontData(const UChar* family, derived->ascent = getAscent(derived->hfont); derived->spaceGlyph = getSpaceGlyph(derived->hfont); } else { - derived = &iter->second; + derived = &iter->value; // Last time, GetAscent failed so that only HFONT was // cached. Try once more assuming that TryPreloadFont // was called by a caller between calls. diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index 47c03cbe9..075749e9a 100644 --- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -49,6 +49,7 @@ #include "FloatConversion.h" #include "FloatRect.h" #include "GraphicsContext.h" +#include "GraphicsLayerFactory.h" #include "Image.h" #include "NativeImageSkia.h" #include "PlatformContextSkia.h" @@ -77,6 +78,14 @@ using namespace WebKit; namespace WebCore { +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) +{ + if (!factory) + return adoptPtr(new GraphicsLayerChromium(client)); + + return factory->createGraphicsLayer(client); +} + PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return adoptPtr(new GraphicsLayerChromium(client)); @@ -459,7 +468,8 @@ void GraphicsLayerChromium::setContentsRect(const IntRect& rect) void GraphicsLayerChromium::setContentsToImage(Image* image) { bool childrenChanged = false; - if (image) { + NativeImageSkia* nativeImage = image ? image->nativeImageForCurrentFrame() : 0; + if (nativeImage) { if (m_contentsLayerPurpose != ContentsLayerForImage) { m_imageLayer = adoptPtr(Platform::current()->compositorSupport()->createImageLayer()); registerContentsLayer(m_imageLayer->layer()); @@ -468,7 +478,6 @@ void GraphicsLayerChromium::setContentsToImage(Image* image) m_contentsLayerPurpose = ContentsLayerForImage; childrenChanged = true; } - NativeImageSkia* nativeImage = image->nativeImageForCurrentFrame(); m_imageLayer->setBitmap(nativeImage->bitmap()); m_imageLayer->layer()->setOpaque(image->isBitmapImage() && !image->currentFrameHasAlpha()); updateContentsRect(); diff --git a/Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h b/Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h index 6d49c5578..160eb0faa 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h +++ b/Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h @@ -42,6 +42,8 @@ class ImageBufferData { public: ImageBufferData(const IntSize&); + void reportMemoryUsage(MemoryObjectInfo*) const; + OwnPtr<SkCanvas> m_canvas; PlatformContextSkia m_platformContext; #if USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp index 579fa2860..8510dfa52 100644 --- a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp @@ -109,34 +109,34 @@ void SimpleFontData::platformDestroy() { } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { LOGFONT winFont; GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont); float scaledSize = scaleFactor * fontDescription.computedSize(); winFont.lfHeight = -lroundf(scaledSize); HFONT hfont = CreateFontIndirect(&winFont); - return adoptPtr(new SimpleFontData(FontPlatformData(hfont, scaledSize, m_platformData.orientation()), isCustomFont(), false)); + return SimpleFontData::create(FontPlatformData(hfont, scaledSize, m_platformData.orientation()), isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const diff --git a/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp b/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp index bd30a978d..1d6d3d0c2 100644 --- a/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp +++ b/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp @@ -32,8 +32,7 @@ #include <stdlib.h> #include <string.h> -// For htons/ntohs -#include <arpa/inet.h> +#include <wtf/ByteOrder.h> // Buffer helper class // diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp index abfbd47e6..7df1ee92d 100644 --- a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp +++ b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp @@ -56,11 +56,6 @@ 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(); diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp b/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp index eda14d037..104b7982b 100644 --- a/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp +++ b/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp @@ -28,11 +28,20 @@ #if USE(ACCELERATED_COMPOSITING) #include "GraphicsLayerClutter.h" +#include "GraphicsLayerFactory.h" #include "NotImplemented.h" namespace WebCore { +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) +{ + if (!factory) + return adoptPtr(new GraphicsLayerClutter(client)); + + return factory->createGraphicsLayer(client); +} + PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return adoptPtr(new GraphicsLayerClutter(client)); diff --git a/Source/WebCore/platform/graphics/efl/CairoUtilitiesEfl.cpp b/Source/WebCore/platform/graphics/efl/CairoUtilitiesEfl.cpp new file mode 100644 index 000000000..d7232413e --- /dev/null +++ b/Source/WebCore/platform/graphics/efl/CairoUtilitiesEfl.cpp @@ -0,0 +1,109 @@ +/* + Copyright (C) 2009-2010 ProFUSION embedded systems + Copyright (C) 2009-2010 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 "CairoUtilitiesEfl.h" + +#include "RefPtrCairo.h" + +namespace WebCore { + +PassRefPtr<Evas_Object> evasObjectFromCairoImageSurface(Evas* canvas, cairo_surface_t* surface) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(surface, 0); + + cairo_status_t status = cairo_surface_status(surface); + if (status != CAIRO_STATUS_SUCCESS) { + fprintf(stderr, "cairo surface is invalid: %s", cairo_status_to_string(status)); + return 0; + } + + cairo_surface_type_t type = cairo_surface_get_type(surface); + if (type != CAIRO_SURFACE_TYPE_IMAGE) { + fprintf(stderr, "unknown surface type %d, required %d (CAIRO_SURFACE_TYPE_IMAGE).", + type, CAIRO_SURFACE_TYPE_IMAGE); + return 0; + } + + cairo_format_t format = cairo_image_surface_get_format(surface); + if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24) { + fprintf(stderr, "unknown surface format %d, expected %d or %d.", + format, CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24); + return 0; + } + + int width = cairo_image_surface_get_width(surface); + int height = cairo_image_surface_get_height(surface); + int stride = cairo_image_surface_get_stride(surface); + if (width <= 0 || height <= 0 || stride <= 0) { + fprintf(stderr, "invalid image size %dx%d, stride=%d", width, height, stride); + return 0; + } + + void* data = cairo_image_surface_get_data(surface); + if (!data) { + fprintf(stderr, "could not get source data."); + return 0; + } + + RefPtr<Evas_Object> image = adoptRef(evas_object_image_filled_add(canvas)); + if (!image) { + fprintf(stderr, "could not add image to canvas."); + return 0; + } + + evas_object_image_colorspace_set(image.get(), EVAS_COLORSPACE_ARGB8888); + evas_object_image_size_set(image.get(), width, height); + evas_object_image_alpha_set(image.get(), format == CAIRO_FORMAT_ARGB32); + + if (evas_object_image_stride_get(image.get()) != stride) { + fprintf(stderr, "evas' stride %d diverges from cairo's %d.", + evas_object_image_stride_get(image.get()), stride); + return 0; + } + + evas_object_image_data_copy_set(image.get(), data); + + return image.release(); +} + +PassRefPtr<cairo_surface_t> createSurfaceForBackingStore(Ecore_Evas* ee) +{ + ASSERT(ee); + + int width; + int height; + ecore_evas_geometry_get(ee, 0, 0, &width, &height); + ASSERT(width > 0 && height > 0); + + unsigned char* buffer = static_cast<unsigned char*>(const_cast<void*>(ecore_evas_buffer_pixels_get(ee))); + RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32, width, height, width * 4)); + + cairo_status_t status = cairo_surface_status(surface.get()); + if (status != CAIRO_STATUS_SUCCESS) { + EINA_LOG_ERR("Could not create cairo surface: %s", cairo_status_to_string(status)); + return 0; + } + + return surface; +} + +} diff --git a/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.h b/Source/WebCore/platform/graphics/efl/CairoUtilitiesEfl.h index d03fb1b75..a5cd2e2fb 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.h +++ b/Source/WebCore/platform/graphics/efl/CairoUtilitiesEfl.h @@ -1,5 +1,6 @@ /* - Copyright (C) 2009-2011 Samsung Electronics + Copyright (C) 2009-2010 ProFUSION embedded systems + Copyright (C) 2009-2010 Samsung Electronics This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -17,26 +18,20 @@ Boston, MA 02110-1301, USA. */ -#ifndef GraphicsLayerEfl_h -#define GraphicsLayerEfl_h +#ifndef CairoUtilitiesEfl_h +#define CairoUtilitiesEfl_h -#if USE(ACCELERATED_COMPOSITING) - -#include "GraphicsLayer.h" +#include <Ecore_Evas.h> +#include <Evas.h> +#include <cairo.h> +#include <wtf/PassRefPtr.h> +#include <wtf/efl/RefPtrEfl.h> namespace WebCore { -class GraphicsLayerEfl : public GraphicsLayer { -public: - GraphicsLayerEfl(GraphicsLayerClient*); - virtual ~GraphicsLayerEfl(); - - virtual void setNeedsDisplay(); - virtual void setNeedsDisplayInRect(const FloatRect&); -}; - -} // namespace WebCore +PassRefPtr<Evas_Object> evasObjectFromCairoImageSurface(Evas* canvas, cairo_surface_t*); +PassRefPtr<cairo_surface_t> createSurfaceForBackingStore(Ecore_Evas* ee); -#endif // USE(ACCELERATED_COMPOSITING) +} -#endif // GraphicsLayerEfl_h +#endif // CairoUtilitiesEfl_h diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp index 721d7c7be..6f1d4ca15 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp @@ -18,33 +18,134 @@ */ #include "config.h" +#include "GraphicsContext3D.h" #if USE(3D_GRAPHICS) || USE(ACCELERATED_COMPOSITING) #include "GraphicsContext3DPrivate.h" - #include "ImageData.h" #include "NotImplemented.h" +#include "OpenGLShims.h" +#include "PlatformContextCairo.h" +#include <GL/glx.h> + +#if USE(OPENGL_ES_2) +#include "Extensions3DOpenGLES.h" +#else +#include "Extensions3DOpenGL.h" +#endif namespace WebCore { PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, RenderStyle renderStyle) { - bool renderDirectlyToEvasGLObject = (renderStyle == RenderDirectlyToHostWindow); - - OwnPtr<GraphicsContext3DPrivate> internal = GraphicsContext3DPrivate::create(attrs, hostWindow, renderDirectlyToEvasGLObject); - if (!internal) - return 0; - RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attrs, hostWindow, renderStyle)); - context->m_private = internal.release(); - return context.release(); + return context->m_private ? context.release() : 0; } GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) : m_currentWidth(0) , m_currentHeight(0) -{ + , m_compiler(isGLES2Compliant() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT) + , m_attrs(attrs) + , m_texture(0) + , m_compositorTexture(0) + , m_fbo(0) +#if USE(OPENGL_ES_2) + , m_depthBuffer(0) + , m_stencilBuffer(0) +#endif + , m_depthStencilBuffer(0) + , m_layerComposited(false) + , m_internalColorFormat(0) + , m_boundFBO(0) + , m_activeTexture(GL_TEXTURE0) + , m_boundTexture0(0) + , m_multisampleFBO(0) + , m_multisampleDepthStencilBuffer(0) + , m_multisampleColorBuffer(0) + , m_private(adoptPtr(new GraphicsContext3DPrivate(this, hostWindow, renderStyle))) +{ + validateAttributes(); + + if (!m_private) + return; + + static bool initializedShims = false; + static bool success = true; + if (!initializedShims) { + success = initializeOpenGLShims(); + initializedShims = true; + } + if (!success) { + m_private = nullptr; + return; + } + + if (renderStyle == RenderToCurrentGLContext) { + // Evas doesn't allow including gl headers and Evas_GL headers at the same time, + // so we need to query the current gl context/surface here instead of in GraphicsContext3DPrivate. + void* currentContext = (void*)glXGetCurrentContext(); + void* currentSurface = (void*)glXGetCurrentDrawable(); + m_private->setCurrentGLContext(currentContext, currentSurface); + } + + if (renderStyle == RenderOffscreen) { + // Create buffers for the canvas FBO. + glGenFramebuffers(/* count */ 1, &m_fbo); + + // Create a texture to render into. + glGenTextures(1, &m_texture); + glBindTexture(GraphicsContext3D::TEXTURE_2D, m_texture); + glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + glBindTexture(GraphicsContext3D::TEXTURE_2D, 0); + + // Create a multisample FBO. + if (m_attrs.antialias) { + glGenFramebuffers(1, &m_multisampleFBO); + glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); + m_boundFBO = m_multisampleFBO; + glGenRenderbuffers(1, &m_multisampleColorBuffer); + if (m_attrs.stencil || m_attrs.depth) + glGenRenderbuffers(1, &m_multisampleDepthStencilBuffer); + } else { + // Bind canvas FBO. + glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); + m_boundFBO = m_fbo; +#if USE(OPENGL_ES_2) + if (m_attrs.depth) + glGenRenderbuffers(1, &m_depthBuffer); + if (m_context->m_attrs.stencil) + glGenRenderbuffers(1, &m_stencilBuffer); +#endif + if (m_attrs.stencil || m_attrs.depth) + glGenRenderbuffers(1, &m_depthStencilBuffer); + } + } + + // ANGLE initialization. + ShBuiltInResources ANGLEResources; + ShInitBuiltInResources(&ANGLEResources); + + getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs); + getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors); + getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors); + getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors); + + // Always set to 1 for OpenGL ES. + ANGLEResources.MaxDrawBuffers = 1; + m_compiler.setResources(ANGLEResources); + +#if !USE(OPENGL_ES_2) + glEnable(GL_POINT_SPRITE); + glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); +#endif } GraphicsContext3D::~GraphicsContext3D() @@ -59,768 +160,74 @@ PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() #if USE(ACCELERATED_COMPOSITING) PlatformLayer* GraphicsContext3D::platformLayer() const { +#if USE(TEXTURE_MAPPER_GL) + return m_private.get(); +#else notImplemented(); return 0; +#endif } #endif bool GraphicsContext3D::makeContextCurrent() { - return m_private->makeContextCurrent(); -} - -bool GraphicsContext3D::isGLES2Compliant() const -{ - return m_private->isGLES2Compliant(); -} - -void GraphicsContext3D::activeTexture(GC3Denum texture) -{ - m_private->activeTexture(texture); -} - -void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader) -{ - m_private->attachShader(program, shader); -} - -void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name) -{ - m_private->bindAttribLocation(program, index, name); -} - -void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer) -{ - m_private->bindBuffer(target, buffer); -} - -void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer) -{ - m_private->bindFramebuffer(target, buffer); -} - -void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer) -{ - m_private->bindRenderbuffer(target, renderbuffer); -} - -void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture) -{ - m_private->bindTexture(target, texture); -} - -void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) -{ - m_private->blendColor(red, green, blue, alpha); -} - -void GraphicsContext3D::blendEquation(GC3Denum mode) -{ - m_private->blendEquation(mode); -} - -void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) -{ - m_private->blendEquationSeparate(modeRGB, modeAlpha); -} - -void GraphicsContext3D::blendFunc(GC3Denum srcFactor, GC3Denum dstFactor) -{ - m_private->blendFunc(srcFactor, dstFactor); -} - -void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) -{ - m_private->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); -} - -void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage) -{ - m_private->bufferData(target, size, 0, usage); -} - -void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage) -{ - m_private->bufferData(target, size, data, usage); -} - -void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data) -{ - m_private->bufferSubData(target, offset, size, data); -} - -GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target) -{ - return m_private->checkFramebufferStatus(target); -} - -void GraphicsContext3D::clear(GC3Dbitfield mask) -{ - m_private->clear(mask); -} - -void GraphicsContext3D::clearColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) -{ - m_private->clearColor(red, green, blue, alpha); -} - -void GraphicsContext3D::clearDepth(GC3Dclampf depth) -{ - m_private->clearDepth(depth); -} - -void GraphicsContext3D::clearStencil(GC3Dint clearValue) -{ - m_private->clearStencil(clearValue); -} - -void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) -{ - m_private->colorMask(red, green, blue, alpha); -} - -void GraphicsContext3D::compileShader(Platform3DObject shader) -{ - m_private->compileShader(shader); -} - -void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) -{ - m_private->copyTexImage2D(target, level, internalformat, x, y, width, height, border); -} - -void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - m_private->copyTexSubImage2D(target, level, xOffset, yOffset, x, y, width, height); -} - -void GraphicsContext3D::cullFace(GC3Denum mode) -{ - m_private->cullFace(mode); -} - -void GraphicsContext3D::depthFunc(GC3Denum func) -{ - m_private->depthFunc(func); -} - -void GraphicsContext3D::depthMask(GC3Dboolean flag) -{ - m_private->depthMask(flag); -} - -void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar) -{ - m_private->depthRange(zNear, zFar); -} - -void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader) -{ - m_private->detachShader(program, shader); -} - -void GraphicsContext3D::disable(GC3Denum cap) -{ - m_private->disable(cap); -} - -void GraphicsContext3D::disableVertexAttribArray(GC3Duint index) -{ - m_private->disableVertexAttribArray(index); -} - -void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count) -{ - m_private->drawArrays(mode, first, count); -} - -void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset) -{ - m_private->drawElements(mode, count, type, offset); -} - -void GraphicsContext3D::enable(GC3Denum cap) -{ - m_private->enable(cap); -} - -void GraphicsContext3D::enableVertexAttribArray(GC3Duint index) -{ - m_private->enableVertexAttribArray(index); -} - -void GraphicsContext3D::finish() -{ - m_private->finish(); -} - -void GraphicsContext3D::flush() -{ - m_private->flush(); -} - -void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbufferTarget, Platform3DObject buffer) -{ - m_private->framebufferRenderbuffer(target, attachment, renderbufferTarget, buffer); -} - -void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum texTarget, Platform3DObject texture, GC3Dint level) -{ - m_private->framebufferTexture2D(target, attachment, texTarget, texture, level); -} - -void GraphicsContext3D::frontFace(GC3Denum mode) -{ - m_private->frontFace(mode); -} - -void GraphicsContext3D::generateMipmap(GC3Denum target) -{ - m_private->generateMipmap(target); -} - -bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - return m_private->getActiveAttrib(program, index, info); -} - -bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - return m_private->getActiveUniform(program, index, info); -} - -void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders) -{ - m_private->getAttachedShaders(program, maxCount, count, shaders); -} - -int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name) -{ - return m_private->getAttribLocation(program, name); -} - -void GraphicsContext3D::getBooleanv(GC3Denum paramName, GC3Dboolean* value) -{ - m_private->getBooleanv(paramName, value); -} - -void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - m_private->getBufferParameteriv(target, paramName, value); -} - -GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() -{ - return m_private->getContextAttributes(); -} - -GC3Denum GraphicsContext3D::getError() -{ - return m_private->getError(); -} - -void GraphicsContext3D::getFloatv(GC3Denum paramName, GC3Dfloat* value) -{ - m_private->getFloatv(paramName, value); -} - -void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum paramName, GC3Dint* value) -{ - m_private->getFramebufferAttachmentParameteriv(target, attachment, paramName, value); -} - -void GraphicsContext3D::getIntegerv(GC3Denum paramName, GC3Dint* value) -{ - m_private->getIntegerv(paramName, value); -} - -void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum paramName, GC3Dint* value) -{ - m_private->getProgramiv(program, paramName, value); -} - -String GraphicsContext3D::getProgramInfoLog(Platform3DObject program) -{ - return m_private->getProgramInfoLog(program); -} - -void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - m_private->getRenderbufferParameteriv(target, paramName, value); -} - -void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum paramName, GC3Dint* value) -{ - m_private->getShaderiv(shader, paramName, value); -} - -String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader) -{ - return m_private->getShaderInfoLog(shader); -} - -String GraphicsContext3D::getShaderSource(Platform3DObject shader) -{ - return m_private->getShaderSource(shader); -} - -String GraphicsContext3D::getString(GC3Denum name) -{ - return m_private->getString(name); -} - -void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum paramName, GC3Dfloat* value) -{ - m_private->getTexParameterfv(target, paramName, value); -} - -void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - m_private->getTexParameteriv(target, paramName, value); -} - -void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value) -{ - m_private->getUniformfv(program, location, value); -} - -void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value) -{ - m_private->getUniformiv(program, location, value); -} - -GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name) -{ - return m_private->getUniformLocation(program, name); -} - -void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum paramName, GC3Dfloat* value) -{ - m_private->getVertexAttribfv(index, paramName, value); -} - -void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum paramName, GC3Dint* value) -{ - m_private->getVertexAttribiv(index, paramName, value); -} - -long GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum paramName) -{ - return m_private->getVertexAttribOffset(index, paramName); -} - -void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode) -{ - m_private->hint(target, mode); -} - -GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject obj) -{ - return m_private->isBuffer(obj); -} - -GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap) -{ - return m_private->isEnabled(cap); -} - -GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject obj) -{ - return m_private->isFramebuffer(obj); -} - -GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject obj) -{ - return m_private->isProgram(obj); -} - -GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject obj) -{ - return m_private->isRenderbuffer(obj); -} - -GC3Dboolean GraphicsContext3D::isShader(Platform3DObject obj) -{ - return m_private->isShader(obj); -} - -GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject obj) -{ - return m_private->isTexture(obj); -} - -void GraphicsContext3D::lineWidth(GC3Dfloat width) -{ - m_private->lineWidth(width); -} - -void GraphicsContext3D::linkProgram(Platform3DObject program) -{ - m_private->linkProgram(program); -} - -void GraphicsContext3D::pixelStorei(GC3Denum paramName, GC3Dint param) -{ - m_private->pixelStorei(paramName, param); -} - -void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units) -{ - m_private->polygonOffset(factor, units); -} - -void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) -{ - m_private->readPixels(x, y, width, height, format, type, data); -} - -void GraphicsContext3D::releaseShaderCompiler() -{ - notImplemented(); -} - -void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) -{ - m_private->renderbufferStorage(target, internalformat, width, height); -} - -void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert) -{ - m_private->sampleCoverage(value, invert); -} - -void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - m_private->scissor(x, y, width, height); -} - -void GraphicsContext3D::shaderSource(Platform3DObject program, const String& string) -{ - m_private->shaderSource(program, string); -} - -void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - m_private->stencilFunc(func, ref, mask); -} - -void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - m_private->stencilFuncSeparate(face, func, ref, mask); -} - -void GraphicsContext3D::stencilMask(GC3Duint mask) -{ - m_private->stencilMask(mask); -} - -void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask) -{ - m_private->stencilMaskSeparate(face, mask); -} - -void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - m_private->stencilOp(fail, zfail, zpass); -} - -void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - m_private->stencilOpSeparate(face, fail, zfail, zpass); -} - -bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) -{ - return m_private->texImage2D(target, level, internalformat, width, height, border, format, type, pixels); -} - -void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum paramName, GC3Dfloat param) -{ - m_private->texParameterf(target, paramName, param); -} - -void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum paramName, GC3Dint param) -{ - m_private->texParameteri(target, paramName, param); -} - -void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels) -{ - m_private->texSubImage2D(target, level, xOffset, yOffset, width, height, format, type, pixels); -} - -void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat x) -{ - m_private->uniform1f(location, x); -} - -void GraphicsContext3D::uniform1fv(GC3Dint location, GGC3Dsizei size, C3Dfloat* v) -{ - m_private->uniform1fv(location, size, v); -} - -void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint x) -{ - m_private->uniform1i(location, x); -} - -void GraphicsContext3D::uniform1iv(GC3Dint location, GGC3Dsizei size, C3Dint* v) -{ - m_private->uniform1iv(location, size, v); -} - -void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat x, float y) -{ - m_private->uniform2f(location, x, y); -} - -void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* v) -{ - m_private->uniform2fv(location, size, v); -} - -void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint x, GC3Dint y) -{ - m_private->uniform2i(location, x, y); -} - -void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dsizei size, GC3Dint* v) -{ - m_private->uniform2iv(location, size, v); -} - -void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - m_private->uniform3f(location, x, y, z); -} - -void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* v) -{ - m_private->uniform3fv(location, size, v); -} - -void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z) -{ - m_private->uniform3i(location, x, y, z); -} - -void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dsizei size, GC3Dint* v) -{ - m_private->uniform3iv(location, size, v); -} - -void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - m_private->uniform4f(location, x, y, z, w); -} - -void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* v) -{ - m_private->uniform4fv(location, size, v); -} - -void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w) -{ - m_private->uniform4i(location, x, y, z, w); -} - -void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dsizei size, GC3Dint* v) -{ - m_private->uniform4iv(location, size, v); -} - -void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - m_private->uniformMatrix2fv(location, size, transpose, value); -} - -void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - m_private->uniformMatrix3fv(location, size, transpose, value); -} - -void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - m_private->uniformMatrix4fv(location, size, transpose, value); -} - -void GraphicsContext3D::useProgram(Platform3DObject program) -{ - m_private->useProgram(program); -} - -void GraphicsContext3D::validateProgram(Platform3DObject program) -{ - m_private->validateProgram(program); -} - -void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat x) -{ - m_private->vertexAttrib1f(index, x); -} - -void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* values) -{ - m_private->vertexAttrib1fv(index, values); -} - -void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y) -{ - m_private->vertexAttrib2f(index, x, y); -} + if (!m_private) + return false; -void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* values) -{ - m_private->vertexAttrib2fv(index, values); -} - -void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - m_private->vertexAttrib3f(index, x, y, z); -} - -void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* values) -{ - m_private->vertexAttrib3fv(index, values); -} - -void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - m_private->vertexAttrib4f(index, x, y, z, w); -} + if (m_renderStyle == RenderToCurrentGLContext) + return true; -void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* values) -{ - m_private->vertexAttrib4fv(index, values); -} - -void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset) -{ - m_private->vertexAttribPointer(index, size, type, normalized, stride, offset); -} - -void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - m_private->viewport(x, y, width, height); -} - -void GraphicsContext3D::reshape(int width, int height) -{ - notImplemented(); -} - -void GraphicsContext3D::markContextChanged() -{ - notImplemented(); -} - -void GraphicsContext3D::markLayerComposited() -{ - notImplemented(); + return m_private->makeContextCurrent(); } -bool GraphicsContext3D::layerComposited() const +bool GraphicsContext3D::isGLES2Compliant() const { - notImplemented(); +#if USE(OPENGL_ES_2) + return true; +#else return false; +#endif } -void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer*, DrawingBuffer* drawingBuffer) +void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>) { notImplemented(); } -PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer* drawingBuffer) +void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>) { notImplemented(); - return 0; -} - -bool GraphicsContext3D::paintCompositedResultsToCanvas(ImageBuffer*) -{ - return false; -} - -Platform3DObject GraphicsContext3D::createBuffer() -{ - return m_private->createBuffer(); -} - -Platform3DObject GraphicsContext3D::createFramebuffer() -{ - return m_private->createFramebuffer(); -} - -Platform3DObject GraphicsContext3D::createProgram() -{ - return m_private->createProgram(); -} - -Platform3DObject GraphicsContext3D::createRenderbuffer() -{ - return m_private->createRenderbuffer(); -} - -Platform3DObject GraphicsContext3D::createShader(GC3Denum type) -{ - return m_private->createShader(type); -} - -Platform3DObject GraphicsContext3D::createTexture() -{ - return m_private->createTexture(); } -void GraphicsContext3D::deleteBuffer(Platform3DObject buffer) +void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context) { - m_private->deleteBuffer(buffer); -} + if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context) + return; -void GraphicsContext3D::deleteFramebuffer(Platform3DObject buffer) -{ - m_private->deleteFramebuffer(buffer); -} + cairo_t* cr = context->cr(); + context->save(); -void GraphicsContext3D::deleteProgram(Platform3DObject program) -{ - m_private->deleteProgram(program); -} + RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data( + const_cast<unsigned char*>(imagePixels), CAIRO_FORMAT_ARGB32, imageWidth, imageHeight, imageWidth * 4)); -void GraphicsContext3D::deleteRenderbuffer(Platform3DObject buffer) -{ - m_private->deleteRenderbuffer(buffer); -} + // OpenGL keeps the pixels stored bottom up, so we need to flip the image here. + cairo_translate(cr, 0, imageHeight); + cairo_scale(cr, 1, -1); -void GraphicsContext3D::deleteShader(Platform3DObject shader) -{ - m_private->deleteShader(shader); -} + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface(cr, imageSurface.get(), 0, 0); + cairo_rectangle(cr, 0, 0, canvasWidth, -canvasHeight); -void GraphicsContext3D::deleteTexture(Platform3DObject texture) -{ - m_private->deleteTexture(texture); -} - -void GraphicsContext3D::synthesizeGLError(GC3Denum error) -{ - m_private->synthesizeGLError(error); + cairo_fill(cr); + context->restore(); } -Extensions3D* GraphicsContext3D::getExtensions() -{ - return m_private->getExtensions(); -} - -IntSize GraphicsContext3D::getInternalFramebufferSize() const -{ - notImplemented(); - return IntSize(); -} - -void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>) +#if USE(GRAPHICS_SURFACE) +void GraphicsContext3D::createGraphicsSurfaces(const IntSize& size) { notImplemented(); } +#endif bool GraphicsContext3D::getImageData(Image* image, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) @@ -829,32 +236,6 @@ bool GraphicsContext3D::getImageData(Image* image, GC3Denum format, GC3Denum typ return false; } -void GraphicsContext3D::validateAttributes() -{ - notImplemented(); -} - -void GraphicsContext3D::readRenderingResults(unsigned char* pixels, int pixelsSize) -{ - notImplemented(); -} - -bool GraphicsContext3D::reshapeFBOs(const IntSize&) -{ - notImplemented(); -} - -void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect&) -{ - notImplemented(); -} - -bool GraphicsContext3D::isResourceSafe() -{ - notImplemented(); - return false; -} - } // namespace WebCore #endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp index 78e6fb12a..68bd0d57b 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp @@ -20,93 +20,90 @@ #include "config.h" #if USE(3D_GRAPHICS) || USE(ACCELERATED_COMPOSITING) - #include "GraphicsContext3DPrivate.h" +#include "GraphicsContext.h" #include "HostWindow.h" #include "NotImplemented.h" -#include "PageClientEfl.h" - +#include <Ecore_Evas.h> +#include <Evas_GL.h> #include <wtf/OwnArrayPtr.h> #include <wtf/text/CString.h> namespace WebCore { -PassOwnPtr<GraphicsContext3DPrivate> GraphicsContext3DPrivate::create(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, bool renderDirectlyToHostWindow) -{ - OwnPtr<GraphicsContext3DPrivate> internal = adoptPtr(new GraphicsContext3DPrivate()); - - if (!internal->initialize(attributes, hostWindow, renderDirectlyToHostWindow)) - return nullptr; - - return internal.release(); -} - -GraphicsContext3DPrivate::GraphicsContext3DPrivate() - : m_boundFBO(0) - , m_boundTexture(0) - , m_boundArrayBuffer(0) +GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) + : m_context(context) + , m_hostWindow(hostWindow) , m_evasGL(0) - , m_context(0) - , m_surface(0) + , m_evasGLContext(0) + , m_evasGLSurface(0) + , m_glContext(0) + , m_glSurface(0) , m_api(0) + , m_renderStyle(renderStyle) { -} - -GraphicsContext3DPrivate::~GraphicsContext3DPrivate() -{ - if (!m_evasGL) + if (renderStyle == GraphicsContext3D::RenderToCurrentGLContext) return; - if (m_surface) - evas_gl_surface_destroy(m_evasGL, m_surface); - - if (m_context) - evas_gl_context_destroy(m_evasGL, m_context); - - evas_gl_free(m_evasGL); -} + if (m_hostWindow && m_hostWindow->platformPageClient()) { + // FIXME: Implement this code path for WebKit1. + // Get Evas object from platformPageClient and set EvasGL related members. + return; + } -bool GraphicsContext3DPrivate::initialize(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, bool renderDirectlyToHostWindow) -{ - PageClientEfl* pageClient = static_cast<PageClientEfl*>(hostWindow->platformPageClient()); + // For WebKit2, we need to create a dummy ecoreEvas object for the WebProcess in order to use EvasGL APIs. +#ifdef HAVE_ECORE_X + ecore_evas_init(); + m_ecoreEvas = adoptPtr(ecore_evas_gl_x11_new(0, 0, 0, 0, 1, 1)); + if (!m_ecoreEvas) + return; +#else + return; +#endif - Evas* evas = evas_object_evas_get(pageClient->view()); + Evas* evas = ecore_evas_get(m_ecoreEvas.get()); + if (!evas) + return; // Create a new Evas_GL object for gl rendering on efl. m_evasGL = evas_gl_new(evas); if (!m_evasGL) - return false; + return; // Get the API for rendering using OpenGL. // This returns a structure that contains all the OpenGL functions we can use to render in Evas m_api = evas_gl_api_get(m_evasGL); if (!m_api) - return false; - - Evas_GL_Context* shareContext = 0; - -#if USE(ACCELERATED_COMPOSITING) - // GC3D with RenderOffscreen style for WebGL has to be shared with AC's context when AC is enabled. - if (!renderDirectlyToHostWindow) { - GraphicsContext3D* context = pageClient->acceleratedCompositingContext(); - if (context) - shareContext = static_cast<Evas_GL_Context*>(context->platformGraphicsContext3D()); - } -#endif + return; // Create a context - m_context = evas_gl_context_create(m_evasGL, shareContext); - if (!m_context) - return false; + m_evasGLContext = evas_gl_context_create(m_evasGL, 0); + if (!m_evasGLContext) + return; // Create a surface - if (!createSurface(pageClient, renderDirectlyToHostWindow)) - return false; + if (!createSurface(0, renderStyle == GraphicsContext3D::RenderDirectlyToHostWindow)) + return; + + makeContextCurrent(); +} + +GraphicsContext3DPrivate::~GraphicsContext3DPrivate() +{ + if (!m_evasGL) + return; + + if (m_evasGLSurface) + evas_gl_surface_destroy(m_evasGL, m_evasGLSurface); - return makeContextCurrent(); + if (m_evasGLContext) + evas_gl_context_destroy(m_evasGL, m_evasGLContext); + + evas_gl_free(m_evasGL); } + bool GraphicsContext3DPrivate::createSurface(PageClientEfl* pageClient, bool renderDirectlyToHostWindow) { // If RenderStyle is RenderOffscreen, we will be rendering to a FBO, @@ -117,8 +114,11 @@ bool GraphicsContext3DPrivate::createSurface(PageClientEfl* pageClient, bool ren int height = 1; // But, in case of RenderDirectlyToHostWindow, we have to render to a render target surface with the same size as our webView. - if (renderDirectlyToHostWindow) - evas_object_geometry_get(pageClient->view(), &x, &y, &width, &height); + if (renderDirectlyToHostWindow) { + if (!pageClient) + return false; + // FIXME: Get geometry of webView and set size of target surface. + } Evas_GL_Config config = { EVAS_GL_RGBA_8888, @@ -128,1002 +128,48 @@ bool GraphicsContext3DPrivate::createSurface(PageClientEfl* pageClient, bool ren }; // Create a new Evas_GL_Surface object - m_surface = evas_gl_surface_create(m_evasGL, &config, width, height); - if (!m_surface) + m_evasGLSurface = evas_gl_surface_create(m_evasGL, &config, width, height); + if (!m_evasGLSurface) return false; #if USE(ACCELERATED_COMPOSITING) if (renderDirectlyToHostWindow) { Evas_Native_Surface nativeSurface; // Fill in the Native Surface information from the given Evas GL surface. - evas_gl_native_surface_get(m_evasGL, m_surface, &nativeSurface); + evas_gl_native_surface_get(m_evasGL, m_evasGLSurface, &nativeSurface); - // Create and specially set up a evas_object which act as the render targer surface. - if (!pageClient->createEvasObjectForAcceleratedCompositing(&nativeSurface, IntRect(x, y, width, height))) - return false; + // FIXME: Create and specially set up a evas_object which act as the render targer surface. } #endif - return true; -} - -PlatformGraphicsContext3D GraphicsContext3DPrivate::platformGraphicsContext3D() const -{ - return m_context; -} -bool GraphicsContext3DPrivate::makeContextCurrent() -{ - return evas_gl_make_current(m_evasGL, m_surface, m_context); -} - -bool GraphicsContext3DPrivate::isGLES2Compliant() const -{ return true; } -void GraphicsContext3DPrivate::activeTexture(GC3Denum texture) +void GraphicsContext3DPrivate::setCurrentGLContext(void* context, void* surface) { - makeContextCurrent(); - m_api->glActiveTexture(texture); -} - -void GraphicsContext3DPrivate::attachShader(Platform3DObject program, Platform3DObject shader) -{ - makeContextCurrent(); - m_api->glAttachShader(program, shader); -} - -void GraphicsContext3DPrivate::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name) -{ - makeContextCurrent(); - m_api->glBindAttribLocation(program, index, name.utf8().data()); -} - -void GraphicsContext3DPrivate::bindBuffer(GC3Denum target, Platform3DObject buffer) -{ - makeContextCurrent(); - m_api->glBindBuffer(target, buffer); - - if (target == GL_ARRAY_BUFFER) - m_boundArrayBuffer = buffer; -} - -void GraphicsContext3DPrivate::bindFramebuffer(GC3Denum target, Platform3DObject framebuffer) -{ - makeContextCurrent(); - - if (framebuffer != m_boundFBO) { - m_api->glBindFramebuffer(target, framebuffer); - m_boundFBO = framebuffer; - } + m_glContext = context; + m_glSurface = surface; } -void GraphicsContext3DPrivate::bindRenderbuffer(GC3Denum target, Platform3DObject buffer) -{ - makeContextCurrent(); - m_api->glBindRenderbuffer(target, buffer); -} - -void GraphicsContext3DPrivate::bindTexture(GC3Denum target, Platform3DObject texture) -{ - makeContextCurrent(); - m_api->glBindTexture(target, texture); - m_boundTexture = texture; -} - -void GraphicsContext3DPrivate::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) -{ - makeContextCurrent(); - m_api->glBlendColor(red, green, blue, alpha); -} - -void GraphicsContext3DPrivate::blendEquation(GC3Denum mode) -{ - makeContextCurrent(); - m_api->glBlendEquation(mode); -} - -void GraphicsContext3DPrivate::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) -{ - makeContextCurrent(); - m_api->glBlendEquationSeparate(modeRGB, modeAlpha); -} - -void GraphicsContext3DPrivate::blendFunc(GC3Denum srcFactor, GC3Denum dstFactor) -{ - makeContextCurrent(); - m_api->glBlendFunc(srcFactor, dstFactor); -} - -void GraphicsContext3DPrivate::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) -{ - makeContextCurrent(); - m_api->glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); -} - -void GraphicsContext3DPrivate::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage) -{ - makeContextCurrent(); - m_api->glBufferData(target, size, data, usage); -} - -void GraphicsContext3DPrivate::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data) -{ - makeContextCurrent(); - m_api->glBufferSubData(target, offset, size, data); -} - -GC3Denum GraphicsContext3DPrivate::checkFramebufferStatus(GC3Denum target) -{ - makeContextCurrent(); - return m_api->glCheckFramebufferStatus(target); -} - -void GraphicsContext3DPrivate::clear(GC3Dbitfield mask) -{ - makeContextCurrent(); - m_api->glClear(mask); -} - -void GraphicsContext3DPrivate::clearColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) -{ - makeContextCurrent(); - m_api->glClearColor(red, green, blue, alpha); -} - -void GraphicsContext3DPrivate::clearDepth(GC3Dclampf depth) -{ - makeContextCurrent(); - m_api->glClearDepthf(depth); -} - -void GraphicsContext3DPrivate::clearStencil(GC3Dint clearValue) -{ - makeContextCurrent(); - m_api->glClearStencil(clearValue); -} - -void GraphicsContext3DPrivate::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) -{ - makeContextCurrent(); - m_api->glColorMask(red, green, blue, alpha); -} - -void GraphicsContext3DPrivate::compileShader(Platform3DObject shader) -{ - makeContextCurrent(); - m_api->glCompileShader(shader); -} - -void GraphicsContext3DPrivate::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) -{ - makeContextCurrent(); - m_api->glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border); -} - -void GraphicsContext3DPrivate::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - makeContextCurrent(); - m_api->glCopyTexSubImage2D(target, level, xOffset, yOffset, x, y, width, height); -} - -void GraphicsContext3DPrivate::cullFace(GC3Denum mode) -{ - makeContextCurrent(); - m_api->glCullFace(mode); -} - -void GraphicsContext3DPrivate::depthFunc(GC3Denum func) -{ - makeContextCurrent(); - m_api->glDepthFunc(func); -} - -void GraphicsContext3DPrivate::depthMask(GC3Dboolean flag) -{ - makeContextCurrent(); - m_api->glDepthMask(flag); -} - -void GraphicsContext3DPrivate::depthRange(GC3Dclampf zNear, GC3Dclampf zFar) -{ - makeContextCurrent(); - m_api->glDepthRangef(zNear, zFar); -} - -void GraphicsContext3DPrivate::detachShader(Platform3DObject program, Platform3DObject shader) -{ - makeContextCurrent(); - m_api->glDetachShader(program, shader); -} - -void GraphicsContext3DPrivate::disable(GC3Denum cap) -{ - makeContextCurrent(); - m_api->glDisable(cap); -} - -void GraphicsContext3DPrivate::disableVertexAttribArray(GC3Duint index) -{ - makeContextCurrent(); - m_api->glDisableVertexAttribArray(index); -} - -void GraphicsContext3DPrivate::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count) -{ - makeContextCurrent(); - m_api->glDrawArrays(mode, first, count); -} - -void GraphicsContext3DPrivate::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset) -{ - makeContextCurrent(); - m_api->glDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset))); -} - -void GraphicsContext3DPrivate::enable(GC3Denum cap) -{ - makeContextCurrent(); - m_api->glEnable(cap); -} - -void GraphicsContext3DPrivate::enableVertexAttribArray(GC3Duint index) -{ - makeContextCurrent(); - m_api->glEnableVertexAttribArray(index); -} - -void GraphicsContext3DPrivate::finish() -{ - makeContextCurrent(); - m_api->glFinish(); -} - -void GraphicsContext3DPrivate::flush() -{ - makeContextCurrent(); - m_api->glFlush(); -} - -void GraphicsContext3DPrivate::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbufferTarget, Platform3DObject renderbuffer) -{ - makeContextCurrent(); - m_api->glFramebufferRenderbuffer(target, attachment, renderbufferTarget, renderbuffer); -} - -void GraphicsContext3DPrivate::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum texTarget, Platform3DObject texture, GC3Dint level) -{ - makeContextCurrent(); - m_api->glFramebufferTexture2D(target, attachment, texTarget, texture, level); -} - -void GraphicsContext3DPrivate::frontFace(GC3Denum mode) -{ - makeContextCurrent(); - m_api->glFrontFace(mode); -} - -void GraphicsContext3DPrivate::generateMipmap(GC3Denum target) -{ - makeContextCurrent(); - m_api->glGenerateMipmap(target); -} - -bool GraphicsContext3DPrivate::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - if (!program) { - synthesizeGLError(GL_INVALID_VALUE); - return false; - } - - makeContextCurrent(); - - GLint maxNameLength = 0; - m_api->glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength); - if (!maxNameLength) - return false; - - OwnArrayPtr<char> name = adoptArrayPtr(new char[maxNameLength]); - if (!name) { - synthesizeGLError(GL_OUT_OF_MEMORY); - return false; - } - - GLsizei length = 0; - GLint size = 0; - GLenum type = 0; - m_api->glGetActiveAttrib(program, index, maxNameLength, &length, &size, &type, name.get()); - if (!length) - return false; - - info.name = String::fromUTF8(name.get(), length); - info.type = type; - info.size = size; - return true; -} - -bool GraphicsContext3DPrivate::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - if (!program) { - synthesizeGLError(GL_INVALID_VALUE); - return false; - } - - makeContextCurrent(); - - GLint maxNameLength = 0; - m_api->glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); - if (!maxNameLength) - return false; - - OwnArrayPtr<char> name = adoptArrayPtr(new char[maxNameLength]); - if (!name) { - synthesizeGLError(GL_OUT_OF_MEMORY); - return false; - } - - GLsizei length = 0; - GLint size = 0; - GLenum type = 0; - m_api->glGetActiveUniform(program, index, maxNameLength, &length, &size, &type, name.get()); - if (!length) - return false; - - info.name = String::fromUTF8(name.get(), length); - info.type = type; - info.size = size; - return true; -} - -void GraphicsContext3DPrivate::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders) -{ - makeContextCurrent(); - m_api->glGetAttachedShaders(program, maxCount, count, shaders); -} - -int GraphicsContext3DPrivate::getAttribLocation(Platform3DObject program, const String& name) -{ - makeContextCurrent(); - return m_api->glGetAttribLocation(program, name.utf8().data()); -} - -void GraphicsContext3DPrivate::getBooleanv(GC3Denum paramName, GC3Dboolean* value) -{ - makeContextCurrent(); - m_api->glGetBooleanv(paramName, value); -} - -void GraphicsContext3DPrivate::getBufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetBufferParameteriv(target, paramName, value); -} - -GraphicsContext3D::Attributes GraphicsContext3DPrivate::getContextAttributes() -{ - return m_attributes; -} - -GC3Denum GraphicsContext3DPrivate::getError() -{ - if (!m_syntheticErrors.isEmpty()) { - GC3Denum error = m_syntheticErrors.first(); - m_syntheticErrors.remove(m_syntheticErrors.begin()); - return error; - } - - makeContextCurrent(); - return m_api->glGetError(); -} - -void GraphicsContext3DPrivate::getFloatv(GC3Denum paramName, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glGetFloatv(paramName, value); -} - -void GraphicsContext3DPrivate::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetFramebufferAttachmentParameteriv(target, attachment, paramName, value); -} - -void GraphicsContext3DPrivate::getIntegerv(GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetIntegerv(paramName, value); -} - -void GraphicsContext3DPrivate::getProgramiv(Platform3DObject program, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetProgramiv(program, paramName, value); -} - -String GraphicsContext3DPrivate::getProgramInfoLog(Platform3DObject program) -{ - makeContextCurrent(); - - GLint logLength = 0; - m_api->glGetProgramiv(program, GraphicsContext3D::INFO_LOG_LENGTH, &logLength); - if (!logLength) - return String(); - - OwnArrayPtr<char> log = adoptArrayPtr(new char[logLength]); - if (!log) - return String(); - - GLint returnedLogLength = 0; - m_api->glGetProgramInfoLog(program, logLength, &returnedLogLength, log.get()); - ASSERT(logLength == returnedLogLength + 1); - - String result = String::fromUTF8(log.get(), returnedLogLength); - return result; -} - -void GraphicsContext3DPrivate::getRenderbufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetRenderbufferParameteriv(target, paramName, value); -} - -void GraphicsContext3DPrivate::getShaderiv(Platform3DObject shader, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetShaderiv(shader, paramName, value); -} - -String GraphicsContext3DPrivate::getShaderInfoLog(Platform3DObject shader) -{ - makeContextCurrent(); - - GLint logLength = 0; - m_api->glGetShaderiv(shader, GraphicsContext3D::INFO_LOG_LENGTH, &logLength); - if (logLength <= 1) - return String(); - - OwnArrayPtr<char> log = adoptArrayPtr(new char[logLength]); - if (!log) - return String(); - - GLint returnedLogLength = 0; - m_api->glGetShaderInfoLog(shader, logLength, &returnedLogLength, log.get()); - ASSERT(logLength == returnedLogLength + 1); - - String result = String::fromUTF8(log.get(), returnedLogLength); - return result; -} - -String GraphicsContext3DPrivate::getShaderSource(Platform3DObject shader) -{ - makeContextCurrent(); - - GLint logLength = 0; - m_api->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &logLength); - if (logLength <= 1) - return String(); - - OwnArrayPtr<char> log = adoptArrayPtr(new char[logLength]); - if (!log) - return String(); - - GLint returnedLogLength = 0; - m_api->glGetShaderSource(shader, logLength, &returnedLogLength, log.get()); - ASSERT(logLength == returnedLogLength + 1); - - String result = String::fromUTF8(log.get(), returnedLogLength); - return result; -} - -String GraphicsContext3DPrivate::getString(GC3Denum name) -{ - makeContextCurrent(); - return String(reinterpret_cast<const char*>(m_api->glGetString(name))); -} - -void GraphicsContext3DPrivate::getTexParameterfv(GC3Denum target, GC3Denum paramName, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glGetTexParameterfv(target, paramName, value); -} - -void GraphicsContext3DPrivate::getTexParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetTexParameteriv(target, paramName, value); -} - -void GraphicsContext3DPrivate::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glGetUniformfv(program, location, value); -} - -void GraphicsContext3DPrivate::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetUniformiv(program, location, value); -} - -GC3Dint GraphicsContext3DPrivate::getUniformLocation(Platform3DObject program, const String& name) -{ - makeContextCurrent(); - return m_api->glGetUniformLocation(program, name.utf8().data()); -} - -void GraphicsContext3DPrivate::getVertexAttribfv(GC3Duint index, GC3Denum paramName, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glGetVertexAttribfv(index, paramName, value); -} - -void GraphicsContext3DPrivate::getVertexAttribiv(GC3Duint index, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetVertexAttribiv(index, paramName, value); -} - -GC3Dsizeiptr GraphicsContext3DPrivate::getVertexAttribOffset(GC3Duint index, GC3Denum paramName) -{ - makeContextCurrent(); - void* pointer = 0; - m_api->glGetVertexAttribPointerv(index, paramName, &pointer); - return reinterpret_cast<GC3Dsizeiptr>(pointer); -} - -void GraphicsContext3DPrivate::hint(GC3Denum target, GC3Denum mode) -{ - makeContextCurrent(); - m_api->glHint(target, mode); -} - -GC3Dboolean GraphicsContext3DPrivate::isBuffer(Platform3DObject buffer) -{ - makeContextCurrent(); - return m_api->glIsBuffer(buffer); -} - -GC3Dboolean GraphicsContext3DPrivate::isEnabled(GC3Denum cap) -{ - makeContextCurrent(); - return m_api->glIsEnabled(cap); -} - -GC3Dboolean GraphicsContext3DPrivate::isFramebuffer(Platform3DObject framebuffer) -{ - makeContextCurrent(); - return m_api->glIsFramebuffer(framebuffer); -} - -GC3Dboolean GraphicsContext3DPrivate::isProgram(Platform3DObject program) -{ - makeContextCurrent(); - return m_api->glIsProgram(program); -} - -GC3Dboolean GraphicsContext3DPrivate::isRenderbuffer(Platform3DObject renderbuffer) -{ - makeContextCurrent(); - return m_api->glIsRenderbuffer(renderbuffer); -} - -GC3Dboolean GraphicsContext3DPrivate::isShader(Platform3DObject shader) -{ - makeContextCurrent(); - return m_api->glIsShader(shader); -} - -GC3Dboolean GraphicsContext3DPrivate::isTexture(Platform3DObject texture) -{ - makeContextCurrent(); - return m_api->glIsTexture(texture); -} - -void GraphicsContext3DPrivate::lineWidth(GC3Dfloat width) -{ - makeContextCurrent(); - m_api->glLineWidth(width); -} - -void GraphicsContext3DPrivate::linkProgram(Platform3DObject program) -{ - makeContextCurrent(); - m_api->glLinkProgram(program); -} - -void GraphicsContext3DPrivate::pixelStorei(GC3Denum paramName, GC3Dint param) -{ - makeContextCurrent(); - m_api->glPixelStorei(paramName, param); -} - -void GraphicsContext3DPrivate::polygonOffset(GC3Dfloat factor, GC3Dfloat units) -{ - makeContextCurrent(); - m_api->glPolygonOffset(factor, units); -} - -void GraphicsContext3DPrivate::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) -{ - makeContextCurrent(); - - m_api->glFlush(); - m_api->glReadPixels(x, y, width, height, format, type, data); -} - -void GraphicsContext3DPrivate::renderbufferStorage(GC3Denum target, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height) -{ - makeContextCurrent(); - m_api->glRenderbufferStorage(target, internalFormat, width, height); -} - -void GraphicsContext3DPrivate::sampleCoverage(GC3Dclampf value, GC3Dboolean invert) -{ - makeContextCurrent(); - m_api->glSampleCoverage(value, invert); -} - -void GraphicsContext3DPrivate::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - makeContextCurrent(); - m_api->glScissor(x, y, width, height); -} - -void GraphicsContext3DPrivate::shaderSource(Platform3DObject shader, const String& string) -{ - makeContextCurrent(); - const char* str = string.utf8().data(); - int length = string.length(); - m_api->glShaderSource(shader, 1, &str, &length); -} - -void GraphicsContext3DPrivate::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - makeContextCurrent(); - m_api->glStencilFunc(func, ref, mask); -} - -void GraphicsContext3DPrivate::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - makeContextCurrent(); - m_api->glStencilFuncSeparate(face, func, ref, mask); -} - -void GraphicsContext3DPrivate::stencilMask(GC3Duint mask) -{ - makeContextCurrent(); - m_api->glStencilMask(mask); -} - -void GraphicsContext3DPrivate::stencilMaskSeparate(GC3Denum face, GC3Duint mask) -{ - makeContextCurrent(); - m_api->glStencilMaskSeparate(face, mask); -} - -void GraphicsContext3DPrivate::stencilOp(GC3Denum fail, GC3Denum zFail, GC3Denum zPass) -{ - makeContextCurrent(); - m_api->glStencilOp(fail, zFail, zPass); -} - -void GraphicsContext3DPrivate::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zFail, GC3Denum zPass) -{ - makeContextCurrent(); - m_api->glStencilOpSeparate(face, fail, zFail, zPass); -} - -bool GraphicsContext3DPrivate::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) -{ - makeContextCurrent(); - m_api->glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels); - return true; -} - -void GraphicsContext3DPrivate::texParameterf(GC3Denum target, GC3Denum paramName, GC3Dfloat param) -{ - makeContextCurrent(); - m_api->glTexParameterf(target, paramName, param); -} - -void GraphicsContext3DPrivate::texParameteri(GC3Denum target, GC3Denum paramName, GC3Dint param) -{ - makeContextCurrent(); - m_api->glTexParameteri(target, paramName, param); -} - -void GraphicsContext3DPrivate::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels) -{ - makeContextCurrent(); - m_api->glTexSubImage2D(target, level, xOffset, yOffset, width, height, format, type, pixels); -} - -void GraphicsContext3DPrivate::uniform1f(GC3Dint location, GC3Dfloat x) -{ - makeContextCurrent(); - m_api->glUniform1f(location, x); -} - -void GraphicsContext3DPrivate::uniform1fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) -{ - makeContextCurrent(); - m_api->glUniform1fv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform1i(GC3Dint location, GC3Dint x) -{ - makeContextCurrent(); - m_api->glUniform1i(location, x); -} - -void GraphicsContext3DPrivate::uniform1iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) -{ - makeContextCurrent(); - m_api->glUniform1iv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform2f(GC3Dint location, GC3Dfloat x, GC3Dfloat y) -{ - makeContextCurrent(); - m_api->glUniform2f(location, x, y); -} - -void GraphicsContext3DPrivate::uniform2fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) -{ - makeContextCurrent(); - m_api->glUniform2fv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform2i(GC3Dint location, GC3Dint x, GC3Dint y) -{ - makeContextCurrent(); - m_api->glUniform2i(location, x, y); -} - -void GraphicsContext3DPrivate::uniform2iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) -{ - makeContextCurrent(); - m_api->glUniform2iv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform3f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - makeContextCurrent(); - m_api->glUniform3f(location, x, y, z); -} - -void GraphicsContext3DPrivate::uniform3fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) -{ - makeContextCurrent(); - m_api->glUniform3fv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform3i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z) -{ - makeContextCurrent(); - m_api->glUniform3i(location, x, y, z); -} - -void GraphicsContext3DPrivate::uniform3iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) -{ - makeContextCurrent(); - m_api->glUniform3iv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform4f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - makeContextCurrent(); - m_api->glUniform4f(location, x, y, z, w); -} - -void GraphicsContext3DPrivate::uniform4fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) -{ - makeContextCurrent(); - m_api->glUniform4fv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform4i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w) -{ - makeContextCurrent(); - m_api->glUniform4i(location, x, y, z, w); -} - -void GraphicsContext3DPrivate::uniform4iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) -{ - makeContextCurrent(); - m_api->glUniform4iv(location, size, array); -} - -void GraphicsContext3DPrivate::uniformMatrix2fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glUniformMatrix2fv(location, size, transpose, value); -} - -void GraphicsContext3DPrivate::uniformMatrix3fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glUniformMatrix3fv(location, size, transpose, value); -} - -void GraphicsContext3DPrivate::uniformMatrix4fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glUniformMatrix4fv(location, size, transpose, value); -} - -void GraphicsContext3DPrivate::useProgram(Platform3DObject program) -{ - makeContextCurrent(); - m_api->glUseProgram(program); -} - -void GraphicsContext3DPrivate::validateProgram(Platform3DObject program) -{ - makeContextCurrent(); - m_api->glValidateProgram(program); -} - -void GraphicsContext3DPrivate::vertexAttrib1f(GC3Duint index, GC3Dfloat x) -{ - makeContextCurrent(); - m_api->glVertexAttrib1f(index, x); -} - -void GraphicsContext3DPrivate::vertexAttrib1fv(GC3Duint index, GC3Dfloat* values) -{ - makeContextCurrent(); - m_api->glVertexAttrib1fv(index, values); -} - -void GraphicsContext3DPrivate::vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y) -{ - makeContextCurrent(); - m_api->glVertexAttrib2f(index, x, y); -} - -void GraphicsContext3DPrivate::vertexAttrib2fv(GC3Duint index, GC3Dfloat* values) -{ - makeContextCurrent(); - m_api->glVertexAttrib2fv(index, values); -} - -void GraphicsContext3DPrivate::vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - makeContextCurrent(); - m_api->glVertexAttrib3f(index, x, y, z); -} - -void GraphicsContext3DPrivate::vertexAttrib3fv(GC3Duint index, GC3Dfloat* values) -{ - makeContextCurrent(); - m_api->glVertexAttrib3fv(index, values); -} - -void GraphicsContext3DPrivate::vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - makeContextCurrent(); - m_api->glVertexAttrib4f(index, x, y, z, w); -} - -void GraphicsContext3DPrivate::vertexAttrib4fv(GC3Duint index, GC3Dfloat* values) -{ - makeContextCurrent(); - m_api->glVertexAttrib4fv(index, values); -} - -void GraphicsContext3DPrivate::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset) -{ - makeContextCurrent(); - - if (m_boundArrayBuffer <= 0) - return; - - m_api->glVertexAttribPointer(index, size, type, normalized, stride, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset))); -} - -void GraphicsContext3DPrivate::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - makeContextCurrent(); - m_api->glViewport(x, y, width, height); -} - -Platform3DObject GraphicsContext3DPrivate::createBuffer() -{ - makeContextCurrent(); - Platform3DObject buffer = 0; - m_api->glGenBuffers(1, &buffer); - return buffer; -} - -Platform3DObject GraphicsContext3DPrivate::createFramebuffer() -{ - makeContextCurrent(); - Platform3DObject buffer = 0; - m_api->glGenFramebuffers(1, &buffer); - return buffer; -} - -Platform3DObject GraphicsContext3DPrivate::createProgram() -{ - makeContextCurrent(); - return m_api->glCreateProgram(); -} - -Platform3DObject GraphicsContext3DPrivate::createRenderbuffer() -{ - makeContextCurrent(); - Platform3DObject buffer; - m_api->glGenRenderbuffers(1, &buffer); - return buffer; -} - -Platform3DObject GraphicsContext3DPrivate::createShader(GC3Denum shaderType) -{ - makeContextCurrent(); - return m_api->glCreateShader(shaderType); -} - -Platform3DObject GraphicsContext3DPrivate::createTexture() -{ - makeContextCurrent(); - Platform3DObject texture; - m_api->glGenTextures(1, &texture); - return texture; -} - -void GraphicsContext3DPrivate::deleteBuffer(Platform3DObject buffer) -{ - makeContextCurrent(); - m_api->glDeleteBuffers(1, &buffer); -} - -void GraphicsContext3DPrivate::deleteFramebuffer(Platform3DObject framebuffer) -{ - makeContextCurrent(); - if (framebuffer == m_boundFBO) { - // Make sure the framebuffer is not going to be used for drawing - // operations after it gets deleted. - bindFramebuffer(FRAMEBUFFER, 0); - } - m_api->glDeleteFramebuffers(1, &framebuffer); -} - -void GraphicsContext3DPrivate::deleteProgram(Platform3DObject program) -{ - makeContextCurrent(); - m_api->glDeleteProgram(program); -} - -void GraphicsContext3DPrivate::deleteRenderbuffer(Platform3DObject renderbuffer) -{ - makeContextCurrent(); - m_api->glDeleteRenderbuffers(1, &renderbuffer); -} - -void GraphicsContext3DPrivate::deleteShader(Platform3DObject shader) +PlatformGraphicsContext3D GraphicsContext3DPrivate::platformGraphicsContext3D() const { - makeContextCurrent(); - m_api->glDeleteShader(shader); -} + if (m_renderStyle == GraphicsContext3D::RenderToCurrentGLContext) + return m_glContext; -void GraphicsContext3DPrivate::deleteTexture(Platform3DObject texture) -{ - makeContextCurrent(); - m_api->glDeleteTextures(1, &texture); + return m_evasGLContext; } -void GraphicsContext3DPrivate::synthesizeGLError(GC3Denum error) +bool GraphicsContext3DPrivate::makeContextCurrent() { - m_syntheticErrors.add(error); + return evas_gl_make_current(m_evasGL, m_evasGLSurface, m_evasGLContext); } -Extensions3D* GraphicsContext3DPrivate::getExtensions() +#if USE(TEXTURE_MAPPER_GL) +void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper*, const FloatRect& target, const TransformationMatrix&, float opacity, BitmapTexture* mask) { notImplemented(); - return 0; } - +#endif } // namespace WebCore #endif // USE(3D_GRAPHICS) || USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h index d02b87845..08ccf77a6 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h @@ -22,15 +22,26 @@ #include "GraphicsContext3D.h" -#include <Evas_GL.h> +#if USE(TEXTURE_MAPPER_GL) +#include <texmap/TextureMapperPlatformLayer.h> +#endif -namespace WebCore { +typedef struct _Evas_GL Evas_GL; +typedef struct _Evas_GL_Surface Evas_GL_Surface; +typedef struct _Evas_GL_Context Evas_GL_Context; +typedef struct _Evas_GL_Config Evas_GL_Config; +typedef struct _Evas_GL_API Evas_GL_API; class PageClientEfl; -class GraphicsContext3DPrivate { +namespace WebCore { +class GraphicsContext3DPrivate +#if USE(TEXTURE_MAPPER_GL) + : public TextureMapperPlatformLayer +#endif +{ public: - static PassOwnPtr<GraphicsContext3DPrivate> create(GraphicsContext3D::Attributes attrs, HostWindow*, bool renderDirectlyToEvasGLObject); + GraphicsContext3DPrivate(GraphicsContext3D*, HostWindow*, GraphicsContext3D::RenderStyle); ~GraphicsContext3DPrivate(); PlatformGraphicsContext3D platformGraphicsContext3D() const; @@ -38,188 +49,27 @@ public: #if USE(ACCELERATED_COMPOSITING) PlatformLayer* platformLayer() const; #endif - +#if USE(TEXTURE_MAPPER_GL) + virtual void paintToTextureMapper(TextureMapper*, const FloatRect& target, const TransformationMatrix&, float opacity, BitmapTexture* mask); +#endif bool makeContextCurrent(); - - bool isGLES2Compliant() const; - - void activeTexture(GC3Denum texture); - void attachShader(Platform3DObject program, Platform3DObject shader); - void bindAttribLocation(Platform3DObject, GC3Duint index, const String& name); - void bindBuffer(GC3Denum target, Platform3DObject); - void bindFramebuffer(GC3Denum target, Platform3DObject); - void bindRenderbuffer(GC3Denum target, Platform3DObject); - void bindTexture(GC3Denum target, Platform3DObject); - void blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha); - void blendEquation(GC3Denum mode); - void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha); - void blendFunc(GC3Denum srcFactor, GC3Denum dstFactor); - void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha); - - void bufferData(GC3Denum target, GC3Dsizeiptr, const void* data, GC3Denum usage); - void bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr, const void* data); - - GC3Denum checkFramebufferStatus(GC3Denum target); - void clear(GC3Dbitfield mask); - void clearColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha); - void clearDepth(GC3Dclampf depth); - void clearStencil(GC3Dint clearValue); - void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha); - void compileShader(Platform3DObject); - - void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border); - void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - void cullFace(GC3Denum mode); - void depthFunc(GC3Denum func); - void depthMask(GC3Dboolean flag); - void depthRange(GC3Dclampf zNear, GC3Dclampf zFar); - void detachShader(Platform3DObject, Platform3DObject); - void disable(GC3Denum cap); - void disableVertexAttribArray(GC3Duint index); - void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count); - void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset); - - void enable(GC3Denum cap); - void enableVertexAttribArray(GC3Duint index); - void finish(); - void flush(); - void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbufferTarget, Platform3DObject); - void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum texTarget, Platform3DObject, GC3Dint level); - void frontFace(GC3Denum mode); - void generateMipmap(GC3Denum target); - - bool getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo&); - bool getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo&); - void getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders); - GC3Dint getAttribLocation(Platform3DObject, const String& name); - void getBooleanv(GC3Denum paramName, GC3Dboolean* value); - void getBufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value); - GraphicsContext3D::Attributes getContextAttributes(); - GC3Denum getError(); - void getFloatv(GC3Denum paramName, GC3Dfloat* value); - void getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum paramName, GC3Dint* value); - void getIntegerv(GC3Denum paramName, GC3Dint* value); - void getProgramiv(Platform3DObject program, GC3Denum paramName, GC3Dint* value); - String getProgramInfoLog(Platform3DObject); - void getRenderbufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value); - void getShaderiv(Platform3DObject, GC3Denum paramName, GC3Dint* value); - String getShaderInfoLog(Platform3DObject); - - String getShaderSource(Platform3DObject); - String getString(GC3Denum name); - void getTexParameterfv(GC3Denum target, GC3Denum paramName, GC3Dfloat* value); - void getTexParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value); - void getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value); - void getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value); - GC3Dint getUniformLocation(Platform3DObject, const String& name); - void getVertexAttribfv(GC3Duint index, GC3Denum paramName, GC3Dfloat* value); - void getVertexAttribiv(GC3Duint index, GC3Denum paramName, GC3Dint* value); - GC3Dsizeiptr getVertexAttribOffset(GC3Duint index, GC3Denum paramName); - - void hint(GC3Denum target, GC3Denum mode); - GC3Dboolean isBuffer(Platform3DObject); - GC3Dboolean isEnabled(GC3Denum cap); - GC3Dboolean isFramebuffer(Platform3DObject); - GC3Dboolean isProgram(Platform3DObject); - GC3Dboolean isRenderbuffer(Platform3DObject); - GC3Dboolean isShader(Platform3DObject); - GC3Dboolean isTexture(Platform3DObject); - void lineWidth(GC3Dfloat); - void linkProgram(Platform3DObject); - void pixelStorei(GC3Denum paramName, GC3Dint param); - void polygonOffset(GC3Dfloat factor, GC3Dfloat units); - - void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data); - - void renderbufferStorage(GC3Denum target, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height); - void sampleCoverage(GC3Dclampf value, GC3Dboolean invert); - void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - void shaderSource(Platform3DObject, const String&); - void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask); - void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask); - void stencilMask(GC3Duint mask); - void stencilMaskSeparate(GC3Denum face, GC3Duint mask); - void stencilOp(GC3Denum fail, GC3Denum zFail, GC3Denum zPass); - void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zFail, GC3Denum zPass); - - bool texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels); - void texParameterf(GC3Denum target, GC3Denum paramName, GC3Dfloat param); - void texParameteri(GC3Denum target, GC3Denum paramName, GC3Dint param); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels); - - void uniform1f(GC3Dint location, GC3Dfloat x); - void uniform1fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v); - void uniform1i(GC3Dint location, GC3Dint x); - void uniform1iv(GC3Dint location, GC3Dsizei, GC3Dint* v); - void uniform2f(GC3Dint location, GC3Dfloat x, float y); - void uniform2fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v); - void uniform2i(GC3Dint location, GC3Dint x, GC3Dint y); - void uniform2iv(GC3Dint location, GC3Dsizei, GC3Dint* v); - void uniform3f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); - void uniform3fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v); - void uniform3i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z); - void uniform3iv(GC3Dint location, GC3Dsizei, GC3Dint* v); - void uniform4f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); - void uniform4fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v); - void uniform4i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w); - void uniform4iv(GC3Dint location, GC3Dsizei, GC3Dint* v); - void uniformMatrix2fv(GC3Dint location, GC3Dsizei, GC3Dboolean transpose, GC3Dfloat* value); - void uniformMatrix3fv(GC3Dint location, GC3Dsizei, GC3Dboolean transpose, GC3Dfloat* value); - void uniformMatrix4fv(GC3Dint location, GC3Dsizei, GC3Dboolean transpose, GC3Dfloat* value); - - void useProgram(Platform3DObject); - void validateProgram(Platform3DObject); - - void vertexAttrib1f(GC3Duint index, GC3Dfloat x); - void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values); - void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y); - void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values); - void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); - void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values); - void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); - void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values); - void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, - GC3Dsizei stride, GC3Dintptr offset); - - void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - - Platform3DObject createBuffer(); - Platform3DObject createFramebuffer(); - Platform3DObject createProgram(); - Platform3DObject createRenderbuffer(); - Platform3DObject createShader(GC3Denum); - Platform3DObject createTexture(); - - void deleteBuffer(Platform3DObject); - void deleteFramebuffer(Platform3DObject); - void deleteProgram(Platform3DObject); - void deleteRenderbuffer(Platform3DObject); - void deleteShader(Platform3DObject); - void deleteTexture(Platform3DObject); - - void synthesizeGLError(GC3Denum error); - - Extensions3D* getExtensions(); - -private: - GraphicsContext3DPrivate(); - - bool initialize(GraphicsContext3D::Attributes attrs, HostWindow*, bool renderDirectlyToHostWindow); - bool createSurface(PageClientEfl*, bool renderDirectlyToEvasGLObject); + void setCurrentGLContext(void*, void*); GraphicsContext3D::Attributes m_attributes; - - Platform3DObject m_boundFBO; - Platform3DObject m_boundTexture; - Platform3DObject m_boundArrayBuffer; + GraphicsContext3D* m_context; + HostWindow* m_hostWindow; ListHashSet<GC3Denum> m_syntheticErrors; + OwnPtr<Ecore_Evas> m_ecoreEvas; Evas_GL* m_evasGL; - Evas_GL_Context* m_context; - Evas_GL_Surface* m_surface; + Evas_GL_Context* m_evasGLContext; + Evas_GL_Surface* m_evasGLSurface; + void* m_glContext; + void* m_glSurface; Evas_GL_API* m_api; + GraphicsContext3D::RenderStyle m_renderStyle; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp b/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp deleted file mode 100644 index a566bd064..000000000 --- a/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright (C) 2009-2011 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" - -#if USE(ACCELERATED_COMPOSITING) - -#include "GraphicsLayerEfl.h" - -#include "NotImplemented.h" - -namespace WebCore { - -PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) -{ - return adoptPtr(new GraphicsLayerEfl(client)); -} - -GraphicsLayerEfl::GraphicsLayerEfl(GraphicsLayerClient* client) - : GraphicsLayer(client) -{ -} - -GraphicsLayerEfl::~GraphicsLayerEfl() -{ - willBeDestroyed(); -} - -void GraphicsLayerEfl::setNeedsDisplay() -{ - notImplemented(); -} - -void GraphicsLayerEfl::setNeedsDisplayInRect(const FloatRect&) -{ - notImplemented(); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/egl/GLContextEGL.cpp b/Source/WebCore/platform/graphics/egl/GLContextEGL.cpp new file mode 100644 index 000000000..b9389b483 --- /dev/null +++ b/Source/WebCore/platform/graphics/egl/GLContextEGL.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2012 Igalia, S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "GLContextEGL.h" + +#if USE(EGL) + +#include "GraphicsContext3D.h" +#include <wtf/OwnPtr.h> + +#if USE(OPENGL_ES_2) +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#else +#include "OpenGLShims.h" +#endif + +namespace WebCore { + +static EGLDisplay gSharedEGLDisplay = EGL_NO_DISPLAY; + +#if USE(OPENGL_ES_2) +static const EGLenum gGLAPI = EGL_OPENGL_ES_API; +#else +static const EGLenum gGLAPI = EGL_OPENGL_API; +#endif + +static EGLDisplay sharedEGLDisplay() +{ + static bool initialized = false; + if (!initialized) { + initialized = true; +#if PLATFORM(X11) + gSharedEGLDisplay = eglGetDisplay(GLContext::sharedX11Display()); +#else + gSharedEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); +#endif + if (gSharedEGLDisplay != EGL_NO_DISPLAY && (!eglInitialize(gSharedEGLDisplay, 0, 0) || !eglBindAPI(gGLAPI))) + gSharedEGLDisplay = EGL_NO_DISPLAY; + } + return gSharedEGLDisplay; +} + +static const EGLint gContextAttributes[] = { +#if USE(OPENGL_ES_2) + EGL_CONTEXT_CLIENT_VERSION, 2, +#endif + EGL_NONE +}; + +static bool getEGLConfig(EGLConfig* config, GLContextEGL::EGLSurfaceType surfaceType) +{ + EGLint attributeList[] = { +#if USE(OPENGL_ES_2) + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#else + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, +#endif + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_STENCIL_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_NONE, + EGL_NONE + }; + + switch (surfaceType) { + case GLContextEGL::PbufferSurface: + attributeList[13] = EGL_PBUFFER_BIT; + break; + case GLContextEGL::PixmapSurface: + attributeList[13] = EGL_PIXMAP_BIT; + break; + case GLContextEGL::WindowSurface: + attributeList[13] = EGL_WINDOW_BIT; + break; + } + + EGLint numberConfigsReturned; + return eglChooseConfig(sharedEGLDisplay(), attributeList, config, 1, &numberConfigsReturned) && numberConfigsReturned; +} + +PassOwnPtr<GLContextEGL> GLContextEGL::createWindowContext(EGLNativeWindowType window, GLContext* sharingContext) +{ + EGLContext eglSharingContext = sharingContext ? static_cast<GLContextEGL*>(sharingContext)->m_context : 0; + + EGLDisplay display = sharedEGLDisplay(); + if (display == EGL_NO_DISPLAY) + return nullptr; + + EGLConfig config; + if (!getEGLConfig(&config, WindowSurface)) + return nullptr; + + EGLContext context = eglCreateContext(display, config, eglSharingContext, gContextAttributes); + if (context == EGL_NO_CONTEXT) + return nullptr; + + EGLSurface surface = eglCreateWindowSurface(display, config, window, 0); + if (surface == EGL_NO_SURFACE) + return nullptr; + + return adoptPtr(new GLContextEGL(context, surface, WindowSurface)); +} + +PassOwnPtr<GLContextEGL> GLContextEGL::createPbufferContext(EGLContext sharingContext) +{ + EGLDisplay display = sharedEGLDisplay(); + if (display == EGL_NO_DISPLAY) + return nullptr; + + EGLConfig config; + if (!getEGLConfig(&config, PbufferSurface)) + return nullptr; + + EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes); + if (context == EGL_NO_CONTEXT) + return nullptr; + + static const int pbufferAttributes[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; + EGLSurface surface = eglCreatePbufferSurface(display, config, pbufferAttributes); + if (surface == EGL_NO_SURFACE) { + eglDestroyContext(display, context); + return nullptr; + } + + return adoptPtr(new GLContextEGL(context, surface, PbufferSurface)); +} + +PassOwnPtr<GLContextEGL> GLContextEGL::createPixmapContext(EGLContext sharingContext) +{ +#if PLATFORM(X11) + EGLDisplay display = sharedEGLDisplay(); + if (display == EGL_NO_DISPLAY) + return nullptr; + + EGLConfig config; + if (!getEGLConfig(&config, PixmapSurface)) + return nullptr; + + EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes); + if (context == EGL_NO_CONTEXT) + return nullptr; + + EGLint depth; + if (!eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depth)) + return nullptr; + + Pixmap pixmap = XCreatePixmap(sharedX11Display(), DefaultRootWindow(sharedX11Display()), 1, 1, depth); + if (!pixmap) + return nullptr; + + EGLSurface surface = eglCreatePixmapSurface(display, config, pixmap, 0); +#else + EGLSurface surface = EGL_NO_SURFACE; +#endif + if (surface == EGL_NO_SURFACE) + return nullptr; + + return adoptPtr(new GLContextEGL(context, surface, PixmapSurface)); +} + +PassOwnPtr<GLContextEGL> GLContextEGL::createContext(EGLNativeWindowType window, GLContext* sharingContext) +{ + if (!sharedEGLDisplay()) + return nullptr; + + static bool initialized = false; + static bool success = true; + if (!initialized) { +#if !USE(OPENGL_ES_2) + success = initializeOpenGLShims(); +#endif + initialized = true; + } + if (!success) + return nullptr; + + EGLContext eglSharingContext = sharingContext ? static_cast<GLContextEGL*>(sharingContext)->m_context : 0; + OwnPtr<GLContextEGL> context = window ? createWindowContext(window, sharingContext) : nullptr; + if (!context) + context = createPixmapContext(eglSharingContext); + + if (!context) + context = createPbufferContext(eglSharingContext); + + return context.release(); +} + +GLContextEGL::GLContextEGL(EGLContext context, EGLSurface surface, EGLSurfaceType type) + : m_context(context) + , m_surface(surface) + , m_type(type) +{ +} + +GLContextEGL::~GLContextEGL() +{ + EGLDisplay display = sharedEGLDisplay(); + if (m_context) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(display, m_context); + } + + if (m_surface) + eglDestroySurface(display, m_surface); +} + +bool GLContextEGL::canRenderToDefaultFramebuffer() +{ + return m_type == WindowSurface; +} + +IntSize GLContextEGL::defaultFrameBufferSize() +{ + if (!canRenderToDefaultFramebuffer()) + return IntSize(); + + EGLint width, height; + if (!eglQuerySurface(sharedEGLDisplay(), m_surface, EGL_WIDTH, &width) + || !eglQuerySurface(sharedEGLDisplay(), m_surface, EGL_HEIGHT, &height)) + return IntSize(); + + return IntSize(width, height); +} + +bool GLContextEGL::makeContextCurrent() +{ + ASSERT(m_context && m_surface); + + GLContext::makeContextCurrent(); + if (eglGetCurrentContext() == m_context) + return true; + + return eglMakeCurrent(sharedEGLDisplay(), m_surface, m_surface, m_context); +} + +void GLContextEGL::swapBuffers() +{ + ASSERT(m_surface); + eglSwapBuffers(sharedEGLDisplay(), m_surface); +} + +void GLContextEGL::waitNative() +{ + eglWaitNative(EGL_CORE_NATIVE_ENGINE); +} + +#if ENABLE(WEBGL) +PlatformGraphicsContext3D GLContextEGL::platformContext() +{ + return m_context; +} +#endif + +} // namespace WebCore + +#endif // USE(EGL) diff --git a/Source/WebCore/platform/graphics/egl/GLContextEGL.h b/Source/WebCore/platform/graphics/egl/GLContextEGL.h new file mode 100644 index 000000000..c5d4bf756 --- /dev/null +++ b/Source/WebCore/platform/graphics/egl/GLContextEGL.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GLContextEGL_h +#define GLContextEGL_h + +#if USE(EGL) + +#include "GLContext.h" + +#include <EGL/egl.h> + +namespace WebCore { + +class GLContextEGL : public GLContext { + WTF_MAKE_NONCOPYABLE(GLContextEGL); +public: + enum EGLSurfaceType { PbufferSurface, WindowSurface, PixmapSurface }; + static PassOwnPtr<GLContextEGL> createContext(EGLNativeWindowType, GLContext* sharingContext = 0); + static PassOwnPtr<GLContextEGL> createWindowContext(EGLNativeWindowType, GLContext* sharingContext); + + virtual ~GLContextEGL(); + virtual bool makeContextCurrent(); + virtual void swapBuffers(); + virtual void waitNative(); + virtual bool canRenderToDefaultFramebuffer(); + virtual IntSize defaultFrameBufferSize(); + + +#if ENABLE(WEBGL) + virtual PlatformGraphicsContext3D platformContext(); +#endif + +private: + static PassOwnPtr<GLContextEGL> createPbufferContext(EGLContext sharingContext); + static PassOwnPtr<GLContextEGL> createPixmapContext(EGLContext sharingContext); + + static void addActiveContext(GLContextEGL*); + static void cleanupSharedEGLDisplay(void); + + GLContextEGL(EGLContext, EGLSurface, EGLSurfaceType); + + EGLContext m_context; + EGLSurface m_surface; + EGLSurfaceType m_type; +}; + +} // namespace WebCore + +#endif // USE(EGL) + +#endif // GLContextEGL_h diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterConstants.h b/Source/WebCore/platform/graphics/filters/CustomFilterConstants.h new file mode 100644 index 000000000..6080c38f6 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/CustomFilterConstants.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CustomFilterConstants_h +#define CustomFilterConstants_h + +namespace WebCore { + +enum CustomFilterMeshConstants { + // Vertex attribute sizes + PositionAttribSize = 4, + TexAttribSize = 2, + MeshAttribSize = 2, + TriangleAttribSize = 3, + // Vertex attribute offsets + PositionAttribOffset = 0, + TexAttribOffset = PositionAttribOffset + PositionAttribSize * sizeof(float), + MeshAttribOffset = TexAttribOffset + TexAttribSize * sizeof(float), + TriangleAttribOffset = MeshAttribOffset + MeshAttribSize * sizeof(float) +}; + +} // namespace WebCore + +#endif // CustomFilterConstants_h diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp index da9782af8..02a96b864 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp @@ -44,7 +44,7 @@ CustomFilterGlobalContext::CustomFilterGlobalContext() CustomFilterGlobalContext::~CustomFilterGlobalContext() { for (CustomFilterValidatedProgramsMap::iterator iter = m_programs.begin(); iter != m_programs.end(); ++iter) - iter->second->detachFromGlobalContext(); + iter->value->detachFromGlobalContext(); } ANGLEWebKitBridge* CustomFilterGlobalContext::webglShaderValidator() @@ -91,7 +91,7 @@ PassRefPtr<CustomFilterValidatedProgram> CustomFilterGlobalContext::getValidated { CustomFilterValidatedProgramsMap::iterator iter = m_programs.find(programInfo); if (iter != m_programs.end()) - return iter->second; + return iter->value; RefPtr<CustomFilterValidatedProgram> validatedProgram = CustomFilterValidatedProgram::create(this, programInfo); m_programs.set(programInfo, validatedProgram.get()); @@ -107,7 +107,7 @@ void CustomFilterGlobalContext::removeValidatedProgram(const CustomFilterValidat #ifndef NDEBUG // Check that there's no way we could have the same program under a different key. for (iter = m_programs.begin(); iter != m_programs.end(); ++iter) - ASSERT(iter->second != program); + ASSERT(iter->value != program); #endif } diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h b/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h index 09f75621b..b3a184702 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h @@ -32,6 +32,7 @@ #if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) +#include "CustomFilterConstants.h" #include "CustomFilterOperation.h" #include "FloatRect.h" @@ -63,13 +64,8 @@ public: unsigned floatsPerVertex() const { - static const unsigned AttachedMeshVertexSize = 4 + // vec4 a_position - 2 + // vec2 a_texCoord - 2; // vec2 a_meshCoord - - static const unsigned DetachedMeshVertexSize = AttachedMeshVertexSize + - 3; // vec3 a_triangleCoord - + static const unsigned AttachedMeshVertexSize = PositionAttribSize + TexAttribSize + MeshAttribSize; + static const unsigned DetachedMeshVertexSize = AttachedMeshVertexSize + TriangleAttribSize; return m_meshType == CustomFilterOperation::ATTACHED ? AttachedMeshVertexSize : DetachedMeshVertexSize; } diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp index d1cf6134f..c9990d98d 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp @@ -38,8 +38,9 @@ namespace WebCore { -CustomFilterProgram::CustomFilterProgram(CustomFilterProgramMixSettings mixSettings) - : m_mixSettings(mixSettings) +CustomFilterProgram::CustomFilterProgram(CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings) + : m_programType(programType) + , m_mixSettings(mixSettings) { // Keep the constructor protected to prevent creating this object directly. } @@ -75,13 +76,13 @@ void CustomFilterProgram::removeClient(CustomFilterProgramClient* client) void CustomFilterProgram::notifyClients() { for (CustomFilterProgramClientList::iterator iter = m_clients.begin(), end = m_clients.end(); iter != end; ++iter) - iter->first->notifyCustomFilterProgramLoaded(this); + iter->key->notifyCustomFilterProgramLoaded(this); } CustomFilterProgramInfo CustomFilterProgram::programInfo() const { ASSERT(isLoaded()); - return CustomFilterProgramInfo(vertexShaderString(), fragmentShaderString(), m_mixSettings); + return CustomFilterProgramInfo(vertexShaderString(), fragmentShaderString(), m_programType, m_mixSettings); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h index ef19dfb83..0492d476d 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h @@ -58,6 +58,7 @@ public: void removeClient(CustomFilterProgramClient*); CustomFilterProgramInfo programInfo() const; + CustomFilterProgramType programType() const { return m_programType; } // StyleCustomFilterProgram has the only implementation for the following method. That means, it casts to StyleCustomFilterProgram // withouth checking the type. If you add another implementation, also add a mechanism to check for the correct type. @@ -75,11 +76,12 @@ protected: virtual void didRemoveLastClient() = 0; // Keep the constructor protected to prevent creating this object directly. - CustomFilterProgram(CustomFilterProgramMixSettings); + CustomFilterProgram(CustomFilterProgramType, const CustomFilterProgramMixSettings&); private: typedef HashCountedSet<CustomFilterProgramClient*> CustomFilterProgramClientList; CustomFilterProgramClientList m_clients; + CustomFilterProgramType m_programType; CustomFilterProgramMixSettings m_mixSettings; }; diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp index 1bf6a91f0..bc1494faf 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp @@ -64,9 +64,10 @@ bool CustomFilterProgramInfo::isHashTableDeletedValue() const && m_fragmentShaderString.isHashTableDeletedValue(); } -CustomFilterProgramInfo::CustomFilterProgramInfo(const String& vertexShader, const String& fragmentShader, const CustomFilterProgramMixSettings& mixSettings) +CustomFilterProgramInfo::CustomFilterProgramInfo(const String& vertexShader, const String& fragmentShader, CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings) : m_vertexShaderString(vertexShader) , m_fragmentShaderString(fragmentShader) + , m_programType(programType) , m_mixSettings(mixSettings) { // At least one of the shaders needs to be non-null. @@ -80,9 +81,9 @@ unsigned CustomFilterProgramInfo::hash() const uintptr_t hashCodes[5] = { hashPossiblyNullString(m_vertexShaderString), hashPossiblyNullString(m_fragmentShaderString), - m_mixSettings.enabled, - m_mixSettings.enabled ? m_mixSettings.blendMode : 0, - m_mixSettings.enabled ? m_mixSettings.compositeOperator : 0 + m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE, + m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE ? m_mixSettings.blendMode : 0, + m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE ? m_mixSettings.compositeOperator : 0 }; return StringHasher::hashMemory<sizeof(hashCodes)>(&hashCodes); } @@ -91,9 +92,16 @@ bool CustomFilterProgramInfo::operator==(const CustomFilterProgramInfo& o) const { ASSERT(!isHashTableDeletedValue()); ASSERT(!o.isHashTableDeletedValue()); + + if (m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE) + return m_vertexShaderString == o.m_vertexShaderString + && m_fragmentShaderString == o.m_fragmentShaderString + && m_programType == o.m_programType + && m_mixSettings == o.m_mixSettings; + return m_vertexShaderString == o.m_vertexShaderString && m_fragmentShaderString == o.m_fragmentShaderString - && m_mixSettings == o.m_mixSettings; + && m_programType == o.m_programType; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h index 52fe77157..3b544c5ad 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h @@ -45,19 +45,16 @@ enum CustomFilterProgramType { struct CustomFilterProgramMixSettings { CustomFilterProgramMixSettings() - : enabled(false) - , blendMode(BlendModeNormal) + : blendMode(BlendModeNormal) , compositeOperator(CompositeSourceOver) { } bool operator==(const CustomFilterProgramMixSettings& o) const { - return (!enabled && !o.enabled) - || (blendMode == o.blendMode && compositeOperator == o.compositeOperator); + return blendMode == o.blendMode && compositeOperator == o.compositeOperator; } - bool enabled; BlendMode blendMode; CompositeOperator compositeOperator; }; @@ -67,7 +64,7 @@ struct CustomFilterProgramMixSettings { // Null strings are placeholders for the default shader. class CustomFilterProgramInfo { public: - CustomFilterProgramInfo(const String&, const String&, const CustomFilterProgramMixSettings&); + CustomFilterProgramInfo(const String&, const String&, CustomFilterProgramType, const CustomFilterProgramMixSettings&); CustomFilterProgramInfo(); bool isEmptyValue() const; @@ -80,13 +77,12 @@ public: const String& vertexShaderString() const { return m_vertexShaderString; } const String& fragmentShaderString() const { return m_fragmentShaderString; } - // FIXME: We should add CustomFilterProgramType to CustomFilterProgramInfo and remove mixSettings.enabled. - // https://bugs.webkit.org/show_bug.cgi?id=96448 - CustomFilterProgramType programType() const { return m_mixSettings.enabled ? PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE : PROGRAM_TYPE_NO_ELEMENT_TEXTURE; } + CustomFilterProgramType programType() const { return m_programType; } const CustomFilterProgramMixSettings& mixSettings() const { return m_mixSettings; } private: String m_vertexShaderString; String m_fragmentShaderString; + CustomFilterProgramType m_programType; CustomFilterProgramMixSettings m_mixSettings; }; diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp index 4211e82b7..85ddda5a2 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp @@ -83,10 +83,12 @@ CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalCon originalFragmentShader = defaultFragmentShaderString(); // Shaders referenced from the CSS mix function use a different validator than regular WebGL shaders. See CustomFilterGlobalContext.h for more details. - ANGLEWebKitBridge* validator = programInfo.mixSettings().enabled ? m_globalContext->mixShaderValidator() : m_globalContext->webglShaderValidator(); + bool blendsElementTexture = (programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE); + ANGLEWebKitBridge* validator = blendsElementTexture ? m_globalContext->mixShaderValidator() : m_globalContext->webglShaderValidator(); String vertexShaderLog, fragmentShaderLog; - bool vertexShaderValid = validator->validateShaderSource(originalVertexShader.utf8().data(), SHADER_TYPE_VERTEX, m_validatedVertexShader, vertexShaderLog, SH_ATTRIBUTES_UNIFORMS); - bool fragmentShaderValid = validator->validateShaderSource(originalFragmentShader.utf8().data(), SHADER_TYPE_FRAGMENT, m_validatedFragmentShader, fragmentShaderLog, SH_ATTRIBUTES_UNIFORMS); + Vector<ANGLEShaderSymbol> symbols; + bool vertexShaderValid = validator->compileShaderSource(originalVertexShader.utf8().data(), SHADER_TYPE_VERTEX, m_validatedVertexShader, vertexShaderLog, symbols); + bool fragmentShaderValid = validator->compileShaderSource(originalFragmentShader.utf8().data(), SHADER_TYPE_FRAGMENT, m_validatedFragmentShader, fragmentShaderLog, symbols); if (!vertexShaderValid || !fragmentShaderValid) { // FIXME: Report the validation errors. // https://bugs.webkit.org/show_bug.cgi?id=74416 @@ -94,12 +96,7 @@ CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalCon } // Validate the author's samplers. - Vector<ANGLEShaderSymbol> uniforms; - if (!validator->getUniforms(SH_VERTEX_SHADER, uniforms)) - return; - if (!validator->getUniforms(SH_FRAGMENT_SHADER, uniforms)) - return; - for (Vector<ANGLEShaderSymbol>::iterator it = uniforms.begin(); it != uniforms.end(); ++it) { + for (Vector<ANGLEShaderSymbol>::iterator it = symbols.begin(); it != symbols.end(); ++it) { if (it->isSampler()) { // FIXME: For now, we restrict shaders with any sampler defined. // When we implement texture parameters, we will allow shaders whose samplers are bound to valid textures. @@ -111,7 +108,7 @@ CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalCon } // We need to add texture access, blending, and compositing code to shaders that are referenced from the CSS mix function. - if (programInfo.mixSettings().enabled) { + if (blendsElementTexture) { rewriteMixVertexShader(); rewriteMixFragmentShader(); } @@ -129,7 +126,7 @@ PassRefPtr<CustomFilterCompiledProgram> CustomFilterValidatedProgram::compiledPr void CustomFilterValidatedProgram::rewriteMixVertexShader() { - ASSERT(m_programInfo.mixSettings().enabled); + ASSERT(m_programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE); // During validation, ANGLE renamed the author's "main" function to "css_main". // We write our own "main" function and call "css_main" from it. @@ -148,7 +145,7 @@ void CustomFilterValidatedProgram::rewriteMixVertexShader() void CustomFilterValidatedProgram::rewriteMixFragmentShader() { - ASSERT(m_programInfo.mixSettings().enabled); + ASSERT(m_programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE); StringBuilder builder; // ANGLE considered these symbols as built-ins during validation under the SH_CSS_SHADERS_SPEC flag. diff --git a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp index a4a6f9ed3..fad92c95a 100644 --- a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp +++ b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp @@ -243,6 +243,12 @@ ALWAYS_INLINE void setDestinationPixels(Uint8ClampedArray* image, int& pixel, fl image->set(pixel++, maxAlpha); } +#if defined(_MSC_VER) && (_MSC_VER >= 1700) +// Incorrectly diagnosing overwrite of stack in |totals| due to |preserveAlphaValues|. +#pragma warning(push) +#pragma warning(disable: 4789) +#endif + // Only for region C template<bool preserveAlphaValues> ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom, int yStart, int yEnd) @@ -381,6 +387,10 @@ void FEConvolveMatrix::fastSetOuterPixels(PaintingData& paintingData, int x1, in } } +#if defined(_MSC_VER) && (_MSC_VER >= 1700) +#pragma warning(pop) // Disable of 4789 +#endif + ALWAYS_INLINE void FEConvolveMatrix::setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom, int yStart, int yEnd) { // Must be implemented here, since it refers another ALWAYS_INLINE @@ -444,9 +454,13 @@ void FEConvolveMatrix::platformApplySoftware() if (optimalThreadNumber > 1) { WTF::ParallelJobs<InteriorPixelParameters> parallelJobs(&WebCore::FEConvolveMatrix::setInteriorPixelsWorker, optimalThreadNumber); const int numOfThreads = parallelJobs.numberOfJobs(); + + // Split the job into "heightPerThread" jobs but there a few jobs that need to be slightly larger since + // heightPerThread * jobs < total size. These extras are handled by the remainder "jobsWithExtra". const int heightPerThread = clipBottom / numOfThreads; - int startY = 0; + const int jobsWithExtra = clipBottom % numOfThreads; + int startY = 0; for (int job = 0; job < numOfThreads; ++job) { InteriorPixelParameters& param = parallelJobs.parameter(job); param.filter = this; @@ -454,11 +468,8 @@ void FEConvolveMatrix::platformApplySoftware() param.clipRight = clipRight; param.clipBottom = clipBottom; param.yStart = startY; - if (job < numOfThreads - 1) { - startY += heightPerThread; - param.yEnd = startY - 1; - } else - param.yEnd = clipBottom; + startY += job < jobsWithExtra ? heightPerThread + 1 : heightPerThread; + param.yEnd = startY; } parallelJobs.execute(); diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp index fb5760f0b..707edb866 100644 --- a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp +++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp @@ -35,6 +35,7 @@ #include "CustomFilterArrayParameter.h" #include "CustomFilterCompiledProgram.h" +#include "CustomFilterConstants.h" #include "CustomFilterGlobalContext.h" #include "CustomFilterMesh.h" #include "CustomFilterNumberParameter.h" @@ -224,7 +225,7 @@ bool FECustomFilter::programNeedsInputTexture() const bool FECustomFilter::applyShader() { - Uint8ClampedArray* dstPixelArray = createUnmultipliedImageResult(); + Uint8ClampedArray* dstPixelArray = m_validatedProgram->programInfo().programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE ? createPremultipliedImageResult() : createUnmultipliedImageResult(); if (!dstPixelArray) return false; @@ -299,7 +300,8 @@ bool FECustomFilter::createMultisampleBuffer() m_triedMultisampleBuffer = true; Extensions3D* extensions = m_context->getExtensions(); - if (!extensions + if (!extensions + || !extensions->maySupportMultisampling() || !extensions->supports("GL_ANGLE_framebuffer_multisample") || !extensions->supports("GL_ANGLE_framebuffer_blit") || !extensions->supports("GL_OES_rgb8_rgba8")) @@ -569,18 +571,6 @@ void FECustomFilter::bindProgramAndBuffers(Platform3DObject inputTexture) m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_mesh->verticesBufferObject()); m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_mesh->elementsBufferObject()); - // FIXME: Ideally, these should be public members of CustomFilterMesh. - // https://bugs.webkit.org/show_bug.cgi?id=94755 - static const unsigned PositionAttribSize = 4; - static const unsigned TexAttribSize = 2; - static const unsigned MeshAttribSize = 2; - static const unsigned TriangleAttribSize = 3; - - static const unsigned PositionAttribOffset = 0; - static const unsigned TexAttribOffset = PositionAttribOffset + PositionAttribSize * sizeof(float); - static const unsigned MeshAttribOffset = TexAttribOffset + TexAttribSize * sizeof(float); - static const unsigned TriangleAttribOffset = MeshAttribOffset + MeshAttribSize * sizeof(float); - bindVertexAttribute(m_compiledProgram->positionAttribLocation(), PositionAttribSize, PositionAttribOffset); bindVertexAttribute(m_compiledProgram->texAttribLocation(), TexAttribSize, TexAttribOffset); // FIXME: Get rid of the internal tex coord attribute "css_a_texCoord". diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.h b/Source/WebCore/platform/graphics/filters/FECustomFilter.h index e4a2e41d3..09da5f1c7 100644 --- a/Source/WebCore/platform/graphics/filters/FECustomFilter.h +++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.h @@ -50,7 +50,6 @@ class CustomFilterCompiledProgram; class CustomFilterGlobalContext; class CustomFilterMesh; class CustomFilterNumberParameter; -class CustomFilterProgram; class CustomFilterTransformParameter; class CustomFilterValidatedProgram; class DrawingBuffer; @@ -128,7 +127,6 @@ private: Platform3DObject m_multisampleRenderBuffer; Platform3DObject m_multisampleDepthBuffer; - RefPtr<CustomFilterProgram> m_program; CustomFilterParameterList m_parameters; unsigned m_meshRows; diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp index 43731f70d..cb9562f69 100644 --- a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp +++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp @@ -171,29 +171,25 @@ inline void FEGaussianBlur::platformApply(Uint8ClampedArray* srcPixelArray, Uint int jobs = parallelJobs.numberOfJobs(); if (jobs > 1) { - int blockHeight = paintSize.height() / jobs; - --jobs; - for (int job = jobs; job >= 0; --job) { + // Split the job into "blockHeight"-sized jobs but there a few jobs that need to be slightly larger since + // blockHeight * jobs < total size. These extras are handled by the remainder "jobsWithExtra". + const int blockHeight = paintSize.height() / jobs; + const int jobsWithExtra = paintSize.height() % jobs; + + int currentY = 0; + for (int job = 0; job < jobs; job++) { PlatformApplyParameters& params = parallelJobs.parameter(job); params.filter = this; - int startY; - int endY; + int startY = !job ? 0 : currentY - extraHeight; + currentY += job < jobsWithExtra ? blockHeight + 1 : blockHeight; + int endY = job == jobs - 1 ? currentY : currentY + extraHeight; + + int blockSize = (endY - startY) * scanline; if (!job) { - startY = 0; - endY = blockHeight + extraHeight; params.srcPixelArray = srcPixelArray; params.dstPixelArray = tmpPixelArray; } else { - if (job == jobs) { - startY = job * blockHeight - extraHeight; - endY = paintSize.height(); - } else { - startY = job * blockHeight - extraHeight; - endY = (job + 1) * blockHeight + extraHeight; - } - - int blockSize = (endY - startY) * scanline; params.srcPixelArray = Uint8ClampedArray::createUninitialized(blockSize); params.dstPixelArray = Uint8ClampedArray::createUninitialized(blockSize); memcpy(params.srcPixelArray->data(), srcPixelArray->data() + startY * scanline, blockSize); @@ -208,20 +204,19 @@ inline void FEGaussianBlur::platformApply(Uint8ClampedArray* srcPixelArray, Uint parallelJobs.execute(); // Copy together the parts of the image. - for (int job = jobs; job >= 1; --job) { + currentY = 0; + for (int job = 1; job < jobs; job++) { PlatformApplyParameters& params = parallelJobs.parameter(job); int sourceOffset; int destinationOffset; int size; - if (job == jobs) { - sourceOffset = extraHeight * scanline; - destinationOffset = job * blockHeight * scanline; - size = (paintSize.height() - job * blockHeight) * scanline; - } else { - sourceOffset = extraHeight * scanline; - destinationOffset = job * blockHeight * scanline; - size = blockHeight * scanline; - } + int adjustedBlockHeight = job < jobsWithExtra ? blockHeight + 1 : blockHeight; + + currentY += adjustedBlockHeight; + sourceOffset = extraHeight * scanline; + destinationOffset = currentY * scanline; + size = adjustedBlockHeight * scanline; + memcpy(srcPixelArray->data() + destinationOffset, params.srcPixelArray->data() + sourceOffset, size); } return; diff --git a/Source/WebCore/platform/graphics/filters/FELighting.cpp b/Source/WebCore/platform/graphics/filters/FELighting.cpp index bcb3c165e..1a8180334 100644 --- a/Source/WebCore/platform/graphics/filters/FELighting.cpp +++ b/Source/WebCore/platform/graphics/filters/FELighting.cpp @@ -257,19 +257,20 @@ inline void FELighting::platformApplyGeneric(LightingData& data, LightSource::Pa // Fill the parameter array int job = parallelJobs.numberOfJobs(); if (job > 1) { + // Split the job into "yStep"-sized jobs but there a few jobs that need to be slightly larger since + // yStep * jobs < total size. These extras are handled by the remainder "jobsWithExtra". + const int yStep = (data.heightDecreasedByOne - 1) / job; + const int jobsWithExtra = (data.heightDecreasedByOne - 1) % job; + int yStart = 1; - int yStep = (data.heightDecreasedByOne - 1) / job; for (--job; job >= 0; --job) { PlatformApplyGenericParameters& params = parallelJobs.parameter(job); params.filter = this; params.data = data; params.paintingData = paintingData; params.yStart = yStart; - if (job > 0) { - params.yEnd = yStart + yStep; - yStart += yStep; - } else - params.yEnd = data.heightDecreasedByOne; + yStart += job < jobsWithExtra ? yStep + 1 : yStep; + params.yEnd = yStart; } parallelJobs.execute(); return; diff --git a/Source/WebCore/platform/graphics/filters/FEMorphology.cpp b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp index 98d2a6a01..9e720f74a 100644 --- a/Source/WebCore/platform/graphics/filters/FEMorphology.cpp +++ b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp @@ -173,14 +173,17 @@ void FEMorphology::platformApply(PaintingData* paintingData) ParallelJobs<PlatformApplyParameters> parallelJobs(&WebCore::FEMorphology::platformApplyWorker, optimalThreadNumber); int numOfThreads = parallelJobs.numberOfJobs(); if (numOfThreads > 1) { - const int deltaY = 1 + paintingData->height / numOfThreads; + // Split the job into "jobSize"-sized jobs but there a few jobs that need to be slightly larger since + // jobSize * jobs < total size. These extras are handled by the remainder "jobsWithExtra". + const int jobSize = paintingData->height / numOfThreads; + const int jobsWithExtra = paintingData->height % numOfThreads; int currentY = 0; for (int job = numOfThreads - 1; job >= 0; --job) { PlatformApplyParameters& param = parallelJobs.parameter(job); param.filter = this; param.startY = currentY; - currentY += deltaY; - param.endY = job ? currentY : paintingData->height; + currentY += job < jobsWithExtra ? jobSize + 1 : jobSize; + param.endY = currentY; param.paintingData = paintingData; } parallelJobs.execute(); diff --git a/Source/WebCore/platform/graphics/filters/FETurbulence.cpp b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp index 03df56b30..17688746f 100644 --- a/Source/WebCore/platform/graphics/filters/FETurbulence.cpp +++ b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp @@ -376,19 +376,20 @@ void FETurbulence::platformApplySoftware() // Fill the parameter array int i = parallelJobs.numberOfJobs(); if (i > 1) { + // Split the job into "stepY"-sized jobs but there a few jobs that need to be slightly larger since + // stepY * jobs < total size. These extras are handled by the remainder "jobsWithExtra". + const int stepY = absolutePaintRect().height() / i; + const int jobsWithExtra = absolutePaintRect().height() % i; + int startY = 0; - int stepY = absolutePaintRect().height() / i; for (; i > 0; --i) { FillRegionParameters& params = parallelJobs.parameter(i-1); params.filter = this; params.pixelArray = pixelArray; params.paintingData = &paintingData; params.startY = startY; - if (i != 1) { - params.endY = startY + stepY; - startY = startY + stepY; - } else - params.endY = absolutePaintRect().height(); + startY += i < jobsWithExtra ? stepY + 1 : stepY; + params.endY = startY; } // Execute parallel jobs diff --git a/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h b/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h index 50f34b77a..2354dfc80 100644 --- a/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h +++ b/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h @@ -27,8 +27,6 @@ #ifndef FECompositeArithmeticNEON_h #define FECompositeArithmeticNEON_h -#include <wtf/Platform.h> - #if ENABLE(FILTERS) && HAVE(ARM_NEON_INTRINSICS) #include "FEComposite.h" diff --git a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h index 93b46cfd3..3779c2ec5 100644 --- a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h +++ b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h @@ -27,8 +27,6 @@ #ifndef FEGaussianBlurNEON_h #define FEGaussianBlurNEON_h -#include <wtf/Platform.h> - #if ENABLE(FILTERS) && HAVE(ARM_NEON_INTRINSICS) #include "FEGaussianBlur.h" @@ -37,13 +35,14 @@ namespace WebCore { inline void boxBlurNEON(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dstPixelArray, - unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight) + unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight) { 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; + int pixelStride = stride / 4; for (int y = 0; y < effectHeight; ++y) { int line = y * pixelLine; @@ -51,21 +50,21 @@ inline void boxBlurNEON(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dst // Fill the kernel int maxKernelSize = std::min(dxRight, effectWidth); for (int i = 0; i < maxKernelSize; ++i) { - float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + line + i); + float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + line + i * pixelStride); sum = vaddq_f32(sum, sourcePixelAsFloat); } // Blurring for (int x = 0; x < effectWidth; ++x) { - int pixelOffset = line + x; + int pixelOffset = line + x * pixelStride; float32x4_t result = vmulq_f32(sum, deltaX); - storeFloatAsRGBA8(result, destinationPixel+pixelOffset); + storeFloatAsRGBA8(result, destinationPixel + pixelOffset); if (x >= dxLeft) { - float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + pixelOffset - dxLeft); + float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + pixelOffset - dxLeft * pixelStride); sum = vsubq_f32(sum, sourcePixelAsFloat); } if (x + dxRight < effectWidth) { - float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + pixelOffset + dxRight); + float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + pixelOffset + dxRight * pixelStride); sum = vaddq_f32(sum, sourcePixelAsFloat); } } diff --git a/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h index 13c975c09..682922f50 100644 --- a/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h +++ b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h @@ -27,8 +27,6 @@ #ifndef FELightingNeon_h #define FELightingNeon_h -#include <wtf/Platform.h> - #if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC) #include "FELighting.h" diff --git a/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp b/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp index 490517867..3e6bcfa9a 100644 --- a/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp +++ b/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp @@ -81,7 +81,7 @@ FcPattern* findBestFontGivenFallbacks(const FontPlatformData& fontData, FcPatter return FcFontSetMatch(0, sets, 1, pattern, &fontConfigResult); } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { RefPtr<FcPattern> pattern = adoptRef(createFontConfigPatternForCharacters(characters, length)); const FontPlatformData& fontData = font.primaryFont()->platformData(); @@ -100,12 +100,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return getCachedFontData(&alternateFontData, DoNotRetain); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font&) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font&) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { // We want to return a fallback font here, otherwise the logic preventing FontConfig // matches for non-fallback fonts might return 0. See isFallbackFontAllowed. diff --git a/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp b/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp index d7d224264..30d889f5c 100644 --- a/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp +++ b/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp @@ -42,7 +42,9 @@ #include <cairo-ft.h> #include <cairo.h> #include <fontconfig/fcfreetype.h> +#include <unicode/normlzr.h> #include <wtf/MathExtras.h> +#include <wtf/unicode/Unicode.h> namespace WebCore { @@ -87,17 +89,16 @@ void SimpleFontData::platformDestroy() { } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { ASSERT(m_platformData.scaledFont()); - return adoptPtr(new SimpleFontData(FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()), + return SimpleFontData::create(FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()), scaleFactor * fontDescription.computedSize(), m_platformData.syntheticBold(), - m_platformData.syntheticOblique()), - isCustomFont(), false)); + m_platformData.syntheticOblique()), isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); @@ -105,17 +106,17 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const @@ -172,4 +173,33 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const return w; } +#if USE(HARFBUZZ_NG) +bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters, size_t length) const +{ + if (!m_combiningCharacterSequenceSupport) + m_combiningCharacterSequenceSupport = adoptPtr(new HashMap<String, bool>); + + WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false); + if (!addResult.isNewEntry) + return addResult.iterator->value; + + UErrorCode error = U_ZERO_ERROR; + Vector<UChar, 4> normalizedCharacters(length); + int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], length, &error); + // Can't render if we have an error or no composition occurred. + if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length)) + return false; + + FT_Face face = cairo_ft_scaled_font_lock_face(m_platformData.scaledFont()); + if (!face) + return false; + + if (FcFreeTypeCharIndex(face, normalizedCharacters[0])) + addResult.iterator->value = true; + + cairo_ft_scaled_font_unlock_face(m_platformData.scaledFont()); + return addResult.iterator->value; +} +#endif + } diff --git a/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp b/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp index 9540b86a0..31f32cf0b 100644 --- a/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp +++ b/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp @@ -27,71 +27,9 @@ namespace WebCore { -// We do not want to call glXMakeContextCurrent using different Display pointers, -// because it might lead to crashes in some drivers (fglrx). We use a shared display -// pointer here. -static Display* gSharedDisplay = 0; -Display* GLContextGLX::sharedDisplay() -{ - if (!gSharedDisplay) - gSharedDisplay = XOpenDisplay(0); - return gSharedDisplay; -} - -// Because of driver bugs, exiting the program when there are active pbuffers -// can crash the X server (this has been observed with the official Nvidia drivers). -// We need to ensure that we clean everything up on exit. There are several reasons -// that GraphicsContext3Ds will still be alive at exit, including user error (memory -// leaks) and the page cache. In any case, we don't want the X server to crash. -typedef Vector<GLContext*> ActiveContextList; -static ActiveContextList& activeContextList() -{ - DEFINE_STATIC_LOCAL(ActiveContextList, activeContexts, ()); - return activeContexts; -} - -void GLContextGLX::addActiveContext(GLContextGLX* context) -{ - static bool addedAtExitHandler = false; - if (!addedAtExitHandler) { - atexit(&GLContextGLX::cleanupActiveContextsAtExit); - addedAtExitHandler = true; - } - activeContextList().append(context); -} - -static bool gCleaningUpAtExit = false; - -void GLContextGLX::removeActiveContext(GLContext* context) -{ - // If we are cleaning up the context list at exit, don't bother removing the context - // from the list, since we don't want to modify the list while it's being iterated. - if (gCleaningUpAtExit) - return; - - ActiveContextList& contextList = activeContextList(); - size_t i = contextList.find(context); - if (i != notFound) - contextList.remove(i); -} - -void GLContextGLX::cleanupActiveContextsAtExit() -{ - gCleaningUpAtExit = true; - - ActiveContextList& contextList = activeContextList(); - for (size_t i = 0; i < contextList.size(); ++i) - delete contextList[i]; - - if (!gSharedDisplay) - return; - XCloseDisplay(gSharedDisplay); - gSharedDisplay = 0; -} - PassOwnPtr<GLContextGLX> GLContextGLX::createWindowContext(XID window, GLContext* sharingContext) { - Display* display = sharedDisplay(); + Display* display = sharedX11Display(); XWindowAttributes attributes; if (!XGetWindowAttributes(display, window, &attributes)) return nullptr; @@ -130,7 +68,7 @@ PassOwnPtr<GLContextGLX> GLContextGLX::createPbufferContext(GLXContext sharingCo }; int returnedElements; - Display* display = sharedDisplay(); + Display* display = sharedX11Display(); GLXFBConfig* configs = glXChooseFBConfig(display, 0, fbConfigAttributes, &returnedElements); if (!returnedElements) { XFree(configs); @@ -170,7 +108,7 @@ PassOwnPtr<GLContextGLX> GLContextGLX::createPixmapContext(GLXContext sharingCon 0 }; - Display* display = sharedDisplay(); + Display* display = sharedX11Display(); XVisualInfo* visualInfo = glXChooseVisual(display, DefaultScreen(display), visualAttributes); if (!visualInfo) return nullptr; @@ -200,7 +138,7 @@ PassOwnPtr<GLContextGLX> GLContextGLX::createPixmapContext(GLXContext sharingCon PassOwnPtr<GLContextGLX> GLContextGLX::createContext(XID window, GLContext* sharingContext) { - if (!sharedDisplay()) + if (!sharedX11Display()) return nullptr; static bool initialized = false; @@ -231,7 +169,6 @@ GLContextGLX::GLContextGLX(GLXContext context) , m_pixmap(0) , m_glxPixmap(0) { - addActiveContext(this); } GLContextGLX::GLContextGLX(GLXContext context, Pixmap pixmap, GLXPixmap glxPixmap) @@ -241,7 +178,6 @@ GLContextGLX::GLContextGLX(GLXContext context, Pixmap pixmap, GLXPixmap glxPixma , m_pixmap(pixmap) , m_glxPixmap(glxPixmap) { - addActiveContext(this); } GLContextGLX::~GLContextGLX() @@ -250,23 +186,22 @@ GLContextGLX::~GLContextGLX() // This may be necessary to prevent crashes with NVidia's closed source drivers. Originally // from Mozilla's 3D canvas implementation at: http://bitbucket.org/ilmari/canvas3d/ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glXMakeCurrent(sharedDisplay(), None, None); - glXDestroyContext(sharedDisplay(), m_context); + glXMakeCurrent(sharedX11Display(), None, None); + glXDestroyContext(sharedX11Display(), m_context); } if (m_pbuffer) { - glXDestroyPbuffer(sharedDisplay(), m_pbuffer); + glXDestroyPbuffer(sharedX11Display(), m_pbuffer); m_pbuffer = 0; } if (m_glxPixmap) { - glXDestroyGLXPixmap(sharedDisplay(), m_glxPixmap); + glXDestroyGLXPixmap(sharedX11Display(), m_glxPixmap); m_glxPixmap = 0; } if (m_pixmap) { - XFreePixmap(sharedDisplay(), m_pixmap); + XFreePixmap(sharedX11Display(), m_pixmap); m_pixmap = 0; } - removeActiveContext(this); } bool GLContextGLX::canRenderToDefaultFramebuffer() @@ -282,7 +217,7 @@ IntSize GLContextGLX::defaultFrameBufferSize() int x, y; Window rootWindow; unsigned int width, height, borderWidth, depth; - if (!XGetGeometry(sharedDisplay(), m_window, &rootWindow, &x, &y, &width, &height, &borderWidth, &depth)) + if (!XGetGeometry(sharedX11Display(), m_window, &rootWindow, &x, &y, &width, &height, &borderWidth, &depth)) return IntSize(); return IntSize(width, height); @@ -297,18 +232,23 @@ bool GLContextGLX::makeContextCurrent() return true; if (m_window) - return glXMakeCurrent(sharedDisplay(), m_window, m_context); + return glXMakeCurrent(sharedX11Display(), m_window, m_context); if (m_pbuffer) - return glXMakeCurrent(sharedDisplay(), m_pbuffer, m_context); + return glXMakeCurrent(sharedX11Display(), m_pbuffer, m_context); - return ::glXMakeCurrent(sharedDisplay(), m_glxPixmap, m_context); + return ::glXMakeCurrent(sharedX11Display(), m_glxPixmap, m_context); } void GLContextGLX::swapBuffers() { if (m_window) - glXSwapBuffers(sharedDisplay(), m_window); + glXSwapBuffers(sharedX11Display(), m_window); +} + +void GLContextGLX::waitNative() +{ + glXWaitX(); } #if USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/glx/GLContextGLX.h b/Source/WebCore/platform/graphics/glx/GLContextGLX.h index b3b18c156..00f56e791 100644 --- a/Source/WebCore/platform/graphics/glx/GLContextGLX.h +++ b/Source/WebCore/platform/graphics/glx/GLContextGLX.h @@ -25,7 +25,6 @@ #include "GLContext.h" typedef struct __GLXcontextRec* GLXContext; -typedef struct _XDisplay Display; typedef struct __GLXcontextRec *GLXContext; typedef unsigned long GLXPbuffer; typedef unsigned long GLXPixmap; @@ -45,11 +44,10 @@ public: virtual ~GLContextGLX(); virtual bool makeContextCurrent(); virtual void swapBuffers(); + virtual void waitNative(); virtual bool canRenderToDefaultFramebuffer(); virtual IntSize defaultFrameBufferSize(); - static Display* sharedDisplay(); - #if USE(3D_GRAPHICS) virtual PlatformGraphicsContext3D platformContext(); #endif @@ -57,10 +55,6 @@ public: private: static PassOwnPtr<GLContextGLX> createPbufferContext(GLXContext sharingContext); static PassOwnPtr<GLContextGLX> createPixmapContext(GLXContext sharingContext); - static void removeActiveContext(GLContext*); - - static void addActiveContext(GLContextGLX*); - static void cleanupActiveContextsAtExit(); GLContextGLX(GLXContext); GLContextGLX(GLXContext, Pixmap, GLXPixmap); diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp index fe51104f0..282bde03f 100644 --- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp +++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp @@ -54,7 +54,10 @@ static const float s_resourceAdjustedRatio = 0.5; PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size, PreserveDrawingBuffer preserve, AlphaRequirement alpha) { Extensions3D* extensions = context->getExtensions(); - bool multisampleSupported = extensions->supports("GL_ANGLE_framebuffer_blit") && extensions->supports("GL_ANGLE_framebuffer_multisample") && extensions->supports("GL_OES_rgb8_rgba8"); + bool multisampleSupported = extensions->maySupportMultisampling() + && extensions->supports("GL_ANGLE_framebuffer_blit") + && extensions->supports("GL_ANGLE_framebuffer_multisample") + && extensions->supports("GL_OES_rgb8_rgba8"); if (multisampleSupported) { extensions->ensureEnabled("GL_ANGLE_framebuffer_blit"); extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h index 9904242e4..b2c59aae6 100644 --- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h +++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h @@ -32,9 +32,9 @@ #define DrawingBuffer_h #include "GraphicsContext3D.h" -#include "GraphicsLayer.h" #include "GraphicsTypes3D.h" #include "IntSize.h" +#include "PlatformLayer.h" #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> diff --git a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp index 37468bc5c..deeb339d2 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp @@ -86,6 +86,12 @@ template <> void derefGPtr<GstPadTemplate>(GstPadTemplate* ptr) gst_object_unref(GST_OBJECT(ptr)); } +template <> GRefPtr<GstCaps> adoptGRef(GstCaps* ptr) +{ + ASSERT(!ptr || !gstObjectIsFloating(GST_OBJECT(ptr))); + return GRefPtr<GstCaps>(ptr, GRefPtrAdopt); +} + template <> GstCaps* refGPtr<GstCaps>(GstCaps* ptr) { if (ptr) diff --git a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h index a3dcda8ae..5b0ed0db2 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h +++ b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h @@ -45,6 +45,7 @@ template<> GRefPtr<GstPadTemplate> adoptGRef(GstPadTemplate* ptr); template<> GstPadTemplate* refGPtr<GstPadTemplate>(GstPadTemplate* ptr); template<> void derefGPtr<GstPadTemplate>(GstPadTemplate* ptr); +template<> GRefPtr<GstCaps> adoptGRef(GstCaps* ptr); template<> GstCaps* refGPtr<GstCaps>(GstCaps* ptr); template<> void derefGPtr<GstCaps>(GstCaps* ptr); diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.cpp b/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.cpp index 3c3f367b9..638f480ff 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.cpp @@ -34,20 +34,19 @@ void webkitGstObjectRefSink(GstObject* gstObject) #endif } -GstCaps* webkitGstGetPadCaps(GstPad* pad) +GRefPtr<GstCaps> webkitGstGetPadCaps(GstPad* pad) { if (!pad) return 0; - GstCaps* caps; #ifdef GST_API_VERSION_1 - caps = gst_pad_get_current_caps(pad); + GstCaps* caps = gst_pad_get_current_caps(pad); if (!caps) caps = gst_pad_query_caps(pad, 0); + return adoptGRef(caps); // gst_pad_query_caps and gst_pad_get_current_caps return a new reference. #else - caps = GST_PAD_CAPS(pad); + return GST_PAD_CAPS(pad); #endif - return caps; } bool getVideoSizeAndFormatFromCaps(GstCaps* caps, WebCore::IntSize& size, GstVideoFormat& format, int& pixelAspectRatioNumerator, int& pixelAspectRatioDenominator, int& stride) diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.h b/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.h index a8e5182f6..2ecf08cef 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.h +++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.h @@ -20,6 +20,7 @@ #ifndef GStreamerVersioning_h #define GStreamerVersioning_h +#include "GRefPtrGStreamer.h" #include <gst/gst.h> #include <gst/video/video.h> @@ -28,7 +29,7 @@ class IntSize; }; void webkitGstObjectRefSink(GstObject*); -GstCaps* webkitGstGetPadCaps(GstPad*); +GRefPtr<GstCaps> webkitGstGetPadCaps(GstPad*); bool getVideoSizeAndFormatFromCaps(GstCaps*, WebCore::IntSize&, GstVideoFormat&, int& pixelAspectRatioNumerator, int& pixelAspectRatioDenominator, int& stride); GstBuffer* createGstBuffer(GstBuffer*); void setGstElementClassMetadata(GstElementClass*, const char* name, const char* longName, const char* description, const char* author); diff --git a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h index 7a0e5ee56..83bdfe2b7 100644 --- a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h +++ b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h @@ -29,10 +29,6 @@ #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> -#if PLATFORM(QT) -#include <QImage> -#endif - namespace WebCore { class IntSize; diff --git a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp index d6e6e2afc..375026d1f 100644 --- a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp @@ -67,8 +67,9 @@ ImageGStreamer::ImageGStreamer(GstBuffer* buffer, GstCaps* caps) #if G_BYTE_ORDER == G_LITTLE_ENDIAN image.invertPixels(invertMode); #endif - - m_image = BitmapImage::create(new QImage(image)); + QPixmap* surface = new QPixmap; + surface->convertFromImage(image); + m_image = BitmapImage::create(surface); #ifdef GST_API_VERSION_1 if (GstVideoCropMeta* cropMeta = gst_buffer_get_video_crop_meta(buffer)) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index 6f5736baa..a4d47451d 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -540,7 +540,7 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const if (!m_videoSize.isEmpty()) return m_videoSize; - GstCaps* caps = webkitGstGetPadCaps(m_videoSinkPad.get()); + GRefPtr<GstCaps> caps = webkitGstGetPadCaps(m_videoSinkPad.get()); if (!caps) return IntSize(); @@ -555,7 +555,7 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const int pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride; IntSize originalSize; GstVideoFormat format; - if (!getVideoSizeAndFormatFromCaps(caps, originalSize, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) + if (!getVideoSizeAndFormatFromCaps(caps.get(), originalSize, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) return IntSize(); LOG_MEDIA_MESSAGE("Original video size: %dx%d", originalSize.width(), originalSize.height()); @@ -1566,11 +1566,11 @@ void MediaPlayerPrivateGStreamer::paint(GraphicsContext* context, const IntRect& if (!m_buffer) return; - GstCaps* caps = webkitGstGetPadCaps(m_videoSinkPad.get()); + GRefPtr<GstCaps> caps = webkitGstGetPadCaps(m_videoSinkPad.get()); if (!caps) return; - RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_buffer, caps); + RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_buffer, caps.get()); if (!gstImage) return; diff --git a/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp index c2c0bd4e4..d852184c0 100644 --- a/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp @@ -29,6 +29,7 @@ #if USE(GSTREAMER) #include "VideoSinkGStreamer.h" +#include "GRefPtrGStreamer.h" #include "GStreamerVersioning.h" #include "IntSize.h" #include <glib.h> @@ -172,27 +173,20 @@ static GstFlowReturn webkitVideoSinkRender(GstBaseSink* baseSink, GstBuffer* buf gst_buffer_set_caps(priv->buffer, GST_PAD_CAPS(GST_BASE_SINK_PAD(baseSink))); } - GstCaps* caps = GST_BUFFER_CAPS(buffer); + GRefPtr<GstCaps> caps = GST_BUFFER_CAPS(buffer); #else - GstCaps* caps = gst_video_info_to_caps(&priv->info); + GRefPtr<GstCaps> caps = adoptGRef(gst_video_info_to_caps(&priv->info)); #endif GstVideoFormat format; WebCore::IntSize size; int pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride; - if (!getVideoSizeAndFormatFromCaps(caps, size, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) { + if (!getVideoSizeAndFormatFromCaps(caps.get(), size, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) { gst_buffer_unref(buffer); -#ifdef GST_API_VERSION_1 - gst_caps_unref(caps); -#endif g_mutex_unlock(priv->bufferMutex); return GST_FLOW_ERROR; } -#ifdef GST_API_VERSION_1 - gst_caps_unref(caps); -#endif - // Cairo's ARGB has pre-multiplied alpha while GStreamer's doesn't. // Here we convert to Cairo's ARGB. if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA) { diff --git a/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp b/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp index 9401b0135..8a4d8720c 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp @@ -70,8 +70,6 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru // padding and fallback if we find that we are wrong. createGlyphArrays((m_normalizedBufferLength + 2) * 2); - m_item.log_clusters = new unsigned short[m_normalizedBufferLength]; - m_item.face = 0; m_item.font = allocHarfbuzzFont(); @@ -90,7 +88,6 @@ ComplexTextController::~ComplexTextController() { fastFree(m_item.font); deleteGlyphArrays(); - delete[] m_item.log_clusters; } void ComplexTextController::reset(int offset) @@ -299,6 +296,7 @@ void ComplexTextController::deleteGlyphArrays() delete[] m_item.attributes; delete[] m_item.advances; delete[] m_item.offsets; + delete[] m_item.log_clusters; delete[] m_glyphs16; delete[] m_positions; } @@ -309,6 +307,7 @@ void ComplexTextController::createGlyphArrays(int size) m_item.attributes = new HB_GlyphAttributes[size]; m_item.advances = new HB_Fixed[size]; m_item.offsets = new HB_FixedPoint[size]; + m_item.log_clusters = new unsigned short[size]; m_glyphs16 = new uint16_t[size]; m_positions = new SkPoint[size]; diff --git a/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp b/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp index 2d9e86a35..b9d5fc8e8 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp @@ -350,16 +350,12 @@ static SkFontTableTag reverseByteOrder(uint32_t tableTag) const OpenTypeVerticalData* FontPlatformData::verticalData() const { - if (!uniqueID()) - return 0; return fontCache()->getVerticalData(uniqueID(), *this); } PassRefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const { RefPtr<SharedBuffer> buffer; - if (!uniqueID()) - return buffer.release(); SkFontTableTag tag = reverseByteOrder(table); const size_t tableSize = SkFontHost::GetTableSize(uniqueID(), tag); diff --git a/Source/WebCore/platform/graphics/harfbuzz/HarfBuzzSkia.cpp b/Source/WebCore/platform/graphics/harfbuzz/HarfBuzzSkia.cpp index f68ea6192..1e8867bb7 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/HarfBuzzSkia.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/HarfBuzzSkia.cpp @@ -244,18 +244,18 @@ static HB_FaceRec_* getCachedHarfbuzzFace(FontPlatformData* platformData) gHarfbuzzFaceCache->set(uniqueID, entry); return entry.first; } - ++(result.get()->second.second); - return result.get()->second.first; + ++(result.get()->value.second); + return result.get()->value.first; } static void releaseCachedHarfbuzzFace(SkFontID uniqueID) { HarfbuzzFaceCache::iterator result = gHarfbuzzFaceCache->find(uniqueID); ASSERT(result != gHarfbuzzFaceCache->end()); - ASSERT(result.get()->second.second > 0); - --(result.get()->second.second); - if (!(result.get()->second.second)) { - HB_FreeFace(result.get()->second.first); + ASSERT(result.get()->value.second > 0); + --(result.get()->value.second); + if (!(result.get()->value.second)) { + HB_FreeFace(result.get()->value.first); gHarfbuzzFaceCache->remove(uniqueID); } } diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp index 7dd048b3b..50dbd81bd 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp @@ -32,17 +32,44 @@ #include "HarfBuzzNGFace.h" #include "FontPlatformData.h" +#include "hb-ot.h" #include "hb.h" -#include <wtf/HashMap.h> namespace WebCore { +const hb_tag_t HarfBuzzNGFace::vertTag = HB_TAG('v', 'e', 'r', 't'); +const hb_tag_t HarfBuzzNGFace::vrt2Tag = HB_TAG('v', 'r', 't', '2'); + // Though we have FontCache class, which provides the cache mechanism for // WebKit's font objects, we also need additional caching layer for HarfBuzz // to reduce the memory consumption because hb_face_t should be associated with // underling font data (e.g. CTFontRef, FTFace). -typedef pair<hb_face_t*, unsigned> FaceCacheEntry; -typedef HashMap<uint64_t, FaceCacheEntry, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t> > HarfBuzzNGFaceCache; + +class FaceCacheEntry : public RefCounted<FaceCacheEntry> { +public: + static PassRefPtr<FaceCacheEntry> create(hb_face_t* face) + { + ASSERT(face); + return adoptRef(new FaceCacheEntry(face)); + } + ~FaceCacheEntry() + { + hb_face_destroy(m_face); + } + + hb_face_t* face() { return m_face; } + HashMap<uint32_t, uint16_t>* glyphCache() { return &m_glyphCache; } + +private: + explicit FaceCacheEntry(hb_face_t* face) + : m_face(face) + { } + + hb_face_t* m_face; + HashMap<uint32_t, uint16_t> m_glyphCache; +}; + +typedef HashMap<uint64_t, RefPtr<FaceCacheEntry>, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t> > HarfBuzzNGFaceCache; static HarfBuzzNGFaceCache* harfbuzzFaceCache() { @@ -53,28 +80,52 @@ static HarfBuzzNGFaceCache* harfbuzzFaceCache() HarfBuzzNGFace::HarfBuzzNGFace(FontPlatformData* platformData, uint64_t uniqueID) : m_platformData(platformData) , m_uniqueID(uniqueID) + , m_scriptForVerticalText(HB_SCRIPT_INVALID) { - HarfBuzzNGFaceCache::iterator result = harfbuzzFaceCache()->find(m_uniqueID); - if (result == harfbuzzFaceCache()->end()) { - m_face = createFace(); - ASSERT(m_face); - harfbuzzFaceCache()->set(m_uniqueID, FaceCacheEntry(m_face, 1)); - } else { - ++(result.get()->second.second); - m_face = result.get()->second.first; - } + HarfBuzzNGFaceCache::AddResult result = harfbuzzFaceCache()->add(m_uniqueID, 0); + if (result.isNewEntry) + result.iterator->value = FaceCacheEntry::create(createFace()); + result.iterator->value->ref(); + m_face = result.iterator->value->face(); + m_glyphCacheForFaceCacheEntry = result.iterator->value->glyphCache(); } HarfBuzzNGFace::~HarfBuzzNGFace() { HarfBuzzNGFaceCache::iterator result = harfbuzzFaceCache()->find(m_uniqueID); ASSERT(result != harfbuzzFaceCache()->end()); - ASSERT(result.get()->second.second > 0); - --(result.get()->second.second); - if (!(result.get()->second.second)) { - hb_face_destroy(result.get()->second.first); + ASSERT(result.get()->value->refCount() > 1); + result.get()->value->deref(); + if (result.get()->value->refCount() == 1) harfbuzzFaceCache()->remove(m_uniqueID); +} + +static hb_script_t findScriptForVerticalGlyphSubstitution(hb_face_t* face) +{ + static const unsigned maxCount = 32; + + unsigned scriptCount = maxCount; + hb_tag_t scriptTags[maxCount]; + hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCount, scriptTags); + for (unsigned scriptIndex = 0; scriptIndex < scriptCount; ++scriptIndex) { + unsigned languageCount = maxCount; + hb_tag_t languageTags[maxCount]; + hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, scriptIndex, 0, &languageCount, languageTags); + for (unsigned languageIndex = 0; languageIndex < languageCount; ++languageIndex) { + unsigned featureIndex; + if (hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzNGFace::vertTag, &featureIndex) + || hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzNGFace::vrt2Tag, &featureIndex)) + return hb_ot_tag_to_script(scriptTags[scriptIndex]); + } } + return HB_SCRIPT_INVALID; +} + +void HarfBuzzNGFace::setScriptForVerticalGlyphSubstitution(hb_buffer_t* buffer) +{ + if (m_scriptForVerticalText == HB_SCRIPT_INVALID) + m_scriptForVerticalText = findScriptForVerticalGlyphSubstitution(m_face); + hb_buffer_set_script(buffer, m_scriptForVerticalText); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h index cbc8f8ed4..360daf9cf 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h @@ -33,6 +33,7 @@ #include <hb.h> +#include <wtf/HashMap.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -43,6 +44,9 @@ class FontPlatformData; class HarfBuzzNGFace : public RefCounted<HarfBuzzNGFace> { public: + static const hb_tag_t vertTag; + static const hb_tag_t vrt2Tag; + static PassRefPtr<HarfBuzzNGFace> create(FontPlatformData* platformData, uint64_t uniqueID) { return adoptRef(new HarfBuzzNGFace(platformData, uniqueID)); @@ -51,6 +55,8 @@ public: hb_font_t* createFont(); + void setScriptForVerticalGlyphSubstitution(hb_buffer_t*); + private: HarfBuzzNGFace(FontPlatformData*, uint64_t); @@ -59,6 +65,9 @@ private: FontPlatformData* m_platformData; uint64_t m_uniqueID; hb_face_t* m_face; + WTF::HashMap<uint32_t, uint16_t>* m_glyphCacheForFaceCacheEntry; + + hb_script_t m_scriptForVerticalText; }; } diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp index 52fca7baf..2db3d2780 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp @@ -155,9 +155,7 @@ static hb_font_funcs_t* harfbuzzCairoTextGetFontFuncs() static hb_blob_t* harfbuzzCairoGetTable(hb_face_t*, hb_tag_t tag, void* userData) { - FontPlatformData* font = reinterpret_cast<FontPlatformData*>(userData); - - cairo_scaled_font_t* scaledFont = font->scaledFont(); + cairo_scaled_font_t* scaledFont = reinterpret_cast<cairo_scaled_font_t*>(userData); if (!scaledFont) return 0; @@ -186,7 +184,7 @@ static hb_blob_t* harfbuzzCairoGetTable(hb_face_t*, hb_tag_t tag, void* userData hb_face_t* HarfBuzzNGFace::createFace() { - hb_face_t* face = hb_face_create_for_tables(harfbuzzCairoGetTable, m_platformData, 0); + hb_face_t* face = hb_face_create_for_tables(harfbuzzCairoGetTable, m_platformData->scaledFont(), 0); ASSERT(face); return face; } diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp index f2baba73f..e4c65cd41 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp @@ -108,10 +108,7 @@ 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); - // 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(); + CGFontRef cgFont = reinterpret_cast<CGFontRef>(userData); CFDataRef cfData = CGFontCopyTableForTag(cgFont, tag); if (!cfData) return 0; @@ -125,7 +122,9 @@ static hb_blob_t* harfbuzzCoreTextGetTable(hb_face_t* face, hb_tag_t tag, void* hb_face_t* HarfBuzzNGFace::createFace() { - hb_face_t* face = hb_face_create_for_tables(harfbuzzCoreTextGetTable, m_platformData, 0); + // It seems that CTFontCopyTable of MacOSX10.5 sdk doesn't work for + // OpenType layout tables(GDEF, GSUB, GPOS). Use CGFontCopyTableForTag instead. + hb_face_t* face = hb_face_create_for_tables(harfbuzzCoreTextGetTable, m_platformData->cgFont(), 0); ASSERT(face); return face; } diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp index 53acb292c..5d39efa73 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp @@ -43,12 +43,21 @@ #include "SkUtils.h" #include "hb.h" +#include <wtf/HashMap.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. +struct HarfBuzzFontData { + HarfBuzzFontData(WTF::HashMap<uint32_t, uint16_t>* glyphCacheForFaceCacheEntry) + : m_glyphCacheForFaceCacheEntry(glyphCacheForFaceCacheEntry) + { } + SkPaint m_paint; + WTF::HashMap<uint32_t, uint16_t>* m_glyphCacheForFaceCacheEntry; +}; + static hb_position_t SkiaScalarToHarfbuzzPosition(SkScalar value) { return SkScalarToFixed(value); @@ -56,8 +65,7 @@ static hb_position_t SkiaScalarToHarfbuzzPosition(SkScalar value) static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint, hb_position_t* width, hb_glyph_extents_t* extents) { - if (codepoint > 0xFFFF) - return; + ASSERT(codepoint <= 0xFFFF); paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); SkScalar skWidth; @@ -78,23 +86,27 @@ static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint 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; + HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); + + WTF::HashMap<uint32_t, uint16_t>::AddResult result = hbFontData->m_glyphCacheForFaceCacheEntry->add(unicode, 0); + if (result.isNewEntry) { + SkPaint* paint = &hbFontData->m_paint; + paint->setTextEncoding(SkPaint::kUTF32_TextEncoding); + uint16_t glyph16; + paint->textToGlyphs(&unicode, sizeof(hb_codepoint_t), &glyph16); + result.iterator->value = glyph16; + *glyph = glyph16; + } + *glyph = result.iterator->value; 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); + HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); hb_position_t advance = 0; - SkiaGetGlyphWidthAndExtents(paint, glyph, &advance, 0); + SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, &advance, 0); return advance; } @@ -107,9 +119,9 @@ static hb_bool_t harfbuzzGetGlyphHorizontalOrigin(hb_font_t* hbFont, void* fontD 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); + HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); - SkiaGetGlyphWidthAndExtents(paint, glyph, 0, extents); + SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, 0, extents); return true; } @@ -132,16 +144,16 @@ static hb_font_funcs_t* harfbuzzSkiaGetFontFuncs() static hb_blob_t* harfbuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* userData) { - FontPlatformData* font = reinterpret_cast<FontPlatformData*>(userData); + SkFontID uniqueID = static_cast<SkFontID>(reinterpret_cast<uint64_t>(userData)); - const size_t tableSize = SkFontHost::GetTableSize(font->uniqueID(), tag); + const size_t tableSize = SkFontHost::GetTableSize(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); + size_t actualSize = SkFontHost::GetTableData(uniqueID, tag, 0, tableSize, buffer); if (tableSize != actualSize) { fastFree(buffer); return 0; @@ -151,25 +163,25 @@ static hb_blob_t* harfbuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* user HB_MEMORY_MODE_WRITABLE, buffer, fastFree); } -static void destroyPaint(void* userData) +static void destroyHarfBuzzFontData(void* userData) { - SkPaint* paint = reinterpret_cast<SkPaint*>(userData); - delete paint; + HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(userData); + delete hbFontData; } hb_face_t* HarfBuzzNGFace::createFace() { - hb_face_t* face = hb_face_create_for_tables(harfbuzzSkiaGetTable, m_platformData, 0); + hb_face_t* face = hb_face_create_for_tables(harfbuzzSkiaGetTable, reinterpret_cast<void*>(m_platformData->uniqueID()), 0); ASSERT(face); return face; } hb_font_t* HarfBuzzNGFace::createFont() { + HarfBuzzFontData* hbFontData = new HarfBuzzFontData(m_glyphCacheForFaceCacheEntry); + m_platformData->setupPaint(&hbFontData->m_paint); 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); + hb_font_set_funcs(font, harfbuzzSkiaGetFontFuncs(), hbFontData, destroyHarfBuzzFontData); float size = m_platformData->size(); int scale = SkiaScalarToHarfbuzzPosition(size); hb_font_set_scale(font, scale, scale); diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp index 9e55fc411..796b37c95 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp @@ -87,10 +87,6 @@ void HarfBuzzShaper::HarfBuzzRun::applyShapeResult(hb_buffer_t* harfbuzzBuffer) m_advances.resize(m_numGlyphs); m_glyphToCharacterIndexes.resize(m_numGlyphs); m_offsets.resize(m_numGlyphs); - - hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(harfbuzzBuffer, 0); - for (unsigned i = 0; i < m_numGlyphs; ++i) - m_glyphToCharacterIndexes[i] = infos[i].cluster; } void HarfBuzzShaper::HarfBuzzRun::setGlyphAndPositions(unsigned index, uint16_t glyphId, float advance, float offsetX, float offsetY) @@ -204,18 +200,27 @@ void HarfBuzzShaper::setDrawRange(int from, int to) void HarfBuzzShaper::setFontFeatures() { - FontFeatureSettings* settings = m_font->fontDescription().featureSettings(); + const FontDescription& description = m_font->fontDescription(); + if (description.orientation() == Vertical) { + static hb_feature_t vert = { HarfBuzzNGFace::vertTag, 1, 0, static_cast<unsigned>(-1) }; + static hb_feature_t vrt2 = { HarfBuzzNGFace::vrt2Tag, 1, 0, static_cast<unsigned>(-1) }; + m_features.append(vert); + m_features.append(vrt2); + } + + FontFeatureSettings* settings = description.featureSettings(); if (!settings) return; unsigned numFeatures = settings->size(); - m_features.resize(numFeatures); for (unsigned i = 0; i < numFeatures; ++i) { + hb_feature_t feature; const UChar* tag = settings->at(i).tag().characters(); - m_features[i].tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]); - m_features[i].value = settings->at(i).value(); - m_features[i].start = 0; - m_features[i].end = static_cast<unsigned>(-1); + feature.tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]); + feature.value = settings->at(i).value(); + feature.start = 0; + feature.end = static_cast<unsigned>(-1); + m_features.append(feature); } } @@ -240,20 +245,6 @@ FloatPoint HarfBuzzShaper::adjustStartPoint(const FloatPoint& point) return point + m_startOffset; } -static const SimpleFontData* fontDataForCombiningCharacterSequence(const Font* font, const UChar* characters, size_t length) -{ - UErrorCode error = U_ZERO_ERROR; - Vector<UChar, 4> normalizedCharacters(length); - int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], length, &error); - // Should fallback if we have an error or no composition occurred. - if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length)) - return 0; - UChar32 normalizedCharacter; - size_t index = 0; - U16_NEXT(&normalizedCharacters[0], index, static_cast<size_t>(normalizedLength), normalizedCharacter); - return font->glyphDataForCharacter(normalizedCharacter, false).fontData; -} - bool HarfBuzzShaper::collectHarfBuzzRuns() { const UChar* normalizedBufferEnd = m_normalizedBuffer.get() + m_normalizedBufferLength; @@ -278,6 +269,7 @@ bool HarfBuzzShaper::collectHarfBuzzRuns() for (iterator.advance(clusterLength); iterator.consume(character, clusterLength); iterator.advance(clusterLength)) { if (Font::treatAsZeroWidthSpace(character)) continue; + if (U_GET_GC_MASK(character) & U_GC_M_MASK) { int markLength = clusterLength; const UChar* markCharactersEnd = iterator.characters() + clusterLength; @@ -290,11 +282,12 @@ bool HarfBuzzShaper::collectHarfBuzzRuns() markLength += nextCharacterLength; markCharactersEnd += nextCharacterLength; } - nextFontData = fontDataForCombiningCharacterSequence(m_font, currentCharacterPosition, markCharactersEnd - currentCharacterPosition); - if (nextFontData) + + if (currentFontData->canRenderCombiningCharacterSequence(currentCharacterPosition, markCharactersEnd - currentCharacterPosition)) { clusterLength = markLength; - else - nextFontData = m_font->glyphDataForCharacter(character, false).fontData; + continue; + } + nextFontData = m_font->glyphDataForCharacter(character, false).fontData; } else nextFontData = m_font->glyphDataForCharacter(character, false).fontData; @@ -305,6 +298,7 @@ bool HarfBuzzShaper::collectHarfBuzzRuns() break; if (nextScript == USCRIPT_INHERITED) nextScript = currentScript; + currentCharacterPosition = iterator.characters(); } unsigned numCharactersOfCurrentRun = iterator.currentCharacter() - startIndexOfCurrentRun; m_harfbuzzRuns.append(HarfBuzzRun::create(currentFontData, startIndexOfCurrentRun, numCharactersOfCurrentRun, m_run.direction())); @@ -340,7 +334,12 @@ bool HarfBuzzShaper::shapeHarfBuzzRuns() HarfBuzzNGFace* face = platformData->harfbuzzFace(); if (!face) return false; + + if (m_font->fontDescription().orientation() == Vertical) + face->setScriptForVerticalGlyphSubstitution(harfbuzzBuffer.get()); + HarfBuzzScopedPtr<hb_font_t> harfbuzzFont(face->createFont(), hb_font_destroy); + hb_shape(harfbuzzFont.get(), harfbuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size()); currentRun->applyShapeResult(harfbuzzBuffer.get()); @@ -361,6 +360,7 @@ void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(harfbuzzBuffer, 0); unsigned numGlyphs = currentRun->numGlyphs(); + uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes(); float totalAdvance = 0; // HarfBuzz returns the shaping result in visual order. We need not to flip for RTL. @@ -374,6 +374,9 @@ void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb unsigned currentCharacterIndex = currentRun->startIndex() + glyphInfos[i].cluster; bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1].cluster; float spacing = 0; + + glyphToCharacterIndexes[i] = glyphInfos[i].cluster; + if (isClusterEnd && !Font::treatAsZeroWidthSpace(m_normalizedBuffer[currentCharacterIndex])) spacing += m_letterSpacing; diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp index 3553a9780..81cf10486 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -43,7 +43,7 @@ class TextLayout { public: static bool isNeeded(RenderText* text, const Font& font) { - TextRun run = RenderBlock::constructTextRun(text, font, text->characters(), text->textLength(), text->style()); + TextRun run = RenderBlock::constructTextRun(text, font, text, text->style()); return font.codePath(run) == Font::Complex; } @@ -54,13 +54,13 @@ public: { } - float width(unsigned from, unsigned len) + float width(unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts) { - m_controller->advance(from, 0, ByWholeGlyphs); + m_controller->advance(from, 0, ByWholeGlyphs, fallbackFonts); float beforeWidth = m_controller->runWidthSoFar(); if (m_font.wordSpacing() && from && Font::treatAsSpace(m_run[from])) beforeWidth += m_font.wordSpacing(); - m_controller->advance(from + len, 0, ByWholeGlyphs); + m_controller->advance(from + len, 0, ByWholeGlyphs, fallbackFonts); float afterWidth = m_controller->runWidthSoFar(); return afterWidth - beforeWidth; } @@ -68,7 +68,7 @@ public: private: static TextRun constructTextRun(RenderText* text, const Font& font, float xPos) { - TextRun run = RenderBlock::constructTextRun(text, font, text->characters(), text->textLength(), text->style()); + TextRun run = RenderBlock::constructTextRun(text, font, text, text->style()); run.setCharactersLength(text->textLength()); ASSERT(run.charactersLength() >= run.length()); @@ -94,9 +94,9 @@ void Font::deleteLayout(TextLayout* layout) delete layout; } -float Font::width(TextLayout& layout, unsigned from, unsigned len) +float Font::width(TextLayout& layout, unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts) { - return layout.width(from, len); + return layout.width(from, len, fallbackFonts); } static inline CGFloat roundCGFloat(CGFloat f) @@ -142,7 +142,11 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru m_expansionPerOpportunity = 0; else { bool isAfterExpansion = m_afterExpansion; - unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters16(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion); + unsigned expansionOpportunityCount; + if (m_run.is8Bit()) + expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters8(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion); + else + expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters16(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion); if (isAfterExpansion && !m_run.allowsTrailingExpansion()) expansionOpportunityCount--; @@ -284,7 +288,14 @@ void ComplexTextController::collectComplexTextRuns() return; // We break up glyph run generation for the string by FontData. - const UChar* cp = m_run.characters16(); + const UChar* cp; + + if (m_run.is8Bit()) { + String stringFor8BitRun = String::make16BitFrom8BitSource(m_run.characters8(), m_run.length()); + cp = stringFor8BitRun.characters16(); + m_stringsFor8BitRuns.append(stringFor8BitRun); + } else + cp = m_run.characters16(); if (m_font.isSmallCaps()) m_smallCapsBuffer.resize(m_end); @@ -449,7 +460,7 @@ unsigned ComplexTextController::incrementCurrentRun(unsigned& leftmostGlyph) return indexOfCurrentRun(leftmostGlyph); } -void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, GlyphIterationStyle iterationStyle) +void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, GlyphIterationStyle iterationStyle, HashSet<const SimpleFontData*>* fallbackFonts) { if (static_cast<int>(offset) > m_end) offset = m_end; @@ -474,6 +485,8 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, G size_t glyphCount = complexTextRun.glyphCount(); unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun; unsigned k = leftmostGlyph + g; + if (fallbackFonts && complexTextRun.fontData() != m_font.primaryFont()) + fallbackFonts->add(complexTextRun.fontData()); while (m_glyphInCurrentRun < glyphCount) { unsigned glyphStartOffset = complexTextRun.indexAt(g); diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.h b/Source/WebCore/platform/graphics/mac/ComplexTextController.h index b3165c279..25c946ee3 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextController.h +++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.h @@ -31,6 +31,7 @@ #include <wtf/RefCounted.h> #include <wtf/RetainPtr.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> #include <wtf/unicode/Unicode.h> typedef unsigned short CGGlyph; @@ -53,7 +54,7 @@ public: ComplexTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool forTextEmphasis = false); // Advance and emit glyphs up to the specified character. - void advance(unsigned to, GlyphBuffer* = 0, GlyphIterationStyle = IncludePartialGlyphs); + void advance(unsigned to, GlyphBuffer* = 0, GlyphIterationStyle = IncludePartialGlyphs, HashSet<const SimpleFontData*>* fallbackFonts = 0); // Compute the character offset for a given x coordinate. int offsetForPosition(float x, bool includePartialGlyphs); @@ -143,6 +144,7 @@ private: bool m_mayUseNaturalWritingDirection; bool m_forTextEmphasis; + Vector<String> m_stringsFor8BitRuns; Vector<UChar, 256> m_smallCapsBuffer; // Retain lines rather than their runs for better performance. diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm index 2440fd48e..f7d03110b 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm +++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm @@ -282,13 +282,13 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation + runRange.location, runRange.length, m_run.ltr())); continue; } - runFontData = fontCache()->getCachedFontData(m_font.fontDescription(), fontName.get(), false, FontCache::DoNotRetain); + runFontData = fontCache()->getCachedFontData(m_font.fontDescription(), fontName.get(), false, FontCache::DoNotRetain).get(); #if !PLATFORM(WX) // Core Text may have used a font that is not known to NSFontManager. In that case, fall back on // using the font as returned, even though it may not have the best NSFontRenderingMode. if (!runFontData) { FontPlatformData runFontPlatformData((NSFont *)runFont, CTFontGetSize(runFont), m_font.fontDescription().usePrinterFont()); - runFontData = fontCache()->getCachedFontData(&runFontPlatformData, FontCache::DoNotRetain); + runFontData = fontCache()->getCachedFontData(&runFontPlatformData, FontCache::DoNotRetain).get(); } #else // just assert for now, until we can devise a better fix that works with wx. diff --git a/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp b/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp index dfdd8de22..e5c1ad364 100644 --- a/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp +++ b/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp @@ -45,7 +45,7 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef, const CVTimeStamp* now, co return kCVReturnSuccess; } - + DisplayRefreshMonitor::~DisplayRefreshMonitor() { if (m_displayLink) { @@ -61,7 +61,7 @@ bool DisplayRefreshMonitor::requestRefreshCallback() { if (!m_active) return false; - + if (!m_displayLink) { m_active = false; CVReturn error = CVDisplayLinkCreateWithCGDisplay(m_displayID, &m_displayLink); @@ -78,7 +78,7 @@ bool DisplayRefreshMonitor::requestRefreshCallback() m_active = true; } - + MutexLocker lock(m_mutex); m_scheduled = true; return true; @@ -92,9 +92,11 @@ void DisplayRefreshMonitor::displayLinkFired(double nowSeconds, double outputTim m_previousFrameDone = false; - double webKitNow = currentTime(); - m_timestamp = webKitNow - nowSeconds + outputTimeSeconds; - + double webKitMonotonicNow = monotonicallyIncreasingTime(); + double timeUntilOutput = outputTimeSeconds - nowSeconds; + // FIXME: Should this be using webKitMonotonicNow? + m_monotonicAnimationStartTime = webKitMonotonicNow + timeUntilOutput; + callOnMainThread(handleDisplayRefreshedNotificationOnMainThread, this); } diff --git a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm index 9b2555823..d1dc8162a 100644 --- a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm @@ -99,7 +99,7 @@ static inline bool isAppKitFontWeightBold(NSInteger appKitFontWeight) return appKitFontWeight >= 7; } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { UChar32 character; U16_GET(characters, 0, 0, length, character); @@ -172,12 +172,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return getCachedFontData(&alternateFont, DoNotRetain); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { // Attempt to find an appropriate font using a match based on // the presence of keywords in the the requested names. For example, we'll // match any name that contains "Arabic" to Geeza Pro. - SimpleFontData* simpleFontData = 0; + RefPtr<SimpleFontData> simpleFontData; const FontFamily* currFamily = &font.fontDescription().family(); while (currFamily && !simpleFontData) { if (currFamily->family().length()) { @@ -190,18 +190,18 @@ SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) currFamily = currFamily->next(); } - return simpleFontData; + return simpleFontData.release(); } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { DEFINE_STATIC_LOCAL(AtomicString, timesStr, ("Times")); // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick // the default that the user would get without changing any prefs. - SimpleFontData* simpleFontData = getCachedFontData(fontDescription, timesStr, false, shouldRetain); + RefPtr<SimpleFontData> simpleFontData = getCachedFontData(fontDescription, timesStr, false, shouldRetain); if (simpleFontData) - return simpleFontData; + return simpleFontData.release(); // The Times fallback will almost always work, but in the highly unusual case where // the user doesn't have it, we fall back on Lucida Grande because that's diff --git a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp index b7acd83bc..da80c2bde 100644 --- a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp +++ b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp @@ -91,8 +91,7 @@ float Font::getGlyphsAndAdvancesForComplexText(const TextRun& run, int from, int if (run.rtl()) { initialAdvance = controller.totalWidth() + controller.finalRoundingWidth() - afterWidth; - for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end) - glyphBuffer.swap(i, end); + glyphBuffer.reverse(0, glyphBuffer.size()); } else initialAdvance = beforeWidth; @@ -189,21 +188,21 @@ const SimpleFontData* Font::fontDataForCombiningCharacterSequence(const UChar* c if (simpleFontData->platformData().orientation() == Vertical) { if (isCJKIdeographOrSymbol(baseCharacter) && !simpleFontData->hasVerticalGlyphs()) { variant = BrokenIdeographVariant; - simpleFontData = simpleFontData->brokenIdeographFontData(); + simpleFontData = simpleFontData->brokenIdeographFontData().get(); } else if (m_fontDescription.textOrientation() == TextOrientationVerticalRight) { - SimpleFontData* verticalRightFontData = simpleFontData->verticalRightOrientationFontData(); + SimpleFontData* verticalRightFontData = simpleFontData->verticalRightOrientationFontData().get(); Glyph verticalRightGlyph = verticalRightFontData->glyphForCharacter(baseCharacter); if (verticalRightGlyph == baseCharacterGlyphData.glyph) simpleFontData = verticalRightFontData; } else { - SimpleFontData* uprightFontData = simpleFontData->uprightOrientationFontData(); + SimpleFontData* uprightFontData = simpleFontData->uprightOrientationFontData().get(); Glyph uprightGlyph = uprightFontData->glyphForCharacter(baseCharacter); if (uprightGlyph != baseCharacterGlyphData.glyph) simpleFontData = uprightFontData; } } } else { - if (const SimpleFontData* variantFontData = simpleFontData->variantFontData(m_fontDescription, variant)) + if (const SimpleFontData* variantFontData = simpleFontData->variantFontData(m_fontDescription, variant).get()) simpleFontData = variantFontData; } diff --git a/Source/WebCore/platform/graphics/mac/FontMac.mm b/Source/WebCore/platform/graphics/mac/FontMac.mm index 608123cbd..b515f81d5 100644 --- a/Source/WebCore/platform/graphics/mac/FontMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontMac.mm @@ -241,15 +241,15 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons float shadowTextX = point.x() + shadowOffset.width(); // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative. float shadowTextY = point.y() + shadowOffset.height() * (context->shadowsIgnoreTransforms() ? -1 : 1); - showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); if (syntheticBoldOffset) - showGlyphsWithAdvances(FloatPoint(shadowTextX + syntheticBoldOffset, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(FloatPoint(shadowTextX + syntheticBoldOffset, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); context->setFillColor(fillColor, fillColorSpace); } - showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); if (syntheticBoldOffset) - showGlyphsWithAdvances(FloatPoint(point.x() + syntheticBoldOffset, point.y()), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(FloatPoint(point.x() + syntheticBoldOffset, point.y()), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); if (hasSimpleShadow) context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace); diff --git a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index 68f4f2437..82538779c 100644 --- a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -277,12 +277,6 @@ void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback> { } -void GraphicsContext3D::releaseShaderCompiler() -{ - makeContextCurrent(); - notImplemented(); -} - } #endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h index 436160718..3ee1a4c29 100644 --- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h +++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h @@ -76,6 +76,10 @@ private: static PassOwnPtr<MediaPlayerPrivateInterface> create(MediaPlayer*); static void getSupportedTypes(HashSet<String>& types); static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs, const KURL&); +#if ENABLE(ENCRYPTED_MEDIA) + static MediaPlayer::SupportsType extendedSupportsType(const String& type, const String& codecs, const String& keySystem, const KURL&); +#endif + static void getSitesInMediaCache(Vector<String>&); static void clearMediaCache(); static void clearMediaCacheForSite(const String&); diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index 2e849af61..c03eda9e4 100644 --- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -47,7 +47,7 @@ #import <wtf/UnusedParam.h> #if USE(ACCELERATED_COMPOSITING) -#include "GraphicsLayer.h" +#include "PlatformLayer.h" #endif #if DRAW_FRAME_RATE @@ -190,7 +190,11 @@ PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivateQTKit::create(MediaPla void MediaPlayerPrivateQTKit::registerMediaEngine(MediaEngineRegistrar registrar) { if (isAvailable()) +#if ENABLE(ENCRYPTED_MEDIA) + registrar(create, getSupportedTypes, extendedSupportsType, getSitesInMediaCache, clearMediaCache, clearMediaCacheForSite); +#else registrar(create, getSupportedTypes, supportsType, getSitesInMediaCache, clearMediaCache, clearMediaCacheForSite); +#endif } MediaPlayerPrivateQTKit::MediaPlayerPrivateQTKit(MediaPlayer* player) @@ -1518,6 +1522,17 @@ MediaPlayer::SupportsType MediaPlayerPrivateQTKit::supportsType(const String& ty return MediaPlayer::IsNotSupported; } +#if ENABLE(ENCRYPTED_MEDIA) +MediaPlayer::SupportsType MediaPlayerPrivateQTKit::extendedSupportsType(const String& type, const String& codecs, const String& keySystem, const KURL& url) +{ + // QTKit does not support any encrytped media, so return IsNotSupported if the keySystem is non-NULL: + if (!keySystem.isNull() || !keySystem.isEmpty()) + return MediaPlayer::IsNotSupported; + + return supportsType(type, codecs, url);; +} +#endif + bool MediaPlayerPrivateQTKit::isAvailable() { // On 10.5 and higher, QuickTime will always be new enough for <video> and <audio> support, so we just check that the framework can be loaded. diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp index 05193742c..0b713347f 100644 --- a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp +++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp @@ -43,7 +43,7 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese { unsigned key = typesettingFeatures + 1; HashMap<unsigned, RetainPtr<CFDictionaryRef> >::AddResult addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>()); - RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.iterator->second; + RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.iterator->value; if (!addResult.isNewEntry) return attributesDictionary.get(); diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 66fe90a59..f8bb43ba7 100644 --- a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -308,19 +308,19 @@ void SimpleFontData::platformDestroy() if (!isCustomFont() && m_derivedFontData) { // These come from the cache. if (m_derivedFontData->smallCaps) - fontCache()->releaseFontData(m_derivedFontData->smallCaps.leakPtr()); + fontCache()->releaseFontData(m_derivedFontData->smallCaps.get()); if (m_derivedFontData->emphasisMark) - fontCache()->releaseFontData(m_derivedFontData->emphasisMark.leakPtr()); + fontCache()->releaseFontData(m_derivedFontData->emphasisMark.get()); } } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { if (isCustomFont()) { FontPlatformData scaledFontData(m_platformData); scaledFontData.m_size = scaledFontData.m_size * scaleFactor; - return adoptPtr(new SimpleFontData(scaledFontData, true, false)); + return SimpleFontData::create(scaledFontData, true, false); } BEGIN_BLOCK_OBJC_EXCEPTIONS; @@ -345,31 +345,31 @@ PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri scaledFontData.m_syntheticOblique = (fontTraits & NSItalicFontMask) && !(scaledFontTraits & NSItalicFontMask); // SimpleFontData::platformDestroy() takes care of not deleting the cached font data twice. - return adoptPtr(fontCache()->getCachedFontData(&scaledFontData)); + return fontCache()->getCachedFontData(&scaledFontData); } END_BLOCK_OBJC_EXCEPTIONS; - return nullptr; + return 0; } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFontSizeMultiplier); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5f); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const @@ -461,7 +461,7 @@ bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false); if (!addResult.isNewEntry) - return addResult.iterator->second; + return addResult.iterator->value; RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(platformData().ctFont(), 0)); @@ -481,7 +481,7 @@ bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters return false; } - addResult.iterator->second = true; + addResult.iterator->value = true; return true; } diff --git a/Source/WebCore/platform/graphics/mac/WebLayer.mm b/Source/WebCore/platform/graphics/mac/WebLayer.mm index d783e494a..f89fec7f8 100644 --- a/Source/WebCore/platform/graphics/mac/WebLayer.mm +++ b/Source/WebCore/platform/graphics/mac/WebLayer.mm @@ -109,7 +109,7 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCA // Re-fetch the layer owner, since <rdar://problem/9125151> indicates that it might have been destroyed during painting. layerContents = platformLayer->owner(); ASSERT(layerContents); - if (platformLayer->layerType() != PlatformCALayer::LayerTypeTileCacheLayer && layerContents && layerContents->platformCALayerShowRepaintCounter()) { + if (!platformLayer->usesTileCacheLayer() && layerContents && layerContents->platformCALayerShowRepaintCounter(platformLayer)) { bool isTiledLayer = [layer isKindOfClass:[CATiledLayer class]]; char text[16]; // that's a lot of repaints @@ -178,7 +178,7 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCA [super setNeedsDisplayInRect:dirtyRect]; - if (layerOwner->platformCALayerShowRepaintCounter()) { + if (layerOwner->platformCALayerShowRepaintCounter(platformLayer)) { CGRect bounds = [self bounds]; CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 52, 27); if (layerOwner->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp) diff --git a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm index 9736e74dc..65fa7d2ee 100644 --- a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm +++ b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm @@ -84,7 +84,7 @@ using namespace WebCore; [super setNeedsDisplayInRect:dirtyRect]; - if (layerOwner->platformCALayerShowRepaintCounter()) { + if (layerOwner->platformCALayerShowRepaintCounter(platformLayer)) { CGRect bounds = [self bounds]; CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 52, 27); if (layerOwner->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp) diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp index 60f6bfaf3..aaf68d8be 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp @@ -46,6 +46,7 @@ #include "OpenGLShims.h" #endif +#include <wtf/MainThread.h> #include <wtf/Vector.h> namespace WebCore { @@ -53,7 +54,46 @@ namespace WebCore { Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context) : m_initializedAvailableExtensions(false) , m_context(context) + , m_isNVIDIA(false) + , m_isAMD(false) + , m_isIntel(false) + , m_maySupportMultisampling(true) + , m_requiresBuiltInFunctionEmulation(false) { + m_vendor = String(reinterpret_cast<const char*>(::glGetString(GL_VENDOR))); + + Vector<String> vendorComponents; + m_vendor.lower().split(' ', vendorComponents); + if (vendorComponents.contains("nvidia")) + m_isNVIDIA = true; + if (vendorComponents.contains("ati") || vendorComponents.contains("amd")) + m_isAMD = true; + if (vendorComponents.contains("intel")) + m_isIntel = true; + +#if PLATFORM(MAC) + if (m_isAMD || m_isIntel) + m_requiresBuiltInFunctionEmulation = true; + + // Currently in Mac we only allow multisampling if the vendor is NVIDIA, + // or if the vendor is AMD/ATI and the system is 10.7.2 and above. + + bool systemSupportsMultisampling = true; +#if !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1080 + ASSERT(isMainThread()); + static SInt32 version; + if (!version) { + if (Gestalt(gestaltSystemVersion, &version) != noErr) + systemSupportsMultisampling = false; + } + // See https://bugs.webkit.org/show_bug.cgi?id=77922 for more details + if (systemSupportsMultisampling) + systemSupportsMultisampling = version >= 0x1072; +#endif // SNOW_LEOPARD and LION + + if (m_isNVIDIA || (m_isAMD && systemSupportsMultisampling)) + m_maySupportMultisampling = true; +#endif } Extensions3DOpenGLCommon::~Extensions3DOpenGLCommon() @@ -117,23 +157,28 @@ String Extensions3DOpenGLCommon::getTranslatedShaderSourceANGLE(Platform3DObject if (result == m_context->m_shaderSourceMap.end()) return ""; - GraphicsContext3D::ShaderSourceEntry& entry = result->second; + GraphicsContext3D::ShaderSourceEntry& entry = result->value; String translatedShaderSource; String shaderInfoLog; - int extraCompileOptions = 0; + int extraCompileOptions = SH_MAP_LONG_VARIABLE_NAMES; -#if PLATFORM(MAC) - const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); - if (vendor && (std::strstr(vendor, "ATI") || std::strstr(vendor, "AMD") || std::strstr(vendor, "Intel"))) + if (m_requiresBuiltInFunctionEmulation) extraCompileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS; -#endif - bool isValid = compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog, extraCompileOptions); + Vector<ANGLEShaderSymbol> symbols; + bool isValid = compiler.compileShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog, symbols, extraCompileOptions); entry.log = shaderInfoLog; entry.isValid = isValid; + size_t numSymbols = symbols.size(); + for (size_t i = 0; i < numSymbols; ++i) { + ANGLEShaderSymbol shaderSymbol = symbols[i]; + GraphicsContext3D::SymbolInfo symbolInfo(shaderSymbol.dataType, shaderSymbol.size, shaderSymbol.mappedName); + entry.symbolMap(shaderSymbol.symbolType).set(shaderSymbol.name, symbolInfo); + } + if (!isValid) return ""; diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h index 75869de19..7092cfaca 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h @@ -57,6 +57,14 @@ public: virtual void getnUniformfvEXT(GC3Duint program, int location, GC3Dsizei bufSize, float *params); virtual void getnUniformivEXT(GC3Duint program, int location, GC3Dsizei bufSize, int *params); + virtual bool isNVIDIA() { return m_isNVIDIA; } + virtual bool isAMD() { return m_isAMD; } + virtual bool isIntel() { return m_isIntel; } + virtual String vendor() { return m_vendor; } + + virtual bool maySupportMultisampling() { return m_maySupportMultisampling; } + virtual bool requiresBuiltInFunctionEmulation() { return m_requiresBuiltInFunctionEmulation; } + protected: friend class Extensions3DOpenGLES; Extensions3DOpenGLCommon(GraphicsContext3D*); @@ -70,6 +78,14 @@ protected: // Weak pointer back to GraphicsContext3D GraphicsContext3D* m_context; + + bool m_isNVIDIA; + bool m_isAMD; + bool m_isIntel; + bool m_maySupportMultisampling; + bool m_requiresBuiltInFunctionEmulation; + + String m_vendor; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp index 98e1145b3..d7c05e627 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp @@ -49,6 +49,12 @@ namespace WebCore { +void GraphicsContext3D::releaseShaderCompiler() +{ + makeContextCurrent(); + notImplemented(); +} + void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels) { ::glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels); @@ -59,13 +65,7 @@ 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()) + if (!extensions->maySupportMultisampling() || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) m_attrs.antialias = false; else extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); @@ -281,26 +281,6 @@ void GraphicsContext3D::clearDepth(GC3Dclampf depth) ::glClearDepth(depth); } -bool GraphicsContext3D::systemAllowsMultisamplingOnATICards() const -{ -#if PLATFORM(MAC) -#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 - 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) diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp index 4fffee47d..db9fe43b6 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp @@ -88,13 +88,7 @@ void GraphicsContext3D::validateDepthStencil(const char* packedDepthStencilExten m_attrs.stencil = false; } 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()) + if (!extensions->maySupportMultisampling() || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) m_attrs.antialias = false; else extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); @@ -471,8 +465,8 @@ void GraphicsContext3D::compileShader(Platform3DObject shader) ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); if (length) { - HashMap<Platform3DObject, GraphicsContext3D::ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); - GraphicsContext3D::ShaderSourceEntry& entry = result->second; + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader); + GraphicsContext3D::ShaderSourceEntry& entry = result->value; GLsizei size = 0; OwnArrayPtr<GLchar> info = adoptArrayPtr(new GLchar[length]); @@ -483,9 +477,9 @@ void GraphicsContext3D::compileShader(Platform3DObject shader) // ASSERT that ANGLE generated GLSL will be accepted by OpenGL. ASSERT(GLCompileSuccess == GL_TRUE); -#if PLATFORM(BLACKBERRY) +#if PLATFORM(BLACKBERRY) && !defined(NDEBUG) if (GLCompileSuccess != GL_TRUE) - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelWarn, "The shader validated, but didn't compile.\n"); + BBLOG(BlackBerry::Platform::LogLevelWarn, "The shader validated, but didn't compile.\n"); #endif } @@ -635,7 +629,10 @@ bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index ::glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name.get()); if (!nameLength) return false; - info.name = String(name.get(), nameLength); + + String originalName = originalSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, String(name.get(), nameLength)); + + info.name = originalName; info.type = type; info.size = size; return true; @@ -659,11 +656,12 @@ bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint inde ::glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name.get()); if (!nameLength) return false; - - info.name = String(name.get(), nameLength); + + String originalName = originalSymbolName(program, SHADER_SYMBOL_TYPE_UNIFORM, String(name.get(), nameLength)); + + info.name = originalName; info.type = type; info.size = size; - return true; } @@ -677,13 +675,59 @@ void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei m ::glGetAttachedShaders(program, maxCount, count, shaders); } +String GraphicsContext3D::mappedSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name) +{ + GC3Dsizei count; + Platform3DObject shaders[2]; + getAttachedShaders(program, 2, &count, shaders); + + for (GC3Dsizei i = 0; i < count; ++i) { + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]); + if (result == m_shaderSourceMap.end()) + continue; + + const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType); + ShaderSymbolMap::const_iterator symbolEntry = symbolMap.find(name); + if (symbolEntry != symbolMap.end()) + return symbolEntry->value.mappedName; + } + return name; +} + +String GraphicsContext3D::originalSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name) +{ + GC3Dsizei count; + Platform3DObject shaders[2]; + getAttachedShaders(program, 2, &count, shaders); + + for (GC3Dsizei i = 0; i < count; ++i) { + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]); + if (result == m_shaderSourceMap.end()) + continue; + + const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType); + ShaderSymbolMap::const_iterator symbolEntry; + for (symbolEntry = symbolMap.begin(); symbolEntry != symbolMap.end(); ++symbolEntry) { + if (symbolEntry->value.mappedName == name) + return symbolEntry->key; + } + } + return name; +} + int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name) { if (!program) return -1; makeContextCurrent(); - return ::glGetAttribLocation(program, name.utf8().data()); + + // The attribute name may have been translated during ANGLE compilation. + // Look through the corresponding ShaderSourceMap to make sure we + // reference the mapped name rather than the external name. + String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, name); + + return ::glGetAttribLocation(program, mappedName.utf8().data()); } GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() @@ -1132,7 +1176,7 @@ void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3 makeContextCurrent(); - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader); switch (pname) { case DELETE_STATUS: @@ -1144,7 +1188,7 @@ void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3 *value = static_cast<int>(false); return; } - *value = static_cast<int>(result->second.isValid); + *value = static_cast<int>(result->value.isValid); break; case INFO_LOG_LENGTH: if (result == m_shaderSourceMap.end()) { @@ -1167,11 +1211,11 @@ String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader) makeContextCurrent(); - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader); if (result == m_shaderSourceMap.end()) return String(); - ShaderSourceEntry entry = result->second; + ShaderSourceEntry entry = result->value; if (!entry.isValid) return entry.log; @@ -1193,11 +1237,11 @@ String GraphicsContext3D::getShaderSource(Platform3DObject shader) makeContextCurrent(); - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader); if (result == m_shaderSourceMap.end()) return String(); - return result->second.source; + return result->value.source; } @@ -1230,7 +1274,13 @@ GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const St ASSERT(program); makeContextCurrent(); - return ::glGetUniformLocation(program, name.utf8().data()); + + // The uniform name may have been translated during ANGLE compilation. + // Look through the corresponding ShaderSourceMap to make sure we + // reference the mapped name rather than the external name. + String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_UNIFORM, name); + + return ::glGetUniformLocation(program, mappedName.utf8().data()); } void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value) diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp index 4d1530c4b..991571d42 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp @@ -39,7 +39,6 @@ #include "LayerWebKitThread.h" #endif #include "NotImplemented.h" -#include "OpenGLESShims.h" namespace WebCore { @@ -66,14 +65,14 @@ void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsi #else if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + ::glBindFramebuffer(GL_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); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); #endif } @@ -122,12 +121,12 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) bool mustRestoreFBO = false; if (m_boundFBO != m_fbo) { mustRestoreFBO = true; - ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); } ::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); + ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_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); @@ -139,28 +138,28 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) 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); + ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); + ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); if (m_attrs.stencil) - ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); if (m_attrs.depth) - ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0); - ::glBindTexture(GL_TEXTURE_2D, 0); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); + ::glBindRenderbuffer(GL_RENDERBUFFER, 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); + ::glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer); + ::glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_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); + ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); + ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); } - ::glBindRenderbufferEXT(GraphicsContext3D::RENDERBUFFER, 0); + ::glBindRenderbuffer(GL_RENDERBUFFER, 0); } } - if (glCheckFramebufferStatusEXT(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { // FIXME: cleanup notImplemented(); } @@ -178,7 +177,7 @@ void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect) void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) { makeContextCurrent(); - ::glRenderbufferStorageEXT(target, internalformat, width, height); + ::glRenderbufferStorage(target, internalformat, width, height); } void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value) @@ -238,11 +237,6 @@ Extensions3D* GraphicsContext3D::getExtensions() return m_extensions.get(); } -bool GraphicsContext3D::systemAllowsMultisamplingOnATICards() const -{ - return false; // not applicable -} - } #endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp b/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp index 584d78ff8..67013b1ac 100644 --- a/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp +++ b/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp @@ -256,6 +256,15 @@ struct FeatureList : TableBase { return validateOffset<FeatureTable>(buffer, features[index].featureOffset); return 0; } + + const FeatureTable* findFeature(OpenType::Tag tag, const SharedBuffer& buffer) const + { + for (uint16_t i = 0; i < featureCount; ++i) { + if (isValidEnd(buffer, &features[i]) && features[i].featureTag == tag) + return validateOffset<FeatureTable>(buffer, features[i].featureOffset); + } + return 0; + } }; struct LangSysTable : TableBase { @@ -361,9 +370,17 @@ struct GSUBTable : TableBase { { const LangSysTable* langSys = defaultLangSys(buffer); const FeatureList* features = featureList(buffer); - if (!langSys || !features) + if (!features) return 0; - return langSys->feature(featureTag, features, buffer); + const FeatureTable* feature = 0; + if (langSys) + feature = langSys->feature(featureTag, features, buffer); + if (!feature) { + // If the font has no langSys table, or has no default script and the first script doesn't + // have the requested feature, then use the first matching feature directly. + feature = features->findFeature(featureTag, buffer); + } + return feature; } bool getVerticalGlyphSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const diff --git a/Source/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp b/Source/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp index d681d7581..1a68aeff8 100644 --- a/Source/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp +++ b/Source/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp @@ -121,7 +121,7 @@ EGLDisplayOpenVG::~EGLDisplayOpenVG() HashMap<EGLSurface, EGLint>::const_iterator end = m_surfaceConfigIds.end(); for (HashMap<EGLSurface, EGLint>::const_iterator it = m_surfaceConfigIds.begin(); it != end; ++it) - destroySurface((*it).first); + destroySurface((*it).key); eglTerminate(m_display); ASSERT_EGL_NO_ERROR(); @@ -338,7 +338,7 @@ void EGLDisplayOpenVG::destroySurface(const EGLSurface& surface) // ...but only if there's no other surfaces associated to that context. for (HashMap<EGLSurface, EGLint>::iterator it = m_surfaceConfigIds.begin(); it != end; ++it) { - if ((*it).second == surfaceConfigId) { + if ((*it).value == surfaceConfigId) { isContextReferenced = true; break; } @@ -354,7 +354,7 @@ void EGLDisplayOpenVG::destroySurface(const EGLSurface& surface) HashMap<EGLNativeWindowType, EGLSurface>::iterator end = m_windowSurfaces.end(); for (HashMap<EGLNativeWindowType, EGLSurface>::iterator it = m_windowSurfaces.begin(); it != end; ++it) { - if ((*it).second == surface) { + if ((*it).value == surface) { m_windowSurfaces.remove(it); break; } @@ -409,7 +409,7 @@ EGLContext EGLDisplayOpenVG::contextForSurface(const EGLSurface& surface) HashMap<EGLint, EGLContext>::iterator end = m_contexts.end(); for (HashMap<EGLint, EGLContext>::iterator it = m_contexts.begin(); it != end; ++it) { - eglMakeCurrent(m_display, surface, surface, (*it).second); + eglMakeCurrent(m_display, surface, surface, (*it).value); if (eglGetError() == EGL_SUCCESS) { // Restore previous surface/context. if (currentContext != EGL_NO_CONTEXT) { @@ -417,8 +417,8 @@ EGLContext EGLDisplayOpenVG::contextForSurface(const EGLSurface& surface) ASSERT_EGL_NO_ERROR(); } // Cool, surface is compatible to one of our existing contexts. - m_compatibleConfigIds.set(surfaceConfigId, (*it).first); - return (*it).second; + m_compatibleConfigIds.set(surfaceConfigId, (*it).key); + return (*it).value; } } // Restore previous surface/context. diff --git a/Source/WebCore/platform/graphics/pango/FontCachePango.cpp b/Source/WebCore/platform/graphics/pango/FontCachePango.cpp index 2b12c3553..06d63c50f 100644 --- a/Source/WebCore/platform/graphics/pango/FontCachePango.cpp +++ b/Source/WebCore/platform/graphics/pango/FontCachePango.cpp @@ -35,17 +35,17 @@ void FontCache::platformInit() ASSERT_NOT_REACHED(); } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { return 0; } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { // FIXME: Would be even better to somehow get the user's default font here. // For now we'll pick the default that the user would get without changing any prefs. diff --git a/Source/WebCore/platform/graphics/pango/FontPango.cpp b/Source/WebCore/platform/graphics/pango/FontPango.cpp index 03507c4c7..b91bfc980 100644 --- a/Source/WebCore/platform/graphics/pango/FontPango.cpp +++ b/Source/WebCore/platform/graphics/pango/FontPango.cpp @@ -371,7 +371,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon { #if USE(FREETYPE) if (!primaryFont()->platformData().m_pattern) - return floatWidthForSimpleText(run, 0, fallbackFonts, overflow); + return floatWidthForSimpleText(run, fallbackFonts, overflow); #endif if (!run.length()) diff --git a/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp b/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp index ee8ee0f74..4fc1fbe3e 100644 --- a/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp +++ b/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp @@ -84,32 +84,32 @@ void SimpleFontData::platformDestroy() { } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { FontDescription desc = FontDescription(fontDescription); desc.setSpecifiedSize(scaleFactor * fontDescription.computedSize()); FontPlatformData platformData(desc, desc.family().family()); - return adoptPtr(new SimpleFontData(platformData)); + return SimpleFontData::create(platformData); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const diff --git a/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp b/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp index b58198fa3..6d1ee72f2 100644 --- a/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp +++ b/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp @@ -25,9 +25,9 @@ #include "config.h" #include "FontCache.h" +#include "Font.h" #include "FontDescription.h" #include "FontPlatformData.h" -#include "Font.h" #include <utility> #include <wtf/ListHashSet.h> #include <wtf/StdLibExtras.h> @@ -63,7 +63,7 @@ static QRawFont rawFontForCharacters(const QString& string, const QRawFont& font return glyphs.rawFont(); } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { QString qstring = QString::fromRawData(reinterpret_cast<const QChar*>(characters), length); QRawFont computedFont = rawFontForCharacters(qstring, font.rawFont()); @@ -73,12 +73,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return getCachedFontData(&alternateFont, DoNotRetain); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { const AtomicString fallbackFamily = QFont(fontDescription.family().family()).lastResortFamily(); return getCachedFontData(new FontPlatformData(fontDescription, fallbackFamily), shouldRetain); diff --git a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h index fbf9a158d..8d4efeca2 100644 --- a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h @@ -26,10 +26,10 @@ #include "FontRenderingMode.h" #include "FontWidthVariant.h" #include "TextOrientation.h" +#include <QRawFont> #include <wtf/FastAllocBase.h> #include <wtf/Forward.h> #include <wtf/Noncopyable.h> -#include <QRawFont> namespace WebCore { diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index 1678c49fa..69aa86591 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -69,7 +69,7 @@ public: #endif #if USE(GRAPHICS_SURFACE) virtual uint32_t copyToGraphicsSurface(); - virtual uint64_t graphicsSurfaceToken() const; + virtual GraphicsSurfaceToken graphicsSurfaceToken() const; #endif QRectF boundingRect() const; @@ -100,13 +100,6 @@ bool GraphicsContext3D::isGLES2Compliant() const #endif } -#if !USE(OPENGL_ES_2) -void GraphicsContext3D::releaseShaderCompiler() -{ - notImplemented(); -} -#endif - GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) : m_context(context) , m_hostWindow(hostWindow) @@ -206,6 +199,11 @@ void GraphicsContext3DPrivate::initializeANGLE() // Always set to 1 for OpenGL ES. ANGLEResources.MaxDrawBuffers = 1; + + Extensions3D* extensions = m_context->getExtensions(); + if (extensions->supports("GL_ARB_texture_rectangle")) + ANGLEResources.ARB_texture_rectangle = 1; + m_context->m_compiler.setResources(ANGLEResources); } @@ -291,7 +289,7 @@ uint32_t GraphicsContext3DPrivate::copyToGraphicsSurface() return frontBuffer; } -uint64_t GraphicsContext3DPrivate::graphicsSurfaceToken() const +GraphicsSurfaceToken GraphicsContext3DPrivate::graphicsSurfaceToken() const { return m_graphicsSurface->exportToken(); } @@ -492,16 +490,18 @@ bool GraphicsContext3D::getImageData(Image* image, if (!image) return false; - QImage nativeImage; + QImage qtImage; // Is image already loaded? If not, load it. if (image->data()) - nativeImage = QImage::fromData(reinterpret_cast<const uchar*>(image->data()->data()), image->data()->size()); - else - nativeImage = *image->nativeImageForCurrentFrame(); - + qtImage = QImage::fromData(reinterpret_cast<const uchar*>(image->data()->data()), image->data()->size()); + else { + QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); + // With QPA, we can avoid a deep copy. + qtImage = *nativePixmap->handle()->buffer(); + } AlphaOp alphaOp = AlphaDoNothing; - switch (nativeImage.format()) { + switch (qtImage.format()) { case QImage::Format_RGB32: // For opaque images, we should not premultiply or unmultiply alpha. break; @@ -515,7 +515,7 @@ bool GraphicsContext3D::getImageData(Image* image, break; default: // The image has a format that is not supported in packPixels. We have to convert it here. - nativeImage = nativeImage.convertToFormat(premultiplyAlpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_ARGB32); + qtImage = qtImage.convertToFormat(premultiplyAlpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_ARGB32); break; } @@ -526,7 +526,7 @@ bool GraphicsContext3D::getImageData(Image* image, outputVector.resize(packedSize); - return packPixels(nativeImage.constBits(), 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>) diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 5c8a3ae24..c2ab6dfb0 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -283,12 +283,13 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p, cons GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate() { + delete shadow; + if (!platformContextIsOwned) return; QPaintDevice* device = painter->device(); painter->end(); - delete shadow; delete painter; delete device; } @@ -1066,7 +1067,7 @@ void GraphicsContext::clearPlatformShadow() m_data->shadow->clear(); } -void GraphicsContext::pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QImage& alphaMask) +void GraphicsContext::pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask) { QPainter* p = m_data->p(); @@ -1101,7 +1102,7 @@ void GraphicsContext::beginPlatformTransparencyLayer(float opacity) h = int(qBound(qreal(0), deviceClip.height(), (qreal)h) + 2); } - QImage emptyAlphaMask; + QPixmap emptyAlphaMask; m_data->layers.push(new TransparencyLayer(p, QRect(x, y, w, h), opacity, emptyAlphaMask)); ++m_data->layerCount; } @@ -1115,7 +1116,7 @@ void GraphicsContext::endPlatformTransparencyLayer() if (!layer->alphaMask.isNull()) { layer->painter.resetTransform(); layer->painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); - layer->painter.drawImage(QPoint(), layer->alphaMask); + layer->painter.drawPixmap(QPoint(), layer->alphaMask); } else --m_data->layerCount; // see the comment for layerCount layer->painter.end(); @@ -1124,7 +1125,7 @@ void GraphicsContext::endPlatformTransparencyLayer() p->save(); p->resetTransform(); p->setOpacity(layer->opacity); - p->drawImage(layer->offset, layer->image); + p->drawPixmap(layer->offset, layer->pixmap); p->restore(); delete layer; diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h b/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h index 94065d3a6..9cf782bea 100644 --- a/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h +++ b/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h @@ -25,8 +25,8 @@ #include "Image.h" -#include <QImage> #include <QPainter> +#include <QPixmap> #include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> @@ -39,7 +39,9 @@ class ImageBufferData { public: ImageBufferData(const IntSize&); - QImage m_nativeImage; + QImage toQImage() const; + + QPixmap m_pixmap; OwnPtr<QPainter> m_painter; RefPtr<Image> m_image; }; diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp index 32dd39a5f..ac27dc25a 100644 --- a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -32,7 +32,6 @@ #include "GraphicsContext.h" #include "ImageData.h" #include "MIMETypeRegistry.h" -#include "NativeImageQt.h" #include "StillImageQt.h" #include "TransparencyLayer.h" #include <wtf/text/CString.h> @@ -43,22 +42,23 @@ #include <QImage> #include <QImageWriter> #include <QPainter> +#include <QPixmap> #include <math.h> namespace WebCore { ImageBufferData::ImageBufferData(const IntSize& size) - : m_nativeImage(size, NativeImageQt::defaultFormatForAlphaEnabledImages()) + : m_pixmap(size) { - if (m_nativeImage.isNull()) + if (m_pixmap.isNull()) return; - m_nativeImage.fill(QColor(Qt::transparent)); + m_pixmap.fill(QColor(Qt::transparent)); QPainter* painter = new QPainter; m_painter = adoptPtr(painter); - if (!painter->begin(&m_nativeImage)) + if (!painter->begin(&m_pixmap)) return; // Since ImageBuffer is used mainly for Canvas, explicitly initialize @@ -76,7 +76,22 @@ ImageBufferData::ImageBufferData(const IntSize& size) painter->setBrush(brush); painter->setCompositionMode(QPainter::CompositionMode_SourceOver); - m_image = StillImage::createForRendering(&m_nativeImage); + m_image = StillImage::createForRendering(&m_pixmap); +} + +QImage ImageBufferData::toQImage() const +{ + QPaintEngine* paintEngine = m_pixmap.paintEngine(); + if (!paintEngine || paintEngine->type() != QPaintEngine::Raster) + return m_pixmap.toImage(); + + // QRasterPixmapData::toImage() will deep-copy the backing QImage if there's an active QPainter on it. + // For performance reasons, we don't want that here, so we temporarily redirect the paint engine. + QPaintDevice* currentPaintDevice = paintEngine->paintDevice(); + paintEngine->setPaintDevice(0); + QImage image = m_pixmap.toImage(); + paintEngine->setPaintDevice(currentPaintDevice); + return image; } ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode, DeferralMode, bool& success) @@ -105,9 +120,9 @@ GraphicsContext* ImageBuffer::context() const PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const { if (copyBehavior == CopyBackingStore) - return StillImage::create(m_data.m_nativeImage); + return StillImage::create(m_data.m_pixmap); - return StillImage::createForRendering(&m_data.m_nativeImage); + return StillImage::createForRendering(&m_data.m_pixmap); } void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, @@ -134,12 +149,12 @@ void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& src void ImageBuffer::clip(GraphicsContext* context, const FloatRect& floatRect) const { - QImage* nativeImage = m_data.m_image->nativeImageForCurrentFrame(); + QPixmap* nativeImage = m_data.m_image->nativeImageForCurrentFrame(); if (!nativeImage) return; IntRect rect = enclosingIntRect(floatRect); - QImage alphaMask = *nativeImage; + QPixmap alphaMask = *nativeImage; context->pushTransparencyLayerInternal(rect, 1.0, alphaMask); } @@ -150,7 +165,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) if (isPainting) m_data.m_painter->end(); - QImage image = m_data.m_nativeImage.convertToFormat(QImage::Format_ARGB32); + QImage image = m_data.toQImage().convertToFormat(QImage::Format_ARGB32); ASSERT(!image.isNull()); uchar* bits = image.bits(); @@ -167,10 +182,20 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) } } - m_data.m_nativeImage = image; + m_data.m_pixmap = QPixmap::fromImage(image); if (isPainting) - m_data.m_painter->begin(&m_data.m_nativeImage); + m_data.m_painter->begin(&m_data.m_pixmap); +} + +static inline quint32 convertABGRToARGB(quint32 pixel) +{ + return ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); +} + +static inline quint32 convertARGBToABGR(quint32 pixel) +{ + return convertABGRToARGB(pixel); } template <Multiply multiplied> @@ -209,7 +234,7 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe int numRows = endy - originy; // NOTE: For unmultiplied data, we undo the premultiplication below. - QImage image = imageData.m_nativeImage.convertToFormat(NativeImageQt::defaultFormatForAlphaEnabledImages()); + QImage image = imageData.toQImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); ASSERT(!image.isNull()); @@ -217,40 +242,18 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe const uchar* bits = image.constBits(); quint32* destRows = reinterpret_cast_ptr<quint32*>(&data[desty * rect.width() * 4 + destx * 4]); - - if (multiplied == Unmultiplied) { - for (int y = 0; y < numRows; ++y) { - const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - QRgb pixel = scanLine[x + originx]; - int alpha = qAlpha(pixel); - // Un-premultiply and convert RGB to BGR. - if (alpha == 255) - destRows[x] = (0xFF000000 - | (qBlue(pixel) << 16) - | (qGreen(pixel) << 8) - | (qRed(pixel))); - else if (alpha > 0) - destRows[x] = ((alpha << 24) - | (((255 * qBlue(pixel)) / alpha)) << 16) - | (((255 * qGreen(pixel)) / alpha) << 8) - | ((255 * qRed(pixel)) / alpha); - else - destRows[x] = 0; - } - destRows += rect.width(); - } - } else { - for (int y = 0; y < numRows; ++y) { - const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - QRgb pixel = scanLine[x + originx]; - // Convert RGB to BGR. - destRows[x] = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); - - } - destRows += rect.width(); + for (int y = 0; y < numRows; ++y) { + const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); + for (int x = 0; x < numColumns; x++) { + QRgb pixel = scanLine[x + originx]; + Color pixelColor; + if (multiplied == Unmultiplied) + pixelColor = colorFromPremultipliedARGB(Color(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel)).rgb()); + else + pixelColor = Color(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel)); + destRows[x] = convertARGBToABGR(pixelColor.rgb()); } + destRows += rect.width(); } return result.release(); @@ -266,22 +269,6 @@ PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe return getImageData<Premultiplied>(rect, m_data, m_size); } -static inline unsigned int premultiplyABGRtoARGB(unsigned int x) -{ - unsigned int a = x >> 24; - if (a == 255) - return (x << 16) | ((x >> 16) & 0xff) | (x & 0xff00ff00); - unsigned int t = (x & 0xff00ff) * a; - t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; - t = ((t << 16) | (t >> 16)) & 0xff00ff; - - x = ((x >> 8) & 0xff) * a; - x = (x + ((x >> 8) & 0xff) + 0x80); - x &= 0xff00; - x |= t | (a << 24); - return x; -} - void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) { ASSERT(sourceRect.width() > 0); @@ -319,31 +306,21 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c const quint32* srcScanLine = reinterpret_cast_ptr<const quint32*>(source->data() + originy * srcBytesPerRow + originx * 4); - if (multiplied == Unmultiplied) { - for (int y = 0; y < numRows; ++y) { - quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - // Premultiply and convert BGR to RGB. - quint32 pixel = srcScanLine[x]; - destScanLine[x] = premultiplyABGRtoARGB(pixel); - } - srcScanLine += sourceSize.width(); - } - } else { - for (int y = 0; y < numRows; ++y) { - quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - // Convert BGR to RGB. - quint32 pixel = srcScanLine[x]; - destScanLine[x] = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); - } - srcScanLine += sourceSize.width(); + for (int y = 0; y < numRows; ++y) { + quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); + for (int x = 0; x < numColumns; x++) { + quint32 pixel = convertABGRToARGB(srcScanLine[x]); + if (multiplied == Unmultiplied) + destScanLine[x] = premultipliedARGBFromColor(Color(pixel)); + else + destScanLine[x] = pixel; } + srcScanLine += sourceSize.width(); } bool isPainting = m_data.m_painter->isActive(); if (!isPainting) - m_data.m_painter->begin(&m_data.m_nativeImage); + m_data.m_painter->begin(&m_data.m_pixmap); else { m_data.m_painter->save(); @@ -362,7 +339,7 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c m_data.m_painter->restore(); } -static bool encodeImage(const QImage& image, const String& format, const double* quality, QByteArray& data) +static bool encodeImage(const QPixmap& pixmap, const String& format, const double* quality, QByteArray& data) { int compressionQuality = 100; if (quality && *quality >= 0.0 && *quality <= 1.0) @@ -370,7 +347,7 @@ static bool encodeImage(const QImage& image, const String& format, const double* QBuffer buffer(&data); buffer.open(QBuffer::WriteOnly); - bool success = image.save(&buffer, format.utf8().data(), compressionQuality); + bool success = pixmap.save(&buffer, format.utf8().data(), compressionQuality); buffer.close(); return success; @@ -382,10 +359,10 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo // QImageWriter does not support mimetypes. It does support Qt image formats (png, // gif, jpeg..., xpm) so skip the image/ to get the Qt image format used to encode - // the m_nativeImage image. + // the m_pixmap image. QByteArray data; - if (!encodeImage(m_data.m_nativeImage, mimeType.substring(sizeof "image"), quality, data)) + if (!encodeImage(m_data.m_pixmap, mimeType.substring(sizeof "image"), quality, data)) return "data:,"; return "data:" + mimeType + ";base64," + data.toBase64().data(); diff --git a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index f039e4300..a7d9f7523 100644 --- a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -29,8 +29,8 @@ #include "config.h" #include "ImageDecoderQt.h" -#include <QtCore/QByteArray> #include <QtCore/QBuffer> +#include <QtCore/QByteArray> #include <QtGui/QImageReader> namespace WebCore { @@ -272,7 +272,9 @@ NativeImagePtr ImageFrame::asNewNativeImage() const else format = QImage::Format_RGB32; - return new QImage(reinterpret_cast<uchar*>(m_bytes), m_size.width(), m_size.height(), sizeof(PixelData) * m_size.width(), format); + QImage img(reinterpret_cast<uchar*>(m_bytes), m_size.width(), m_size.height(), sizeof(PixelData) * m_size.width(), format); + + return new QPixmap(QPixmap::fromImage(img)); } } diff --git a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.h b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.h index 3e421c336..8ae3b4239 100644 --- a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.h +++ b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.h @@ -28,11 +28,11 @@ #define ImageDecoderQt_h #include "ImageDecoder.h" +#include <QtCore/QBuffer> +#include <QtCore/QHash> +#include <QtCore/QList> #include <QtGui/QImageReader> #include <QtGui/QPixmap> -#include <QtCore/QList> -#include <QtCore/QHash> -#include <QtCore/QBuffer> #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> diff --git a/Source/WebCore/platform/graphics/qt/ImageQt.cpp b/Source/WebCore/platform/graphics/qt/ImageQt.cpp index 5be31cea0..fc01c407d 100644 --- a/Source/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageQt.cpp @@ -37,7 +37,6 @@ #include "FloatRect.h" #include "GraphicsContext.h" #include "ImageObserver.h" -#include "NativeImageQt.h" #include "ShadowBlur.h" #include "StillImageQt.h" #include <wtf/text/WTFString.h> @@ -56,7 +55,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP, int hbitmapFormat = 0); #endif -typedef QHash<QByteArray, QImage> WebGraphicHash; +typedef QHash<QByteArray, QPixmap> WebGraphicHash; Q_GLOBAL_STATIC(WebGraphicHash, _graphics) static void earlyClearGraphics() @@ -70,28 +69,28 @@ static WebGraphicHash* graphics() if (hash->isEmpty()) { - // prevent ~QImage running after ~QApplication (leaks native images) + // prevent ~QPixmap running after ~QApplication (leaks native pixmaps) qAddPostRoutine(earlyClearGraphics); // QWebSettings::MissingImageGraphic - hash->insert("missingImage", QImage(QLatin1String(":webkit/resources/missingImage.png"))); + hash->insert("missingImage", QPixmap(QLatin1String(":webkit/resources/missingImage.png"))); // QWebSettings::MissingPluginGraphic - hash->insert("nullPlugin", QImage(QLatin1String(":webkit/resources/nullPlugin.png"))); + hash->insert("nullPlugin", QPixmap(QLatin1String(":webkit/resources/nullPlugin.png"))); // QWebSettings::DefaultFrameIconGraphic - hash->insert("urlIcon", QImage(QLatin1String(":webkit/resources/urlIcon.png"))); + hash->insert("urlIcon", QPixmap(QLatin1String(":webkit/resources/urlIcon.png"))); // QWebSettings::TextAreaSizeGripCornerGraphic - hash->insert("textAreaResizeCorner", QImage(QLatin1String(":webkit/resources/textAreaResizeCorner.png"))); + hash->insert("textAreaResizeCorner", QPixmap(QLatin1String(":webkit/resources/textAreaResizeCorner.png"))); // QWebSettings::DeleteButtonGraphic - hash->insert("deleteButton", QImage(QLatin1String(":webkit/resources/deleteButton.png"))); + hash->insert("deleteButton", QPixmap(QLatin1String(":webkit/resources/deleteButton.png"))); // QWebSettings::InputSpeechButtonGraphic - hash->insert("inputSpeech", QImage(QLatin1String(":webkit/resources/inputSpeech.png"))); + hash->insert("inputSpeech", QPixmap(QLatin1String(":webkit/resources/inputSpeech.png"))); } return hash; } // This function loads resources into WebKit -static QImage loadResourceImage(const char *name) +static QPixmap loadResourcePixmap(const char *name) { return graphics()->value(name); } @@ -118,23 +117,23 @@ bool FrameData::clear(bool clearMetadata) PassRefPtr<Image> Image::loadPlatformResource(const char* name) { - return StillImage::create(loadResourceImage(name)); + return StillImage::create(loadResourcePixmap(name)); } -void Image::setPlatformResource(const char* name, const QImage& image) +void Image::setPlatformResource(const char* name, const QPixmap& pixmap) { WebGraphicHash* h = graphics(); - if (image.isNull()) + if (pixmap.isNull()) h->remove(name); else - h->insert(name, image); + h->insert(name, pixmap); } void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect) { - QImage* frameImage = nativeImageForCurrentFrame(); - if (!frameImage) // If it's too early we won't have an image yet. + QPixmap* framePixmap = nativeImageForCurrentFrame(); + if (!framePixmap) // If it's too early we won't have an image yet. return; #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) @@ -149,38 +148,34 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const if (!dr.width() || !dr.height() || !tr.width() || !tr.height()) return; - QImage image = *frameImage; - if (tr.x() || tr.y() || tr.width() != image.width() || tr.height() != image.height()) - image = image.copy(tr); + QPixmap pixmap = *framePixmap; + if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height()) + pixmap = pixmap.copy(tr); CompositeOperator previousOperator = ctxt->compositeOperation(); - ctxt->setCompositeOperation(!image.hasAlphaChannel() && op == CompositeSourceOver ? CompositeCopy : op); + ctxt->setCompositeOperation(!pixmap.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op); QPainter* p = ctxt->platformContext(); QTransform transform(patternTransform); - // If this would draw more than one scaled tile, we scale the image first and then use the result to draw. + // If this would draw more than one scaled tile, we scale the pixmap first and then use the result to draw. if (transform.type() == QTransform::TxScale) { QRectF tileRectInTargetCoords = (transform * QTransform().translate(phase.x(), phase.y())).mapRect(tr); bool tileWillBePaintedOnlyOnce = tileRectInTargetCoords.contains(dr); if (!tileWillBePaintedOnlyOnce) { - QSizeF scaledSize(float(image.width()) * transform.m11(), float(image.height()) * transform.m22()); - QImage scaledImage; - if (image.hasAlphaChannel()) { - scaledImage = QImage(scaledSize.toSize(), NativeImageQt::defaultFormatForAlphaEnabledImages()); - scaledImage.fill(Qt::transparent); - } else - scaledImage = QImage(scaledSize.toSize(), NativeImageQt::defaultFormatForOpaqueImages()); - + QSizeF scaledSize(float(pixmap.width()) * transform.m11(), float(pixmap.height()) * transform.m22()); + QPixmap scaledPixmap(scaledSize.toSize()); + if (pixmap.hasAlpha()) + scaledPixmap.fill(Qt::transparent); { - QPainter painter(&scaledImage); + QPainter painter(&scaledPixmap); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.setRenderHints(p->renderHints()); - painter.drawImage(QRect(0, 0, scaledImage.width(), scaledImage.height()), image); + painter.drawPixmap(QRect(0, 0, scaledPixmap.width(), scaledPixmap.height()), pixmap); } - image = scaledImage; + pixmap = scaledPixmap; transform = QTransform::fromTranslate(transform.dx(), transform.dy()); } } @@ -189,7 +184,7 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const transform *= QTransform().translate(phase.x(), phase.y()); transform.translate(tr.x(), tr.y()); - QBrush b(image); + QBrush b(pixmap); b.setTransform(transform); p->fillRect(dr, b); @@ -199,7 +194,7 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const imageObserver()->didDraw(this); } -BitmapImage::BitmapImage(QImage* image, ImageObserver* observer) +BitmapImage::BitmapImage(QPixmap* pixmap, ImageObserver* observer) : Image(observer) , m_currentFrame(0) , m_frames(0) @@ -217,14 +212,14 @@ BitmapImage::BitmapImage(QImage* image, ImageObserver* observer) , m_sizeAvailable(true) , m_haveFrameCount(true) { - int width = image->width(); - int height = image->height(); + int width = pixmap->width(); + int height = pixmap->height(); m_decodedSize = width * height * 4; m_size = IntSize(width, height); m_frames.grow(1); - m_frames[0].m_frame = image; - m_frames[0].m_hasAlpha = image->hasAlphaChannel(); + m_frames[0].m_frame = pixmap; + m_frames[0].m_hasAlpha = pixmap->hasAlpha(); m_frames[0].m_haveMetadata = true; checkForSolidColor(); } @@ -245,8 +240,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, if (normalizedSrc.isEmpty() || normalizedDst.isEmpty()) return; - QImage* image = nativeImageForCurrentFrame(); - + QPixmap* image = nativeImageForCurrentFrame(); if (!image) return; @@ -260,19 +254,19 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, #endif CompositeOperator previousOperator = ctxt->compositeOperation(); - ctxt->setCompositeOperation(!image->hasAlphaChannel() && op == CompositeSourceOver ? CompositeCopy : op); + ctxt->setCompositeOperation(!image->hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op); if (ctxt->hasShadow()) { ShadowBlur* shadow = ctxt->shadowBlur(); GraphicsContext* shadowContext = shadow->beginShadowLayer(ctxt, normalizedDst); if (shadowContext) { QPainter* shadowPainter = shadowContext->platformContext(); - shadowPainter->drawImage(normalizedDst, *image, normalizedSrc); + shadowPainter->drawPixmap(normalizedDst, *image, normalizedSrc); shadow->endShadowLayer(ctxt); } } - ctxt->platformContext()->drawImage(normalizedDst, *image, normalizedSrc); + ctxt->platformContext()->drawPixmap(normalizedDst, *image, normalizedSrc); ctxt->setCompositeOperation(previousOperator); @@ -288,20 +282,20 @@ void BitmapImage::checkForSolidColor() if (frameCount() > 1) return; - QImage* frameImage = frameAtIndex(0); - if (!frameImage || frameImage->width() != 1 || frameImage->height() != 1) + QPixmap* framePixmap = frameAtIndex(0); + if (!framePixmap || framePixmap->width() != 1 || framePixmap->height() != 1) return; m_isSolidColor = true; - m_solidColor = QColor::fromRgba(frameImage->pixel(0, 0)); + m_solidColor = QColor::fromRgba(framePixmap->toImage().pixel(0, 0)); } #if OS(WINDOWS) PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap) { - QImage* nativeImage = new QImage(qt_pixmapFromWinHBITMAP(hBitmap).toImage()); + QPixmap* qPixmap = new QPixmap(qt_pixmapFromWinHBITMAP(hBitmap)); - return BitmapImage::create(nativeImage); + return BitmapImage::create(qPixmap); } #endif diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 5ad418c23..9ec765caa 100644 --- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -31,20 +31,16 @@ #include "RenderVideo.h" #include "TimeRanges.h" #include "Widget.h" -#include "qwebframe.h" -#include "qwebpage.h" -#include <QGraphicsScene> -#include <QGraphicsVideoItem> #include <QMediaPlayerControl> #include <QMediaService> #include <QNetworkAccessManager> +#include <QNetworkCookie> #include <QNetworkCookieJar> #include <QNetworkRequest> #include <QPainter> #include <QPoint> #include <QRect> -#include <QStyleOptionGraphicsItem> #include <QTime> #include <QTimer> #include <QUrl> @@ -96,7 +92,7 @@ MediaPlayer::SupportsType MediaPlayerPrivateQt::supportsType(const String& mime, codecListTrimmed.append(codecStrTrimmed); } - if (QMediaPlayer::hasSupport(mime, codecListTrimmed) >= QtMultimediaKit::ProbablySupported) + if (QMediaPlayer::hasSupport(mime, codecListTrimmed) >= QtMultimedia::ProbablySupported) return MediaPlayer::IsSupported; return MediaPlayer::MayBeSupported; @@ -106,21 +102,17 @@ MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player) : m_webCorePlayer(player) , m_mediaPlayer(new QMediaPlayer) , m_mediaPlayerControl(0) - , m_videoItem(new QGraphicsVideoItem) - , m_videoScene(new QGraphicsScene) , m_networkState(MediaPlayer::Empty) , m_readyState(MediaPlayer::HaveNothing) , m_currentSize(0, 0) , m_naturalSize(RenderVideo::defaultSize()) - , m_isVisible(false) , m_isSeeking(false) , m_composited(false) , m_preload(MediaPlayer::Auto) , m_bytesLoadedAtLastDidLoadingProgress(0) , m_suppressNextPlaybackChanged(false) { - m_mediaPlayer->setVideoOutput(m_videoItem); - m_videoScene->addItem(m_videoItem); + m_mediaPlayer->setVideoOutput(this); // Signal Handlers connect(m_mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), @@ -139,10 +131,8 @@ MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player) this, SLOT(volumeChanged(int))); connect(m_mediaPlayer, SIGNAL(mutedChanged(bool)), this, SLOT(mutedChanged(bool))); - connect(m_videoScene, SIGNAL(changed(QList<QRectF>)), - this, SLOT(repaint())); - connect(m_videoItem, SIGNAL(nativeSizeChanged(QSizeF)), - this, SLOT(nativeSizeChanged(QSizeF))); + connect(this, SIGNAL(surfaceFormatChanged(const QVideoSurfaceFormat&)), + this, SLOT(surfaceFormatChanged(const QVideoSurfaceFormat&))); // Grab the player control if (QMediaService* service = m_mediaPlayer->service()) { @@ -158,7 +148,6 @@ MediaPlayerPrivateQt::~MediaPlayerPrivateQt() m_mediaPlayer->setMedia(QMediaContent()); delete m_mediaPlayer; - delete m_videoScene; } bool MediaPlayerPrivateQt::hasVideo() const @@ -366,8 +355,8 @@ bool MediaPlayerPrivateQt::didLoadingProgress() const { unsigned bytesLoaded = 0; QLatin1String bytesLoadedKey("bytes-loaded"); - if (m_mediaPlayer->availableExtendedMetaData().contains(bytesLoadedKey)) - bytesLoaded = m_mediaPlayer->extendedMetaData(bytesLoadedKey).toInt(); + if (m_mediaPlayer->availableMetaData().contains(bytesLoadedKey)) + bytesLoaded = m_mediaPlayer->metaData(bytesLoadedKey).toInt(); else bytesLoaded = m_mediaPlayer->bufferStatus(); bool didLoadingProgress = bytesLoaded != m_bytesLoadedAtLastDidLoadingProgress; @@ -377,8 +366,8 @@ bool MediaPlayerPrivateQt::didLoadingProgress() const unsigned MediaPlayerPrivateQt::totalBytes() const { - if (m_mediaPlayer->availableMetaData().contains(QtMultimediaKit::Size)) - return m_mediaPlayer->metaData(QtMultimediaKit::Size).toInt(); + if (m_mediaPlayer->availableMetaData().contains(QtMultimedia::MetaData::Size)) + return m_mediaPlayer->metaData(QtMultimedia::MetaData::Size).toInt(); return 100; } @@ -420,9 +409,8 @@ MediaPlayer::ReadyState MediaPlayerPrivateQt::readyState() const return m_readyState; } -void MediaPlayerPrivateQt::setVisible(bool visible) +void MediaPlayerPrivateQt::setVisible(bool) { - m_isVisible = visible; } void MediaPlayerPrivateQt::mediaStatusChanged(QMediaPlayer::MediaStatus) @@ -443,15 +431,20 @@ void MediaPlayerPrivateQt::stateChanged(QMediaPlayer::State) m_suppressNextPlaybackChanged = false; } -void MediaPlayerPrivateQt::nativeSizeChanged(const QSizeF& size) +void MediaPlayerPrivateQt::surfaceFormatChanged(const QVideoSurfaceFormat& format) { + QSize size = format.sizeHint(); LOG(Media, "MediaPlayerPrivateQt::naturalSizeChanged(%dx%d)", - size.toSize().width(), size.toSize().height()); + size.width(), size.height()); if (!size.isValid()) return; - m_naturalSize = size.toSize(); + IntSize webCoreSize = size; + if (webCoreSize == m_naturalSize) + return; + + m_naturalSize = webCoreSize; m_webCorePlayer->sizeChanged(); } @@ -544,7 +537,6 @@ void MediaPlayerPrivateQt::setSize(const IntSize& size) return; m_currentSize = size; - m_videoItem->setSize(QSizeF(QSize(size))); } IntSize MediaPlayerPrivateQt::naturalSize() const @@ -562,34 +554,58 @@ IntSize MediaPlayerPrivateQt::naturalSize() const void MediaPlayerPrivateQt::removeVideoItem() { - m_oldNaturalSize = m_naturalSize; - m_mediaPlayer->setVideoOutput(static_cast<QGraphicsVideoItem*>(0)); - m_videoScene->removeItem(m_videoItem); + m_mediaPlayer->setVideoOutput(static_cast<QAbstractVideoSurface*>(0)); } void MediaPlayerPrivateQt::restoreVideoItem() { - m_mediaPlayer->setVideoOutput(m_videoItem); - m_videoScene->addItem(m_videoItem); - // FIXME: a qtmobility bug, need to reset the size when restore the videoitem, otherwise the size is 0 - // http://bugreports.qt.nokia.com/browse/QTMOBILITY-971 - nativeSizeChanged(QSize(m_oldNaturalSize)); + m_mediaPlayer->setVideoOutput(this); +} + +// Begin QAbstractVideoSurface implementation. + +bool MediaPlayerPrivateQt::start(const QVideoSurfaceFormat& format) +{ + m_currentVideoFrame = QVideoFrame(); + m_frameFormat = format; + + // If the pixel format is not supported by QImage, then we return false here and the QtMultimedia back-end + // will re-negotiate and call us again with a better format. + if (QVideoFrame::imageFormatFromPixelFormat(m_frameFormat.pixelFormat()) == QImage::Format_Invalid) + return false; + + return QAbstractVideoSurface::start(format); +} + +QList<QVideoFrame::PixelFormat> MediaPlayerPrivateQt::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const +{ + QList<QVideoFrame::PixelFormat> formats; + switch (handleType) { + case QAbstractVideoBuffer::QPixmapHandle: + case QAbstractVideoBuffer::NoHandle: + formats << QVideoFrame::Format_RGB32 << QVideoFrame::Format_ARGB32 << QVideoFrame::Format_RGB565; + break; + default: break; + } + return formats; +} + +bool MediaPlayerPrivateQt::present(const QVideoFrame& frame) +{ + m_currentVideoFrame = frame; + m_webCorePlayer->repaint(); + return true; } +// End QAbstractVideoSurface implementation. + void MediaPlayerPrivateQt::paint(GraphicsContext* context, const IntRect& rect) { #if USE(ACCELERATED_COMPOSITING) if (m_composited) return; #endif - if (context->paintingDisabled()) - return; - - if (!m_isVisible) - return; - - QPainter* painter = context->platformContext(); - m_videoScene->render(painter, QRectF(QRect(rect)), m_videoItem->sceneBoundingRect()); + paintCurrentFrameInContext(context, rect); } void MediaPlayerPrivateQt::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect) @@ -597,32 +613,38 @@ void MediaPlayerPrivateQt::paintCurrentFrameInContext(GraphicsContext* context, if (context->paintingDisabled()) return; - if (!m_isVisible) + if (!m_currentVideoFrame.isValid()) return; - // Grab the painter and widget QPainter* painter = context->platformContext(); - // Render the video, using the item as it might not be in the scene - m_videoItem->paint(painter, 0, 0); -} - -void MediaPlayerPrivateQt::repaint() -{ - m_webCorePlayer->repaint(); + if (m_currentVideoFrame.handleType() == QAbstractVideoBuffer::QPixmapHandle) { + painter->drawPixmap(rect, m_currentVideoFrame.handle().value<QPixmap>()); + } else if (m_currentVideoFrame.map(QAbstractVideoBuffer::ReadOnly)) { + QImage image(m_currentVideoFrame.bits(), + m_frameFormat.frameSize().width(), + m_frameFormat.frameSize().height(), + m_currentVideoFrame.bytesPerLine(), + QVideoFrame::imageFormatFromPixelFormat(m_frameFormat.pixelFormat())); + const QRect target = rect; + + if (m_frameFormat.scanLineDirection() == QVideoSurfaceFormat::BottomToTop) { + const QTransform oldTransform = painter->transform(); + painter->scale(1, -1); + painter->translate(0, -target.bottom()); + painter->drawImage(QRect(target.x(), 0, target.width(), target.height()), image); + painter->setTransform(oldTransform); + } else { + painter->drawImage(target, image); + } + m_currentVideoFrame.unmap(); + } } #if USE(ACCELERATED_COMPOSITING) -void MediaPlayerPrivateQt::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, BitmapTexture*) const -{ - GraphicsContext* context = textureMapper->graphicsContext(); - QPainter* painter = context->platformContext(); - painter->save(); - painter->setTransform(matrix); - painter->setOpacity(opacity); - m_videoScene->render(painter, QRectF(targetRect), m_videoItem->sceneBoundingRect()); - painter->restore(); +void MediaPlayerPrivateQt::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, BitmapTexture*) +{ } #endif diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h index f15af138d..8e31c9d6d 100644 --- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h +++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h @@ -22,8 +22,10 @@ #include "MediaPlayerPrivate.h" +#include <QAbstractVideoSurface> #include <QMediaPlayer> #include <QObject> +#include <QVideoSurfaceFormat> QT_BEGIN_NAMESPACE class QMediaPlayerControl; @@ -37,9 +39,9 @@ QT_END_NAMESPACE namespace WebCore { -class MediaPlayerPrivateQt : public QObject, public MediaPlayerPrivateInterface +class MediaPlayerPrivateQt : public QAbstractVideoSurface, public MediaPlayerPrivateInterface #if USE(ACCELERATED_COMPOSITING) - , public TextureMapperPlatformLayer + , public TextureMapperPlatformLayer #endif { @@ -107,7 +109,7 @@ public: virtual void acceleratedRenderingStateChanged() { } // 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; + virtual void paintToTextureMapper(TextureMapper*, const FloatRect& targetRect, const TransformationMatrix&, float opacity, BitmapTexture* mask); #endif virtual PlatformMedia platformMedia() const; @@ -116,17 +118,21 @@ public: void removeVideoItem(); void restoreVideoItem(); + // QAbstractVideoSurface methods + virtual bool start(const QVideoSurfaceFormat& format); + virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const; + virtual bool present(const QVideoFrame& frame); + private Q_SLOTS: void mediaStatusChanged(QMediaPlayer::MediaStatus); void handleError(QMediaPlayer::Error); void stateChanged(QMediaPlayer::State); - void nativeSizeChanged(const QSizeF&); + void surfaceFormatChanged(const QVideoSurfaceFormat&); void positionChanged(qint64); void durationChanged(qint64); void bufferStatusChanged(int); void volumeChanged(int); void mutedChanged(bool); - void repaint(); private: void updateStates(); @@ -139,15 +145,14 @@ private: MediaPlayer* m_webCorePlayer; QMediaPlayer* m_mediaPlayer; QMediaPlayerControl* m_mediaPlayerControl; - QGraphicsVideoItem* m_videoItem; - QGraphicsScene* m_videoScene; + QVideoSurfaceFormat m_frameFormat; + QVideoFrame m_currentVideoFrame; mutable MediaPlayer::NetworkState m_networkState; mutable MediaPlayer::ReadyState m_readyState; IntSize m_currentSize; IntSize m_naturalSize; - IntSize m_oldNaturalSize; bool m_isVisible; bool m_isSeeking; bool m_composited; diff --git a/Source/WebCore/platform/graphics/qt/PathQt.cpp b/Source/WebCore/platform/graphics/qt/PathQt.cpp index 4f65151b7..577023b46 100644 --- a/Source/WebCore/platform/graphics/qt/PathQt.cpp +++ b/Source/WebCore/platform/graphics/qt/PathQt.cpp @@ -38,8 +38,8 @@ #include "NativeImageQt.h" #include "StrokeStyleApplier.h" #include <QPainterPath> -#include <QTransform> #include <QString> +#include <QTransform> #include <wtf/MathExtras.h> #include <wtf/OwnPtr.h> #include <wtf/text/WTFString.h> @@ -149,11 +149,16 @@ void Path::translate(const FloatSize& size) m_path.translate(size.width(), size.height()); } -FloatRect Path::boundingRect() const +FloatRect Path::fastBoundingRect() const { return m_path.controlPointRect(); } +FloatRect Path::boundingRect() const +{ + return m_path.boundingRect(); +} + FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const { GraphicsContext* context = scratchContext(); diff --git a/Source/WebCore/platform/graphics/qt/PatternQt.cpp b/Source/WebCore/platform/graphics/qt/PatternQt.cpp index 5c9412215..7aae62599 100644 --- a/Source/WebCore/platform/graphics/qt/PatternQt.cpp +++ b/Source/WebCore/platform/graphics/qt/PatternQt.cpp @@ -33,12 +33,12 @@ namespace WebCore { QBrush Pattern::createPlatformPattern() const { - QImage* image = tileImage()->nativeImageForCurrentFrame(); - if (!image) + QPixmap* pixmap = tileImage()->nativeImageForCurrentFrame(); + if (!pixmap) return QBrush(); // Qt merges patter space and user space itself - QBrush brush(*image); + QBrush brush(*pixmap); brush.setTransform(m_patternSpaceTransformation); return brush; diff --git a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp index 8ce9f77da..677d6086c 100644 --- a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp +++ b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp @@ -61,30 +61,30 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const return advances.at(0).x(); } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor); - return adoptPtr(new SimpleFontData(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false)); + return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFraction); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, emphasisMarkFraction); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const diff --git a/Source/WebCore/platform/graphics/qt/StillImageQt.cpp b/Source/WebCore/platform/graphics/qt/StillImageQt.cpp index 041252019..80666ba46 100644 --- a/Source/WebCore/platform/graphics/qt/StillImageQt.cpp +++ b/Source/WebCore/platform/graphics/qt/StillImageQt.cpp @@ -36,41 +36,41 @@ namespace WebCore { -StillImage::StillImage(const QImage& image) - : m_image(new QImage(image)) - , m_ownsImage(true) +StillImage::StillImage(const QPixmap& pixmap) + : m_pixmap(new QPixmap(pixmap)) + , m_ownsPixmap(true) {} -StillImage::StillImage(const QImage* image) - : m_image(image) - , m_ownsImage(false) +StillImage::StillImage(const QPixmap* pixmap) + : m_pixmap(pixmap) + , m_ownsPixmap(false) {} StillImage::~StillImage() { - if (m_ownsImage) - delete m_image; + if (m_ownsPixmap) + delete m_pixmap; } bool StillImage::currentFrameHasAlpha() { - return m_image->hasAlphaChannel(); + return m_pixmap->hasAlpha(); } IntSize StillImage::size() const { - return IntSize(m_image->width(), m_image->height()); + return IntSize(m_pixmap->width(), m_pixmap->height()); } NativeImagePtr StillImage::nativeImageForCurrentFrame() { - return const_cast<NativeImagePtr>(m_image); + return const_cast<NativeImagePtr>(m_pixmap); } void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace, CompositeOperator op) { - if (m_image->isNull()) + if (m_pixmap->isNull()) return; FloatRect normalizedSrc = src.normalized(); @@ -84,12 +84,12 @@ void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst, GraphicsContext* shadowContext = shadow->beginShadowLayer(ctxt, normalizedDst); if (shadowContext) { QPainter* shadowPainter = shadowContext->platformContext(); - shadowPainter->drawImage(normalizedDst, *m_image, normalizedSrc); + shadowPainter->drawPixmap(normalizedDst, *m_pixmap, normalizedSrc); shadow->endShadowLayer(ctxt); } } - ctxt->platformContext()->drawImage(normalizedDst, *m_image, normalizedSrc); + ctxt->platformContext()->drawPixmap(normalizedDst, *m_pixmap, normalizedSrc); ctxt->setCompositeOperation(previousOperator); } diff --git a/Source/WebCore/platform/graphics/qt/StillImageQt.h b/Source/WebCore/platform/graphics/qt/StillImageQt.h index 8c9ec0d88..0609b5458 100644 --- a/Source/WebCore/platform/graphics/qt/StillImageQt.h +++ b/Source/WebCore/platform/graphics/qt/StillImageQt.h @@ -34,14 +34,14 @@ namespace WebCore { class StillImage : public Image { public: - static PassRefPtr<StillImage> create(const QImage& image) + static PassRefPtr<StillImage> create(const QPixmap& pixmap) { - return adoptRef(new StillImage(image)); + return adoptRef(new StillImage(pixmap)); } - static PassRefPtr<StillImage> createForRendering(const QImage* image) + static PassRefPtr<StillImage> createForRendering(const QPixmap* pixmap) { - return adoptRef(new StillImage(image)); + return adoptRef(new StillImage(pixmap)); } virtual bool currentFrameHasAlpha(); @@ -56,12 +56,12 @@ namespace WebCore { virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator); private: - StillImage(const QImage&); - StillImage(const QImage*); + StillImage(const QPixmap&); + StillImage(const QPixmap*); virtual ~StillImage(); - const QImage* m_image; - bool m_ownsImage; + const QPixmap* m_pixmap; + bool m_ownsPixmap; }; } diff --git a/Source/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp b/Source/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp index 7ff432b17..73a0e414f 100644 --- a/Source/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp +++ b/Source/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp @@ -27,8 +27,8 @@ #include "AffineTransform.h" #include "TransformationMatrix.h" -#include "IntRect.h" #include "FloatRect.h" +#include "IntRect.h" namespace WebCore { diff --git a/Source/WebCore/platform/graphics/qt/TransparencyLayer.h b/Source/WebCore/platform/graphics/qt/TransparencyLayer.h index 5974017be..f13deb03b 100644 --- a/Source/WebCore/platform/graphics/qt/TransparencyLayer.h +++ b/Source/WebCore/platform/graphics/qt/TransparencyLayer.h @@ -36,24 +36,24 @@ #ifndef TransparencyLayer_h #define TransparencyLayer_h -#include <NativeImageQt.h> #include <QPaintEngine> #include <QPainter> +#include <QPixmap> namespace WebCore { struct TransparencyLayer { WTF_MAKE_FAST_ALLOCATED; public: - TransparencyLayer(const QPainter* p, const QRect &rect, qreal opacity, QImage& alphaMask) - : image(rect.width(), rect.height(), NativeImageQt::defaultFormatForAlphaEnabledImages()) + TransparencyLayer(const QPainter* p, const QRect &rect, qreal opacity, QPixmap& alphaMask) + : pixmap(rect.width(), rect.height()) , opacity(opacity) , alphaMask(alphaMask) , saveCounter(1) // see the comment for saveCounter { offset = rect.topLeft(); - image.fill(Qt::transparent); - painter.begin(&image); + pixmap.fill(Qt::transparent); + painter.begin(&pixmap); painter.setRenderHints(p->renderHints()); painter.translate(-offset); painter.setPen(p->pen()); @@ -67,12 +67,12 @@ public: { } - QImage image; + QPixmap pixmap; QPoint offset; QPainter painter; qreal opacity; // for clipToImageBuffer - QImage alphaMask; + QPixmap alphaMask; // saveCounter is only used in combination with alphaMask // otherwise, its value is unspecified int saveCounter; diff --git a/Source/WebCore/platform/graphics/skia/FontCacheSkia.cpp b/Source/WebCore/platform/graphics/skia/FontCacheSkia.cpp index 271c3d7e9..336abc430 100644 --- a/Source/WebCore/platform/graphics/skia/FontCacheSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/FontCacheSkia.cpp @@ -30,20 +30,16 @@ #include "config.h" #include "FontCache.h" - #include "Font.h" #include "FontDescription.h" #include "FontFamily.h" #include "FontPlatformData.h" #include "Logging.h" #include "NotImplemented.h" -#include "PlatformSupport.h" #include "SimpleFontData.h" - #include "SkPaint.h" #include "SkTypeface.h" #include "SkUtils.h" - #include <unicode/locid.h> #include <wtf/Assertions.h> #include <wtf/text/AtomicString.h> @@ -55,9 +51,7 @@ void FontCache::platformInit() { } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, - const UChar* characters, - int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { icu::Locale locale = icu::Locale::getDefault(); FontCache::SimpleFontFamily family; @@ -94,12 +88,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, return getCachedFontData(&platformData, DoNotRetain); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) { DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("Sans")); DEFINE_STATIC_LOCAL(const AtomicString, serifStr, ("Serif")); diff --git a/Source/WebCore/platform/graphics/skia/FontSkia.cpp b/Source/WebCore/platform/graphics/skia/FontSkia.cpp index 03f1417fb..c8097e349 100644 --- a/Source/WebCore/platform/graphics/skia/FontSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/FontSkia.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "Font.h" +#include "FontSmoothingMode.h" #include "GlyphBuffer.h" #include "GraphicsContext.h" #include "LayoutTestSupport.h" @@ -71,6 +72,16 @@ static void setupPaint(SkPaint* paint, const SimpleFontData* fontData, const Fon paint->setAutohinted(false); // freetype specific paint->setLCDRenderText(shouldSmoothFonts); paint->setSubpixelText(true); + +#if OS(DARWIN) + // When using CoreGraphics, disable hinting when webkit-font-smoothing:antialiased is used. + // See crbug.com/152304 + if (font->fontDescription().fontSmoothing() == Antialiased) + paint->setHinting(SkPaint::kNo_Hinting); +#endif + + if (font->fontDescription().textRenderingMode() == GeometricPrecision) + paint->setHinting(SkPaint::kNo_Hinting); } // TODO: This needs to be split into helper functions to better scope the @@ -120,8 +131,8 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, for (int i = 0; i < numGlyphs; i++) { pos[i].set(x, y); - x += SkFloatToScalar(adv[i].width); - y += SkFloatToScalar(adv[i].height); + x += SkFloatToScalar(adv[i].width()); + y += SkFloatToScalar(adv[i].height()); } SkCanvas* canvas = gc->platformContext()->canvas(); diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 35231a9da..fc9714671 100644 --- a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -83,11 +83,6 @@ inline int fastMod(int value, int max) return value; } -inline float square(float n) -{ - return n * n; -} - } // namespace // Local helper functions ------------------------------------------------------ @@ -121,6 +116,89 @@ void addCornerArc(SkPath* path, const SkRect& rect, const IntSize& size, int sta path->arcTo(r, SkIntToScalar(startAngle), SkIntToScalar(90), false); } +void draw2xMarker(SkBitmap* bitmap, int index) +{ + + static const SkPMColor lineColors[2] = { + SkPreMultiplyARGB(0xFF, 0xFF, 0x00, 0x00), // Opaque red. + SkPreMultiplyARGB(0xFF, 0xC0, 0xC0, 0xC0), // Opaque gray. + }; + static const SkPMColor antiColors1[2] = { + SkPreMultiplyARGB(0xB0, 0xFF, 0x00, 0x00), // Semitransparent red + SkPreMultiplyARGB(0xB0, 0xC0, 0xC0, 0xC0), // Semitransparent gray + }; + static const SkPMColor antiColors2[2] = { + SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00), // More transparent red + SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0), // More transparent gray + }; + + const SkPMColor lineColor = lineColors[index]; + const SkPMColor antiColor1 = antiColors1[index]; + const SkPMColor antiColor2 = antiColors2[index]; + + uint32_t* row1 = bitmap->getAddr32(0, 0); + uint32_t* row2 = bitmap->getAddr32(0, 1); + uint32_t* row3 = bitmap->getAddr32(0, 2); + uint32_t* row4 = bitmap->getAddr32(0, 3); + + // Pattern: X0o o0X0o o0 + // XX0o o0XXX0o o0X + // o0XXX0o o0XXX0o + // o0X0o o0X0o + const SkPMColor row1Color[] = { lineColor, antiColor1, antiColor2, 0, 0, 0, antiColor2, antiColor1 }; + const SkPMColor row2Color[] = { lineColor, lineColor, antiColor1, antiColor2, 0, antiColor2, antiColor1, lineColor }; + const SkPMColor row3Color[] = { 0, antiColor2, antiColor1, lineColor, lineColor, lineColor, antiColor1, antiColor2 }; + const SkPMColor row4Color[] = { 0, 0, antiColor2, antiColor1, lineColor, antiColor1, antiColor2, 0 }; + + for (int x = 0; x < bitmap->width() + 8; x += 8) { + int count = min(bitmap->width() - x, 8); + if (count > 0) { + memcpy(row1 + x, row1Color, count * sizeof(SkPMColor)); + memcpy(row2 + x, row2Color, count * sizeof(SkPMColor)); + memcpy(row3 + x, row3Color, count * sizeof(SkPMColor)); + memcpy(row4 + x, row4Color, count * sizeof(SkPMColor)); + } + } +} + +void draw1xMarker(SkBitmap* bitmap, int index) +{ + static const uint32_t lineColors[2] = { + 0xFF << SK_A32_SHIFT | 0xFF << SK_R32_SHIFT, // Opaque red. + 0xFF << SK_A32_SHIFT | 0xC0 << SK_R32_SHIFT | 0xC0 << SK_G32_SHIFT | 0xC0 << SK_B32_SHIFT, // Opaque gray. + }; + static const uint32_t antiColors[2] = { + 0x60 << SK_A32_SHIFT | 0x60 << SK_R32_SHIFT, // Semitransparent red + 0xFF << SK_A32_SHIFT | 0xC0 << SK_R32_SHIFT | 0xC0 << SK_G32_SHIFT | 0xC0 << SK_B32_SHIFT, // Semitransparent gray + }; + + const uint32_t lineColor = lineColors[index]; + const uint32_t antiColor = antiColors[index]; + + // Pattern: X o o X o o X + // o X o o X o + uint32_t* row1 = bitmap->getAddr32(0, 0); + uint32_t* row2 = bitmap->getAddr32(0, 1); + for (int x = 0; x < bitmap->width(); x++) { + switch (x % 4) { + case 0: + row1[x] = lineColor; + break; + case 1: + row1[x] = antiColor; + row2[x] = antiColor; + break; + case 2: + row2[x] = lineColor; + break; + case 3: + row1[x] = antiColor; + row2[x] = antiColor; + break; + } + } +} + // ----------------------------------------------------------------------------- // This may be called with a NULL pointer to create a graphics context that has @@ -522,92 +600,106 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt if (paintingDisabled()) return; + int deviceScaleFactor = SkScalarRoundToInt(WebCoreFloatToSkScalar(platformContext()->deviceScaleFactor())); + ASSERT(deviceScaleFactor == 1 || deviceScaleFactor == 2); + // Create the pattern we'll use to draw the underline. int index = style == DocumentMarkerGrammarLineStyle ? 1 : 0; - static SkBitmap* misspellBitmap[2] = { 0, 0 }; + static SkBitmap* misspellBitmap1x[2] = { 0, 0 }; + static SkBitmap* misspellBitmap2x[2] = { 0, 0 }; + SkBitmap** misspellBitmap = deviceScaleFactor == 2 ? misspellBitmap2x : misspellBitmap1x; if (!misspellBitmap[index]) { #if PLATFORM(CHROMIUM) && OS(DARWIN) // Match the artwork used by the Mac. - const int rowPixels = 4; - const int colPixels = 3; -#else - // We use a 2-pixel-high misspelling indicator because that seems to be - // what WebKit is designed for, and how much room there is in a typical - // page for it. - const int rowPixels = 32; // Must be multiple of 4 for pattern below. - const int colPixels = 2; -#endif + const int rowPixels = 4 * deviceScaleFactor; + const int colPixels = 3 * deviceScaleFactor; misspellBitmap[index] = new SkBitmap; misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config, rowPixels, colPixels); misspellBitmap[index]->allocPixels(); misspellBitmap[index]->eraseARGB(0, 0, 0, 0); -#if PLATFORM(CHROMIUM) && OS(DARWIN) - const uint32_t colors[2][6] = { - { 0x2A2A0600, 0x57571000, 0xA8A81B00, 0xBFBF1F00, 0x70701200, 0xE0E02400 }, - { 0x2A001503, 0x57002A08, 0xA800540D, 0xBF005F0F, 0x70003809, 0xE0007012 } - }; const uint32_t transparentColor = 0x00000000; - // Pattern: a b a a b a - // c d c c d c - // e f e e f e - for (int x = 0; x < colPixels; ++x) { - uint32_t* row = misspellBitmap[index]->getAddr32(0, x); - row[0] = colors[index][x * 2]; - row[1] = colors[index][x * 2 + 1]; - row[2] = colors[index][x * 2]; - row[3] = transparentColor; - } -#else - static const uint32_t lineColors[2] = { - 0xFF << SK_A32_SHIFT | 0xFF << SK_R32_SHIFT, // Opaque red. - 0xFF << SK_A32_SHIFT | 0xC0 << SK_R32_SHIFT | 0xC0 << SK_G32_SHIFT | 0xC0 << SK_B32_SHIFT, // Opaque gray. - }; - static const uint32_t antiColors[2] = { - 0x60 << SK_A32_SHIFT | 0x60 << SK_R32_SHIFT, // Semitransparent red - 0xFF << SK_A32_SHIFT | 0xC0 << SK_R32_SHIFT | 0xC0 << SK_G32_SHIFT | 0xC0 << SK_B32_SHIFT, // Semitransparent gray - }; - const uint32_t lineColor = lineColors[index]; - const uint32_t antiColor = antiColors[index]; - - // Pattern: X o o X o o X - // o X o o X o - uint32_t* row1 = misspellBitmap[index]->getAddr32(0, 0); - uint32_t* row2 = misspellBitmap[index]->getAddr32(0, 1); - for (int x = 0; x < rowPixels; x++) { - switch (x % 4) { - case 0: - row1[x] = lineColor; - break; - case 1: - row1[x] = antiColor; - row2[x] = antiColor; - break; - case 2: - row2[x] = lineColor; - break; - case 3: - row1[x] = antiColor; - row2[x] = antiColor; - break; + if (deviceScaleFactor == 1) { + const uint32_t colors[2][6] = { + { 0x2A2A0600, 0x57571000, 0xA8A81B00, 0xBFBF1F00, 0x70701200, 0xE0E02400 }, + { 0x2A001503, 0x57002A08, 0xA800540D, 0xBF005F0F, 0x70003809, 0xE0007012 } + }; + + // Pattern: a b a a b a + // c d c c d c + // e f e e f e + for (int x = 0; x < colPixels; ++x) { + uint32_t* row = misspellBitmap[index]->getAddr32(0, x); + row[0] = colors[index][x * 2]; + row[1] = colors[index][x * 2 + 1]; + row[2] = colors[index][x * 2]; + row[3] = transparentColor; } - } + } else if (deviceScaleFactor == 2) { + const uint32_t colors[2][18] = { + { 0x0a090101, 0x33320806, 0x55540f0a, 0x37360906, 0x6e6c120c, 0x6e6c120c, 0x7674140d, 0x8d8b1810, 0x8d8b1810, + 0x96941a11, 0xb3b01f15, 0xb3b01f15, 0x6d6b130c, 0xd9d62619, 0xd9d62619, 0x19180402, 0x7c7a150e, 0xcecb2418 }, + { 0x0a000400, 0x33031b06, 0x55062f0b, 0x37041e06, 0x6e083d0d, 0x6e083d0d, 0x7608410e, 0x8d094e11, 0x8d094e11, + 0x960a5313, 0xb30d6417, 0xb30d6417, 0x6d073c0d, 0xd90f781c, 0xd90f781c, 0x19010d03, 0x7c094510, 0xce0f731a } + }; + + // Pattern: a b c c b a + // d e f f e d + // g h j j h g + // k l m m l k + // n o p p o n + // q r s s r q + for (int x = 0; x < colPixels; ++x) { + uint32_t* row = misspellBitmap[index]->getAddr32(0, x); + row[0] = colors[index][x * 3]; + row[1] = colors[index][x * 3 + 1]; + row[2] = colors[index][x * 3 + 2]; + row[3] = colors[index][x * 3 + 2]; + row[4] = colors[index][x * 3 + 1]; + row[5] = colors[index][x * 3]; + row[6] = transparentColor; + row[7] = transparentColor; + } + } else + ASSERT_NOT_REACHED(); +#else + // We use a 2-pixel-high misspelling indicator because that seems to be + // what WebKit is designed for, and how much room there is in a typical + // page for it. + const int rowPixels = 32 * deviceScaleFactor; // Must be multiple of 4 for pattern below. + const int colPixels = 2 * deviceScaleFactor; + misspellBitmap[index] = new SkBitmap; + misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config, rowPixels, colPixels); + misspellBitmap[index]->allocPixels(); + + misspellBitmap[index]->eraseARGB(0, 0, 0, 0); + if (deviceScaleFactor == 1) + draw1xMarker(misspellBitmap[index], index); + else if (deviceScaleFactor == 2) + draw2xMarker(misspellBitmap[index], index); + else + ASSERT_NOT_REACHED(); #endif } - SkScalar originX = WebCoreFloatToSkScalar(pt.x()); #if PLATFORM(CHROMIUM) && OS(DARWIN) - SkScalar originY = WebCoreFloatToSkScalar(pt.y()); + SkScalar originX = WebCoreFloatToSkScalar(pt.x()) * deviceScaleFactor; + SkScalar originY = WebCoreFloatToSkScalar(pt.y()) * deviceScaleFactor; + // Make sure to draw only complete dots. int rowPixels = misspellBitmap[index]->width(); - float widthMod = fmodf(width, rowPixels); - if (rowPixels - widthMod > 1) - width -= widthMod; + float widthMod = fmodf(width * deviceScaleFactor, rowPixels); + if (rowPixels - widthMod > deviceScaleFactor) + width -= widthMod / deviceScaleFactor; #else + SkScalar originX = WebCoreFloatToSkScalar(pt.x()); + // Offset it vertically by 1 so that there's some space under the text. SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1; + originX *= deviceScaleFactor; + originY *= deviceScaleFactor; #endif // Make a shader for the bitmap with an origin of the box we'll draw. This @@ -616,23 +708,26 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt *misspellBitmap[index], SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); SkMatrix matrix; - matrix.reset(); - matrix.postTranslate(originX, originY); + matrix.setTranslate(originX, originY); shader->setLocalMatrix(matrix); // Assign the shader to the paint & release our reference. The paint will // now own the shader and the shader will be destroyed when the paint goes // out of scope. SkPaint paint; - paint.setShader(shader); - shader->unref(); + paint.setShader(shader)->unref(); SkRect rect; - rect.set(originX, - originY, - originX + WebCoreFloatToSkScalar(width), - originY + SkIntToScalar(misspellBitmap[index]->height())); + rect.set(originX, originY, originX + WebCoreFloatToSkScalar(width) * deviceScaleFactor, originY + SkIntToScalar(misspellBitmap[index]->height())); + + if (deviceScaleFactor == 2) { + platformContext()->canvas()->save(); + platformContext()->canvas()->scale(SK_ScalarHalf, SK_ScalarHalf); + } platformContext()->canvas()->drawRect(rect, paint); + if (deviceScaleFactor == 2) + platformContext()->canvas()->restore(); + platformContext()->didDrawRect(rect, paint); } diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index 905480d10..82c367d29 100644 --- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -42,6 +42,7 @@ #include "ImageData.h" #include "JPEGImageEncoder.h" #include "MIMETypeRegistry.h" +#include "MemoryInstrumentationSkia.h" #include "PNGImageEncoder.h" #include "PlatformContextSkia.h" #include "SharedGraphicsContext3D.h" @@ -373,6 +374,16 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo return "data:" + mimeType + ";base64," + base64Data; } +void ImageBufferData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this); + info.addMember(m_canvas); + info.addMember(m_platformContext); +#if USE(ACCELERATED_COMPOSITING) + info.addMember(m_layerBridge); +#endif +} + String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, const double* quality) { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); diff --git a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp index 8f883d819..e5a52411d 100644 --- a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -40,6 +40,7 @@ #include "Logging.h" #include "NativeImageSkia.h" #include "PlatformContextSkia.h" +#include "SkBitmap.h" #include "SkPixelRef.h" #include "SkRect.h" #include "SkShader.h" @@ -50,6 +51,9 @@ #include "skia/ext/image_operations.h" #include "skia/ext/platform_canvas.h" +#include <limits> +#include <math.h> + #if PLATFORM(CHROMIUM) #include "TraceEvent.h" #endif @@ -70,11 +74,8 @@ enum ResamplingMode { RESAMPLE_AWESOME, }; -static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const NativeImageSkia& bitmap, int srcWidth, int srcHeight, float destWidth, float destHeight) +static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const NativeImageSkia& bitmap, float srcWidth, float srcHeight, float destWidth, float destHeight) { - int destIWidth = static_cast<int>(destWidth); - int destIHeight = static_cast<int>(destHeight); - // The percent change below which we will not resample. This usually means // an off-by-one error on the web page, and just doing nearest neighbor // sampling is usually good enough. @@ -92,10 +93,13 @@ static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const Native // Figure out if we should resample this image. We try to prune out some // common cases where resampling won't give us anything, since it is much // slower than drawing stretched. - if (srcWidth == destIWidth && srcHeight == destIHeight) { - // We don't need to resample if the source and destination are the same. + float diffWidth = fabs(destWidth - srcWidth); + float diffHeight = fabs(destHeight - srcHeight); + bool widthNearlyEqual = diffWidth < std::numeric_limits<float>::epsilon(); + bool heightNearlyEqual = diffHeight < std::numeric_limits<float>::epsilon(); + // We don't need to resample if the source and destination are the same. + if (widthNearlyEqual && heightNearlyEqual) return RESAMPLE_NONE; - } if (srcWidth <= kSmallImageSizeThreshold || srcHeight <= kSmallImageSizeThreshold @@ -113,7 +117,7 @@ static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const Native // This is trying to catch cases where somebody has created a border // (which might be large) and then is stretching it to fill some part // of the page. - if (srcWidth == destWidth || srcHeight == destHeight) + if (widthNearlyEqual || heightNearlyEqual) return RESAMPLE_NONE; // The image is growing a lot and in more than one direction. Resampling @@ -121,8 +125,8 @@ static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const Native return RESAMPLE_LINEAR; } - if ((fabs(destWidth - srcWidth) / srcWidth < kFractionalChangeThreshold) - && (fabs(destHeight - srcHeight) / srcHeight < kFractionalChangeThreshold)) { + if ((diffWidth / srcWidth < kFractionalChangeThreshold) + && (diffHeight / srcHeight < kFractionalChangeThreshold)) { // It is disappointingly common on the web for image sizes to be off by // one or two pixels. We don't bother resampling if the size difference // is a small fraction of the original size. @@ -162,11 +166,127 @@ static ResamplingMode limitResamplingMode(PlatformContextSkia* platformContext, return resampling; } -// Draws the given bitmap to the given canvas. The subset of the source bitmap -// identified by src_rect is drawn to the given destination rect. The bitmap -// will be resampled to resample_width * resample_height (this is the size of -// the whole image, not the subset). See shouldResampleBitmap for more. +// Return true if the rectangle is aligned to integer boundaries. +// See comments for computeBitmapDrawRects() for how this is used. +static bool areBoundariesIntegerAligned(const SkRect& rect) +{ + // Value is 1.19209e-007. This is the tolerance threshold. + const float epsilon = std::numeric_limits<float>::epsilon(); + SkIRect roundedRect = roundedIntRect(rect); + + return fabs(rect.x() - roundedRect.x()) < epsilon + && fabs(rect.y() - roundedRect.y()) < epsilon + && fabs(rect.right() - roundedRect.right()) < epsilon + && fabs(rect.bottom() - roundedRect.bottom()) < epsilon; +} + +// FIXME: Remove this code when SkCanvas accepts SkRect as source rectangle. +// See crbug.com/117597 for background. +// +// WebKit wants to draw a sub-rectangle (FloatRect) in a bitmap and scale it to +// another FloatRect. However Skia only allows bitmap to be addressed by a +// IntRect. This function computes the appropriate IntRect that encloses the +// source rectangle and the corresponding enclosing destination rectangle, +// while maintaining the scale factor. +// +// |srcRect| is the source rectangle in the bitmap. Return true if fancy +// alignment is required. User of this function needs to clip to |dstRect|. +// Return false if clipping is not needed. +// +// |dstRect| is the input rectangle that |srcRect| is scaled to. +// +// |outSrcRect| and |outDstRect| are the corresponding output rectangles. +// +// ALGORITHM +// +// The objective is to (a) find an enclosing IntRect for the source rectangle +// and (b) the corresponding FloatRect in destination space. +// +// These are the steps performed: +// +// 1. IntRect enclosingSrcRect = enclosingIntRect(srcRect) +// +// Compute the enclosing IntRect for |srcRect|. This ensures the bitmap +// image is addressed with integer boundaries. +// +// 2. FloatRect enclosingDestRect = mapSrcToDest(enclosingSrcRect) +// +// Map the enclosing source rectangle to destination coordinate space. +// +// The output will be enclosingSrcRect and enclosingDestRect from the +// algorithm above. +static bool computeBitmapDrawRects(const SkISize& bitmapSize, const SkRect& srcRect, const SkRect& dstRect, SkIRect* outSrcRect, SkRect* outDstRect) +{ + if (areBoundariesIntegerAligned(srcRect)) { + *outSrcRect = roundedIntRect(srcRect); + *outDstRect = dstRect; + return false; + } + + SkIRect bitmapRect = SkIRect::MakeSize(bitmapSize); + SkIRect enclosingSrcRect = enclosingIntRect(srcRect); + enclosingSrcRect.intersect(bitmapRect); // Clip to bitmap rectangle. + SkRect enclosingDstRect; + enclosingDstRect.set(enclosingSrcRect); + SkMatrix transform; + transform.setRectToRect(srcRect, dstRect, SkMatrix::kFill_ScaleToFit); + transform.mapRect(&enclosingDstRect); + *outSrcRect = enclosingSrcRect; + *outDstRect = enclosingDstRect; + return true; +} + +// This function is used to scale an image and extract a scaled fragment. // +// ALGORITHM +// +// Because the scaled image size has to be integers, we approximate the real +// scale with the following formula (only X direction is shown): +// +// scaledImageWidth = round(scaleX * imageRect.width()) +// approximateScaleX = scaledImageWidth / imageRect.width() +// +// With this method we maintain a constant scale factor among fragments in +// the scaled image. This allows fragments to stitch together to form the +// full scaled image. The downside is there will be a small difference +// between |scaleX| and |approximateScaleX|. +// +// A scaled image fragment is identified by: +// +// - Scaled image size +// - Scaled image fragment rectangle (IntRect) +// +// Scaled image size has been determined and the next step is to compute the +// rectangle for the scaled image fragment which needs to be an IntRect. +// +// scaledSrcRect = srcRect * (approximateScaleX, approximateScaleY) +// enclosingScaledSrcRect = enclosingIntRect(scaledSrcRect) +// +// Finally we extract the scaled image fragment using +// (scaledImageSize, enclosingScaledSrcRect). +// +static SkBitmap extractScaledImageFragment(const NativeImageSkia& bitmap, const SkRect& srcRect, float scaleX, float scaleY, SkRect* scaledSrcRect, SkIRect* enclosingScaledSrcRect) +{ + SkISize imageSize = SkISize::Make(bitmap.bitmap().width(), bitmap.bitmap().height()); + SkISize scaledImageSize = SkISize::Make(clampToInteger(roundf(imageSize.width() * scaleX)), + clampToInteger(roundf(imageSize.height() * scaleY))); + + SkRect imageRect = SkRect::MakeWH(imageSize.width(), imageSize.height()); + SkRect scaledImageRect = SkRect::MakeWH(scaledImageSize.width(), scaledImageSize.height()); + + SkMatrix scaleTransform; + scaleTransform.setRectToRect(imageRect, scaledImageRect, SkMatrix::kFill_ScaleToFit); + scaleTransform.mapRect(scaledSrcRect, srcRect); + + scaledSrcRect->intersect(scaledImageRect); + *enclosingScaledSrcRect = enclosingIntRect(*scaledSrcRect); + + // |enclosingScaledSrcRect| can be larger than |scaledImageSize| because + // of float inaccuracy so clip to get inside. + enclosingScaledSrcRect->intersect(SkIRect::MakeSize(scaledImageSize)); + return bitmap.resizedBitmap(scaledImageSize, *enclosingScaledSrcRect); +} + // This does a lot of computation to resample only the portion of the bitmap // that will only be drawn. This is critical for performance since when we are // scrolling, for example, we are only drawing a small strip of the image. @@ -175,48 +295,62 @@ static ResamplingMode limitResamplingMode(PlatformContextSkia* platformContext, // // Note: this code is only used when the canvas transformation is limited to // scaling or translation. -static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeImageSkia& bitmap, const SkIRect& srcIRect, const SkRect& destRect) +static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeImageSkia& bitmap, const SkRect& srcRect, const SkRect& destRect) { #if PLATFORM(CHROMIUM) TRACE_EVENT0("skia", "drawResampledBitmap"); #endif - // Apply forward transform to destRect to estimate required size of - // re-sampled bitmap, and use only in calls required to resize, or that - // check for the required size. - SkRect destRectTransformed; - canvas.getTotalMatrix().mapRect(&destRectTransformed, destRect); - SkIRect destRectTransformedRounded; - destRectTransformed.round(&destRectTransformedRounded); - - // Compute the visible portion of our rect. + // We want to scale |destRect| with transformation in the canvas to obtain + // the final scale. The final scale is a combination of scale transform + // in canvas and explicit scaling (srcRect and destRect). + SkRect screenRect; + canvas.getTotalMatrix().mapRect(&screenRect, destRect); + float realScaleX = screenRect.width() / srcRect.width(); + float realScaleY = screenRect.height() / srcRect.height(); + + // This part of code limits scaling only to visible portion in the SkRect destRectVisibleSubset; ClipRectToCanvas(canvas, destRect, &destRectVisibleSubset); + // ClipRectToCanvas often overshoots, resulting in a larger region than our // original destRect. Intersecting gets us back inside. if (!destRectVisibleSubset.intersect(destRect)) return; // Nothing visible in destRect. - // Compute the transformed (screen space) portion of the visible portion for - // use below. - SkRect destRectVisibleSubsetTransformed; - canvas.getTotalMatrix().mapRect(&destRectVisibleSubsetTransformed, destRectVisibleSubset); - SkRect destBitmapSubsetTransformed = destRectVisibleSubsetTransformed; - destBitmapSubsetTransformed.offset(-destRectTransformed.fLeft, - -destRectTransformed.fTop); - SkIRect destBitmapSubsetTransformedRounded; - destBitmapSubsetTransformed.round(&destBitmapSubsetTransformedRounded); - - // Transforms above plus rounding may cause destBitmapSubsetTransformedRounded - // to go outside the image, so need to clip to avoid problems. - if (!destBitmapSubsetTransformedRounded.intersect( - 0, 0, destRectTransformedRounded.width(), destRectTransformedRounded.height())) - return; // Image is not visible. - - SkBitmap resampled = bitmap.resizedBitmap(srcIRect, - destRectTransformedRounded.width(), - destRectTransformedRounded.height(), - destBitmapSubsetTransformedRounded); - canvas.drawBitmapRect(resampled, 0, destRectVisibleSubset, &paint); + // Find the corresponding rect in the source image. + SkMatrix destToSrcTransform; + SkRect srcRectVisibleSubset; + destToSrcTransform.setRectToRect(destRect, srcRect, SkMatrix::kFill_ScaleToFit); + destToSrcTransform.mapRect(&srcRectVisibleSubset, destRectVisibleSubset); + + SkRect scaledSrcRect; + SkIRect enclosingScaledSrcRect; + SkBitmap scaledImageFragment = extractScaledImageFragment(bitmap, srcRectVisibleSubset, realScaleX, realScaleY, &scaledSrcRect, &enclosingScaledSrcRect); + + // Expand the destination rectangle because the source rectangle was + // expanded to fit to integer boundaries. + SkMatrix scaledSrcToDestTransform; + scaledSrcToDestTransform.setRectToRect(scaledSrcRect, destRectVisibleSubset, SkMatrix::kFill_ScaleToFit); + SkRect enclosingDestRect; + enclosingDestRect.set(enclosingScaledSrcRect); + scaledSrcToDestTransform.mapRect(&enclosingDestRect); + + // The reason we do clipping is because Skia doesn't support SkRect as + // source rect. See http://crbug.com/145540. + // When Skia supports then use this as the source rect to replace 0. + // + // scaledSrcRect.offset(-enclosingScaledSrcRect.x(), -enclosingScaledSrcRect.y()); + canvas.save(); + canvas.clipRect(destRectVisibleSubset); + + // Because the image fragment is generated with an approxmiated scaling + // factor. This draw will perform a close to 1 scaling. + // + // NOTE: For future optimization. If the difference in scale is so small + // that Skia doesn't produce a difference then we can just blit it directly + // to enhance performance. + canvas.drawBitmapRect(scaledImageFragment, 0, enclosingDestRect, &paint); + canvas.restore(); } static bool hasNon90rotation(PlatformContextSkia* context) @@ -224,7 +358,7 @@ static bool hasNon90rotation(PlatformContextSkia* context) return !context->canvas()->getTotalMatrix().rectStaysRect(); } -static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkIRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp) +static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp) { #if PLATFORM(CHROMIUM) TRACE_EVENT0("skia", "paintSkBitmap"); @@ -249,8 +383,9 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag if (!(canvas->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask))) canvas->getTotalMatrix().mapRect(&destRectTarget, destRect); - resampling = computeResamplingMode(canvas->getTotalMatrix(), bitmap, srcRect.width(), srcRect.height(), - SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height())); + resampling = computeResamplingMode(canvas->getTotalMatrix(), bitmap, + SkScalarToFloat(srcRect.width()), SkScalarToFloat(srcRect.height()), + SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height())); } if (resampling == RESAMPLE_NONE) { @@ -269,7 +404,27 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag // is something interesting going on with the matrix (like a rotation). // Note: for serialization, we will want to subset the bitmap first so // we don't send extra pixels. - canvas->drawBitmapRect(bitmap.bitmap(), &srcRect, destRect, &paint); + SkIRect enclosingSrcRect; + SkRect enclosingDestRect; + SkISize bitmapSize = SkISize::Make(bitmap.bitmap().width(), bitmap.bitmap().height()); + bool needsClipping = computeBitmapDrawRects(bitmapSize, srcRect, destRect, &enclosingSrcRect, &enclosingDestRect); + + if (enclosingSrcRect.isEmpty() || enclosingDestRect.isEmpty()) + return; + + // If destination is enlarged because source rectangle didn't align to + // integer boundaries then we draw a slightly larger rectangle and clip + // to the original destination rectangle. + // See http://crbug.com/145540. + if (needsClipping) { + platformContext->save(); + platformContext->canvas()->clipRect(destRect); + } + + canvas->drawBitmapRect(bitmap.bitmap(), &enclosingSrcRect, enclosingDestRect, &paint); + + if (needsClipping) + platformContext->restore(); } platformContext->didDrawRect(destRect, paint, &bitmap.bitmap()); } @@ -323,7 +478,6 @@ void Image::drawPattern(GraphicsContext* context, if (!bitmap) return; - SkIRect srcRect = enclosingIntRect(normSrcRect); SkMatrix ctm = context->platformContext()->canvas()->getTotalMatrix(); SkMatrix totalMatrix; totalMatrix.setConcat(ctm, patternTransform); @@ -342,7 +496,7 @@ void Image::drawPattern(GraphicsContext* context, if (context->platformContext()->isAccelerated() || context->platformContext()->printing()) resampling = RESAMPLE_LINEAR; else - resampling = computeResamplingMode(totalMatrix, *bitmap, srcRect.width(), srcRect.height(), destBitmapWidth, destBitmapHeight); + resampling = computeResamplingMode(totalMatrix, *bitmap, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight); resampling = limitResamplingMode(context->platformContext(), resampling); // Load the transform WebKit requested. @@ -351,12 +505,19 @@ void Image::drawPattern(GraphicsContext* context, SkShader* shader; if (resampling == RESAMPLE_AWESOME) { // Do nice resampling. - int width = static_cast<int>(destBitmapWidth); - int height = static_cast<int>(destBitmapHeight); - SkBitmap resampled = bitmap->resizedBitmap(srcRect, width, height); + float scaleX = destBitmapWidth / normSrcRect.width(); + float scaleY = destBitmapHeight / normSrcRect.height(); + SkRect scaledSrcRect; + SkIRect enclosingScaledSrcRect; + + // The image fragment generated here is not exactly what is + // requested. The scale factor used is approximated and image + // fragment is slightly larger to align to integer + // boundaries. + SkBitmap resampled = extractScaledImageFragment(*bitmap, normSrcRect, scaleX, scaleY, &scaledSrcRect, &enclosingScaledSrcRect); shader = SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); - // Since we just resized the bitmap, we need to remove the scale + // Since we just resized the bitmap, we need to remove the scale // applied to the pixels in the bitmap shader. This means we need // CTM * patternTransform to have identity scale. Since we // can't modify CTM (or the rectangle will be drawn in the wrong @@ -367,7 +528,7 @@ void Image::drawPattern(GraphicsContext* context, } else { // No need to do nice resampling. SkBitmap srcSubset; - bitmap->bitmap().extractSubset(&srcSubset, srcRect); + bitmap->bitmap().extractSubset(&srcSubset, enclosingIntRect(normSrcRect)); shader = SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); } @@ -443,10 +604,10 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, return; // Nothing to draw. paintSkBitmap(ctxt->platformContext(), - *bm, - enclosingIntRect(normSrcRect), - normDstRect, - WebCoreCompositeToSkiaComposite(compositeOp)); + *bm, + normSrcRect, + normDstRect, + WebCoreCompositeToSkiaComposite(compositeOp)); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); @@ -467,10 +628,10 @@ void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt, return; // Nothing to draw. paintSkBitmap(ctxt->platformContext(), - m_nativeImage, - enclosingIntRect(normSrcRect), - normDstRect, - WebCoreCompositeToSkiaComposite(compositeOp)); + m_nativeImage, + normSrcRect, + normDstRect, + WebCoreCompositeToSkiaComposite(compositeOp)); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); diff --git a/Source/WebCore/platform/graphics/skia/MemoryInstrumentationSkia.cpp b/Source/WebCore/platform/graphics/skia/MemoryInstrumentationSkia.cpp new file mode 100644 index 000000000..0793c3569 --- /dev/null +++ b/Source/WebCore/platform/graphics/skia/MemoryInstrumentationSkia.cpp @@ -0,0 +1,59 @@ +/* + * 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 "MemoryInstrumentationSkia.h" + +#include "PlatformMemoryInstrumentation.h" +#include "SkBitmap.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkPixelRef.h" + +void reportMemoryUsage(const SkBitmap* const& image, WTF::MemoryObjectInfo* memoryObjectInfo) +{ + WTF::MemoryClassInfo info(memoryObjectInfo, image); + SkPixelRef* pixelRef = image->pixelRef(); + info.addMember(pixelRef); + if (pixelRef) + info.addRawBuffer(pixelRef->pixels(), image->getSize()); +} + +void reportMemoryUsage(const SkDevice* const& device, WTF::MemoryObjectInfo* memoryObjectInfo) +{ + WTF::MemoryClassInfo info(memoryObjectInfo, device); + info.addMember(const_cast<SkDevice*>(device)->accessBitmap(false)); +} + +void reportMemoryUsage(const SkCanvas* const& canvas, WTF::MemoryObjectInfo* memoryObjectInfo) +{ + WTF::MemoryClassInfo info(memoryObjectInfo, canvas); + info.addMember(canvas->getDevice()); +} diff --git a/Source/WebCore/platform/graphics/skia/MemoryInstrumentationSkia.h b/Source/WebCore/platform/graphics/skia/MemoryInstrumentationSkia.h new file mode 100644 index 000000000..e6f81b0d2 --- /dev/null +++ b/Source/WebCore/platform/graphics/skia/MemoryInstrumentationSkia.h @@ -0,0 +1,44 @@ +/* + * 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 MemoryInstrumentationSkia_h +#define MemoryInstrumentationSkia_h + +#include "PlatformMemoryInstrumentation.h" + +class SkBitmap; +class SkDevice; +class SkCanvas; + +void reportMemoryUsage(const SkBitmap* const&, WTF::MemoryObjectInfo*); +void reportMemoryUsage(const SkDevice* const&, WTF::MemoryObjectInfo*); +void reportMemoryUsage(const SkCanvas* const&, WTF::MemoryObjectInfo*); + +#endif // !defined(MemoryInstrumentationSkia_h) diff --git a/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp b/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp index 2c4baed75..1862a2afc 100644 --- a/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp @@ -34,7 +34,10 @@ #include "NativeImageSkia.h" #include "GraphicsContext3D.h" +#include "MemoryInstrumentationSkia.h" #include "PlatformInstrumentation.h" +#include "PlatformMemoryInstrumentation.h" +#include "SkPixelRef.h" #include "SkiaUtils.h" namespace WebCore { @@ -61,56 +64,48 @@ int NativeImageSkia::decodedSize() const return m_image.getSize() + m_resizedImage.getSize(); } -bool NativeImageSkia::hasResizedBitmap(const SkIRect& srcSubset, int destWidth, int destHeight) const +bool NativeImageSkia::hasResizedBitmap(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const { - return m_cachedImageInfo.isEqual(srcSubset, destWidth, destHeight) && !m_resizedImage.empty(); + bool imageScaleEqual = m_cachedImageInfo.scaledImageSize == scaledImageSize; + bool scaledImageSubsetAvailable = m_cachedImageInfo.scaledImageSubset.contains(scaledImageSubset); + return imageScaleEqual && scaledImageSubsetAvailable && !m_resizedImage.empty(); } -SkBitmap NativeImageSkia::resizedBitmap(const SkIRect& srcSubset, - int destWidth, - int destHeight, - const SkIRect& destVisibleSubset) const +SkBitmap NativeImageSkia::resizedBitmap(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const { - if (!hasResizedBitmap(srcSubset, destWidth, destHeight)) { + if (!hasResizedBitmap(scaledImageSize, scaledImageSubset)) { bool shouldCache = isDataComplete() - && shouldCacheResampling(srcSubset, destWidth, destHeight, destVisibleSubset); - - SkBitmap subset; - m_image.extractSubset(&subset, srcSubset); - if (!shouldCache) { - // Just resize the visible subset and return it. - PlatformInstrumentation::willResizeImage(shouldCache); - SkBitmap resizedImage = skia::ImageOperations::Resize(subset, skia::ImageOperations::RESIZE_LANCZOS3, destWidth, destHeight, destVisibleSubset); - PlatformInstrumentation::didResizeImage(); - resizedImage.setImmutable(); + && shouldCacheResampling(scaledImageSize, scaledImageSubset); + + PlatformInstrumentation::willResizeImage(shouldCache); + SkBitmap resizedImage = skia::ImageOperations::Resize(m_image, skia::ImageOperations::RESIZE_LANCZOS3, scaledImageSize.width(), scaledImageSize.height(), scaledImageSubset); + resizedImage.setImmutable(); + PlatformInstrumentation::didResizeImage(); + + if (!shouldCache) return resizedImage; - } else { - PlatformInstrumentation::willResizeImage(shouldCache); - m_resizedImage = skia::ImageOperations::Resize(subset, skia::ImageOperations::RESIZE_LANCZOS3, destWidth, destHeight); - PlatformInstrumentation::didResizeImage(); - } - m_resizedImage.setImmutable(); + + m_resizedImage = resizedImage; } - SkBitmap visibleBitmap; - m_resizedImage.extractSubset(&visibleBitmap, destVisibleSubset); - return visibleBitmap; + SkBitmap resizedSubset; + SkIRect resizedSubsetRect = m_cachedImageInfo.rectInSubset(scaledImageSubset); + m_resizedImage.extractSubset(&resizedSubset, resizedSubsetRect); + return resizedSubset; } -bool NativeImageSkia::shouldCacheResampling(const SkIRect& srcSubset, - int destWidth, - int destHeight, - const SkIRect& destVisibleSubset) const +bool NativeImageSkia::shouldCacheResampling(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const { // Check whether the requested dimensions match previous request. - bool matchesPreviousRequest = m_cachedImageInfo.isEqual(srcSubset, destWidth, destHeight); + bool matchesPreviousRequest = m_cachedImageInfo.isEqual(scaledImageSize, scaledImageSubset); if (matchesPreviousRequest) ++m_resizeRequests; else { - m_cachedImageInfo.set(srcSubset, destWidth, destHeight); + m_cachedImageInfo.set(scaledImageSize, scaledImageSubset); m_resizeRequests = 0; - // Reset m_resizedImage now, because we don't distinguish between the - // last requested resize info and m_resizedImage's resize info. + // Reset m_resizedImage now, because we don't distinguish + // between the last requested resize info and m_resizedImage's + // resize info. m_resizedImage.reset(); } @@ -123,13 +118,16 @@ bool NativeImageSkia::shouldCacheResampling(const SkIRect& srcSubset, // If the destination bitmap is excessively large, we'll never allow caching. static const unsigned long long kLargeBitmapSize = 4096ULL * 4096ULL; - if ((static_cast<unsigned long long>(destWidth) * static_cast<unsigned long long>(destHeight)) > kLargeBitmapSize) + unsigned long long fullSize = static_cast<unsigned long long>(scaledImageSize.width()) * static_cast<unsigned long long>(scaledImageSize.height()); + unsigned long long fragmentSize = static_cast<unsigned long long>(scaledImageSubset.width()) * static_cast<unsigned long long>(scaledImageSubset.height()); + + if (fragmentSize > kLargeBitmapSize) return false; // If the destination bitmap is small, we'll always allow caching, since // there is not very much penalty for computing it and it may come in handy. - static const int kSmallBitmapSize = 4096; - if (destWidth * destHeight <= kSmallBitmapSize) + static const unsigned kSmallBitmapSize = 4096; + if (fragmentSize <= kSmallBitmapSize) return true; // If "too many" requests have been made for this bitmap, we assume that @@ -138,28 +136,46 @@ bool NativeImageSkia::shouldCacheResampling(const SkIRect& srcSubset, if (m_resizeRequests >= kManyRequestThreshold) return true; - // If more than 1/4 of the resized image is visible, it's worth caching. - int destVisibleSize = destVisibleSubset.width() * destVisibleSubset.height(); - return (destVisibleSize > (destWidth * destHeight) / 4); + // If more than 1/4 of the resized image is requested, it's worth caching. + return fragmentSize > fullSize / 4; } NativeImageSkia::CachedImageInfo::CachedImageInfo() { - srcSubset.setEmpty(); + scaledImageSize.setEmpty(); + scaledImageSubset.setEmpty(); +} + +bool NativeImageSkia::CachedImageInfo::isEqual(const SkISize& otherScaledImageSize, const SkIRect& otherScaledImageSubset) const +{ + return scaledImageSize == otherScaledImageSize && scaledImageSubset == otherScaledImageSubset; +} + +void NativeImageSkia::CachedImageInfo::set(const SkISize& otherScaledImageSize, const SkIRect& otherScaledImageSubset) +{ + scaledImageSize = otherScaledImageSize; + scaledImageSubset = otherScaledImageSubset; +} + +SkIRect NativeImageSkia::CachedImageInfo::rectInSubset(const SkIRect& otherScaledImageSubset) +{ + if (!scaledImageSubset.contains(otherScaledImageSubset)) + return SkIRect::MakeEmpty(); + SkIRect subsetRect = otherScaledImageSubset; + subsetRect.offset(-scaledImageSubset.x(), -scaledImageSubset.y()); + return subsetRect; } -bool NativeImageSkia::CachedImageInfo::isEqual(const SkIRect& otherSrcSubset, int width, int height) const +void NativeImageSkia::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { - return srcSubset == otherSrcSubset - && requestSize.width() == width - && requestSize.height() == height; + MemoryClassInfo info(memoryObjectInfo, this); + info.addMember(m_image); + info.addMember(m_resizedImage); } -void NativeImageSkia::CachedImageInfo::set(const SkIRect& otherSrcSubset, int width, int height) +void reportMemoryUsage(const NativeImageSkia* const& image, MemoryObjectInfo* memoryObjectInfo) { - srcSubset = otherSrcSubset; - requestSize.setWidth(width); - requestSize.setHeight(height); + image->reportMemoryUsage(memoryObjectInfo); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/skia/NativeImageSkia.h b/Source/WebCore/platform/graphics/skia/NativeImageSkia.h index 2a52e68ee..8b795e2a5 100644 --- a/Source/WebCore/platform/graphics/skia/NativeImageSkia.h +++ b/Source/WebCore/platform/graphics/skia/NativeImageSkia.h @@ -33,7 +33,8 @@ #include "SkBitmap.h" #include "SkRect.h" -#include "IntSize.h" +#include "SkSize.h" +#include <wtf/Forward.h> namespace WebCore { @@ -70,39 +71,35 @@ public: float resolutionScale() const { return m_resolutionScale; } // We can keep a resized version of the bitmap cached on this object. - // This function will return true if there is a cached version of the - // given image subset with the given dimensions and subsets. - bool hasResizedBitmap(const SkIRect& srcSubset, int width, int height) const; + // This function will return true if there is a cached version of the given + // scale and subset. + bool hasResizedBitmap(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const; // This will return an existing resized image subset, or generate a new one - // of the specified size and subsets and possibly cache it. - // srcSubset is the subset of the image to resize in image space. - SkBitmap resizedBitmap(const SkIRect& srcSubset, int destWidth, int destHeight) const - { - SkIRect destVisibleSubset = {0, 0, destWidth, destHeight}; - return resizedBitmap(srcSubset, destWidth, destHeight, destVisibleSubset); - } - - // Same as above, but returns a subset of the destination image (ie: the - // visible subset). destVisibleSubset is the subset of the resized - // (destWidth x destHeight) image. - // In other words: - // - crop image by srcSubset -> imageSubset. - // - resize imageSubset to destWidth x destHeight -> destImage. - // - return destImage cropped by destVisibleSubset. - SkBitmap resizedBitmap(const SkIRect& srcSubset, int destWidth, int destHeight, const SkIRect& destVisibleSubset) const; + // of the specified size and subset and possibly cache it. + // + // scaledImageSize + // Dimensions of the scaled full image. + // + // scaledImageSubset + // Rectangle of the subset in the scaled image. + SkBitmap resizedBitmap(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const; + + void reportMemoryUsage(MemoryObjectInfo*) const; private: // CachedImageInfo is used to uniquely identify cached or requested image // resizes. + // Image resize is identified by the scaled image size and scaled image subset. struct CachedImageInfo { - IntSize requestSize; - SkIRect srcSubset; + SkISize scaledImageSize; + SkIRect scaledImageSubset; CachedImageInfo(); - bool isEqual(const SkIRect& otherSrcSubset, int width, int height) const; - void set(const SkIRect& otherSrcSubset, int width, int height); + bool isEqual(const SkISize& otherScaledImageSize, const SkIRect& otherScaledImageSubset) const; + void set(const SkISize& otherScaledImageSize, const SkIRect& otherScaledImageSubset); + SkIRect rectInSubset(const SkIRect& otherScaledImageRect); }; // Returns true if the given resize operation should either resize the whole @@ -118,16 +115,14 @@ private: // better if we're going to be using it more than once (like a bitmap // scrolling on and off the screen. Since we only cache when doing the // entire thing, it's best to just do it up front. - bool shouldCacheResampling(const SkIRect& srcSubset, - int destWidth, - int destHeight, - const SkIRect& destSubset) const; + bool shouldCacheResampling(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const; // The original image. SkBitmap m_image; float m_resolutionScale; - // The cached bitmap. This will be empty() if there is no cached image. + // The cached bitmap fragment. This is a subset of the scaled version of + // |m_image|. empty() returns true if there is no cached image. mutable SkBitmap m_resizedImage; // References how many times that the image size has been requested for @@ -141,12 +136,11 @@ private: // resized image, we know that we should probably cache it, even if all of // those requests individually are small and would not otherwise be cached. // - // We also track the source and destination subsets for caching partial - // image resizes. + // We also track scaling information and destination subset for the scaled + // image. See comments for CachedImageInfo. mutable CachedImageInfo m_cachedImageInfo; mutable int m_resizeRequests; }; } #endif // NativeImageSkia_h - diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index a508a6e29..5d6bf936c 100644 --- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -188,6 +188,7 @@ PlatformContextSkia::PlatformContextSkia(SkCanvas* canvas) , m_accelerated(false) , m_deferred(false) , m_drawingToImageBuffer(false) + , m_deviceScaleFactor(1) #if defined(SK_SUPPORT_HINTING_SCALE_FACTOR) , m_hintingScaleFactor(SK_Scalar1) #endif diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h index 8bc5f32e7..2369f3209 100644 --- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h +++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h @@ -187,6 +187,9 @@ public: bool isDeferred() const { return m_deferred; } void setDeferred(bool deferred) { m_deferred = deferred; } + float deviceScaleFactor() const { return m_deviceScaleFactor; } + void setDeviceScaleFactor(float scale) { m_deviceScaleFactor = scale; } + void setTrackOpaqueRegion(bool track) { m_trackOpaqueRegion = track; } // This will be an empty region unless tracking is enabled. @@ -239,6 +242,7 @@ private: bool m_accelerated; bool m_deferred; bool m_drawingToImageBuffer; + float m_deviceScaleFactor; #if defined(SK_SUPPORT_HINTING_SCALE_FACTOR) SkScalar m_hintingScaleFactor; #endif diff --git a/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp b/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp index 54486c3aa..4d32c74db 100644 --- a/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp @@ -42,6 +42,8 @@ #include "SkTypeface.h" #include "SkTypes.h" #include "VDMXParser.h" +#include <unicode/normlzr.h> +#include <wtf/unicode/Unicode.h> namespace WebCore { @@ -110,16 +112,18 @@ void SimpleFontData::platformInit() m_fontMetrics.setDescent(descent); float xHeight; - if (metrics.fXHeight) + if (metrics.fXHeight) { xHeight = metrics.fXHeight; - else { - // hack taken from the Windows port - xHeight = ascent * 0.56f; + m_fontMetrics.setXHeight(xHeight); + } else { + xHeight = ascent * 0.56; // Best guess from Windows font metrics. + m_fontMetrics.setXHeight(xHeight); + m_fontMetrics.setHasXHeight(false); } + float lineGap = SkScalarToFloat(metrics.fLeading); m_fontMetrics.setLineGap(lineGap); - m_fontMetrics.setXHeight(xHeight); m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap)); if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { @@ -159,6 +163,9 @@ void SimpleFontData::platformInit() } } } + + if (int unitsPerEm = paint.getTypeface()->getUnitsPerEm()) + m_fontMetrics.setUnitsPerEm(unitsPerEm); } void SimpleFontData::platformCharWidthInit() @@ -170,30 +177,30 @@ void SimpleFontData::platformDestroy() { } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor); - return adoptPtr(new SimpleFontData(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false)); + return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFraction); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, emphasisMarkFraction); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const @@ -250,4 +257,32 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const return SkScalarToFloat(width); } +#if USE(HARFBUZZ_NG) +bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters, size_t length) const +{ + if (!m_combiningCharacterSequenceSupport) + m_combiningCharacterSequenceSupport = adoptPtr(new HashMap<String, bool>); + + WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false); + if (!addResult.isNewEntry) + return addResult.iterator->value; + + UErrorCode error = U_ZERO_ERROR; + Vector<UChar, 4> normalizedCharacters(length); + int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], length, &error); + // Can't render if we have an error or no composition occurred. + if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length)) + return false; + + SkPaint paint; + m_platformData.setupPaint(&paint); + paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + if (paint.textToGlyphs(&normalizedCharacters[0], normalizedLength * 2, 0)) { + addResult.iterator->value = true; + return true; + } + return false; +} +#endif + } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp index 9ff3881d0..c16a37799 100644 --- a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp +++ b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp @@ -25,7 +25,7 @@ #if USE(GRAPHICS_SURFACE) namespace WebCore { -PassRefPtr<GraphicsSurface> GraphicsSurface::create(const IntSize& size, Flags flags, uint64_t token) +PassRefPtr<GraphicsSurface> GraphicsSurface::create(const IntSize& size, Flags flags, const GraphicsSurfaceToken& token) { return platformImport(size, flags, token); } @@ -35,7 +35,7 @@ PassRefPtr<GraphicsSurface> GraphicsSurface::create(const IntSize& size, Graphic return platformCreate(size, flags); } -uint64_t GraphicsSurface::exportToken() +GraphicsSurfaceToken GraphicsSurface::exportToken() { return platformExport(); } diff --git a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h index 0ee68cf3d..e78ebbc0e 100644 --- a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h +++ b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h @@ -21,6 +21,7 @@ #define GraphicsSurface_h #include "GraphicsContext.h" +#include "GraphicsSurfaceToken.h" #include "IntRect.h" #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> @@ -32,7 +33,8 @@ #if OS(DARWIN) typedef struct __IOSurface* IOSurfaceRef; typedef IOSurfaceRef PlatformGraphicsSurface; -#else +#endif +#if OS(LINUX) typedef uint32_t PlatformGraphicsSurface; #endif @@ -69,13 +71,13 @@ public: IntSize size() const { return m_size; } static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags); - static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags, uint64_t token); + static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags, const GraphicsSurfaceToken&); void copyToGLTexture(uint32_t target, uint32_t texture, const IntRect& targetRect, const IntPoint& sourceOffset); void copyFromFramebuffer(uint32_t fbo, const IntRect& sourceRect); void paintToTextureMapper(TextureMapper*, const FloatRect& targetRect, const TransformationMatrix&, float opacity, BitmapTexture* mask); uint32_t frontBuffer(); uint32_t swapBuffers(); - uint64_t exportToken(); + GraphicsSurfaceToken exportToken(); uint32_t getTextureID(); PassOwnPtr<GraphicsContext> beginPaint(const IntRect&, LockOptions); PassRefPtr<Image> createReadOnlyImage(const IntRect&); @@ -83,8 +85,8 @@ public: protected: static PassRefPtr<GraphicsSurface> platformCreate(const IntSize&, Flags); - static PassRefPtr<GraphicsSurface> platformImport(const IntSize&, Flags, uint64_t); - uint64_t platformExport(); + static PassRefPtr<GraphicsSurface> platformImport(const IntSize&, Flags, const GraphicsSurfaceToken&); + GraphicsSurfaceToken platformExport(); void platformDestroy(); uint32_t platformGetTextureID(); diff --git a/Source/WebCore/platform/graphics/surfaces/GraphicsSurfaceToken.h b/Source/WebCore/platform/graphics/surfaces/GraphicsSurfaceToken.h new file mode 100644 index 000000000..45342f141 --- /dev/null +++ b/Source/WebCore/platform/graphics/surfaces/GraphicsSurfaceToken.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2012 Digia 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 GraphicsSurfaceToken_h +#define GraphicsSurfaceToken_h + +#include "GraphicsContext.h" +#include "IntRect.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +#if USE(GRAPHICS_SURFACE) + +namespace WebCore { + +struct GraphicsSurfaceToken { + +typedef uint32_t BufferHandle; + +#if HAVE(GLX) + GraphicsSurfaceToken(uint32_t windowID = 0) + : frontBufferHandle(windowID) + { } + + bool operator!=(const GraphicsSurfaceToken &rhs) const + { + return frontBufferHandle != rhs.frontBufferHandle; + } + + bool isValid() const + { + return frontBufferHandle; + } + +#endif + +#if OS(DARWIN) + GraphicsSurfaceToken(BufferHandle frontBuffer = 0, BufferHandle backBuffer = 0) + : frontBufferHandle(frontBuffer) + , backBufferHandle(backBuffer) + { } + + bool operator!=(const GraphicsSurfaceToken &rhs) const + { + return (frontBufferHandle != rhs.frontBufferHandle || backBufferHandle != rhs.backBufferHandle); + } + + bool isValid() const + { + return frontBufferHandle && backBufferHandle; + } + + BufferHandle backBufferHandle; +#endif + + BufferHandle frontBufferHandle; +}; + +} +#endif // USE(GRAPHICS_SURFACE) + +#endif // GraphicsSurfaceToken_h diff --git a/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp b/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp index 8a8322df8..94c339176 100644 --- a/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp +++ b/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp @@ -64,18 +64,13 @@ static uint32_t createTexture(IOSurfaceRef handle) struct GraphicsSurfacePrivate { public: - GraphicsSurfacePrivate(uint64_t token) + GraphicsSurfacePrivate(const GraphicsSurfaceToken& token) : m_token(token) , m_frontBufferTexture(0) , m_backBufferTexture(0) { - // The token contains the IOSurfaceID of the fist surface/buffer in the first 32 Bit - // and the IOSurfaceID of the second surface/buffer in the second 32 Bit. - uint32_t frontBuffer = token >> 32; - uint32_t backBuffer = token & 0xffff; - - m_frontBuffer = IOSurfaceLookup(frontBuffer); - m_backBuffer = IOSurfaceLookup(backBuffer); + m_frontBuffer = IOSurfaceLookup(m_token.frontBufferHandle); + m_backBuffer = IOSurfaceLookup(m_token.backBufferHandle); } GraphicsSurfacePrivate(const IntSize& size, GraphicsSurface::Flags flags) @@ -119,11 +114,7 @@ public: m_frontBuffer = IOSurfaceCreate(dict); m_backBuffer = IOSurfaceCreate(dict); - uint64_t token = IOSurfaceGetID(m_frontBuffer); - token <<= 32; - token |= IOSurfaceGetID(m_backBuffer); - - m_token = token; + m_token = GraphicsSurfaceToken(IOSurfaceGetID(m_frontBuffer), IOSurfaceGetID(m_backBuffer)); } ~GraphicsSurfacePrivate() @@ -149,7 +140,7 @@ public: return IOSurfaceGetID(m_frontBuffer); } - uint64_t token() const + GraphicsSurfaceToken token() const { return m_token; } @@ -185,10 +176,10 @@ private: PlatformGraphicsSurface m_backBuffer; uint32_t m_frontBufferTexture; uint32_t m_backBufferTexture; - uint64_t m_token; + GraphicsSurfaceToken m_token; }; -uint64_t GraphicsSurface::platformExport() +GraphicsSurfaceToken GraphicsSurface::platformExport() { return m_private->token(); } @@ -276,7 +267,7 @@ PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, return surface; } -PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, uint64_t token) +PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, const GraphicsSurfaceToken& token) { // We currently disable support for CopyToTexture on Mac, because this is used for single buffered Tiles. // The single buffered nature of this requires a call to glFlush, as described in platformCopyToTexture. diff --git a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp index 1bbeb73b9..2fd6cba46 100644 --- a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp +++ b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp @@ -107,8 +107,18 @@ struct GraphicsSurfacePrivate { , m_textureIsYInverted(false) , m_hasAlpha(false) { + QSurface* currentSurface = 0; + QOpenGLContext* currentContext = QOpenGLContext::currentContext(); + if (currentContext) + currentSurface = currentContext->surface(); + m_display = XOpenDisplay(0); m_glContext->create(); + + // The GLX implementation of QOpenGLContext will reset the current context when create is being called. + // Therefore we have to make the previous context current again. + if (currentContext) + currentContext->makeCurrent(currentSurface); } ~GraphicsSurfacePrivate() @@ -237,9 +247,9 @@ static bool resolveGLMethods(GraphicsSurfacePrivate* p) return resolved; } -uint64_t GraphicsSurface::platformExport() +GraphicsSurfaceToken GraphicsSurface::platformExport() { - return m_platformSurface; + return GraphicsSurfaceToken(m_platformSurface); } uint32_t GraphicsSurface::platformGetTextureID() @@ -316,7 +326,7 @@ PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, return surface; } -PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, uint64_t token) +PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, const GraphicsSurfaceToken& token) { // X11 does not support CopyToTexture, so we do not create a GraphicsSurface if this is requested. // GraphicsSurfaceGLX uses an XWindow as native surface. This one always has a front and a back buffer. @@ -330,7 +340,7 @@ PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, if (!resolveGLMethods(surface->m_private)) return PassRefPtr<GraphicsSurface>(); - surface->m_platformSurface = token; + surface->m_platformSurface = token.frontBufferHandle; surface->m_private->createPixmap(surface->m_platformSurface); surface->m_size = surface->m_private->size(); diff --git a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp index e1b275893..734a093ae 100644 --- a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp +++ b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp @@ -52,7 +52,8 @@ PassRefPtr<Image> GraphicsSurface::createReadOnlyImage(const IntRect& rect) int stride; QImage::Format format = (flags() & SupportsAlpha) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; char* data = platformLock(rect, &stride, RetainPixels | ReadOnly); - return BitmapImage::create(new QImage(reinterpret_cast<uchar*>(data), rect.width(), rect.height(), stride, format, didReleaseImage, this)); + QImage image(reinterpret_cast<uchar*>(data), rect.width(), rect.height(), stride, format, didReleaseImage, this); + return BitmapImage::create(new QPixmap(QPixmap::fromImage(image))); } } diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp index f3b0eb411..42954a499 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp @@ -20,10 +20,19 @@ #include "config.h" #include "GraphicsLayerTextureMapper.h" +#include "GraphicsLayerFactory.h" #include "TextureMapperLayer.h" namespace WebCore { +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) +{ + if (!factory) + return adoptPtr(new GraphicsLayerTextureMapper(client)); + + return factory->createGraphicsLayer(client); +} + PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { if (s_graphicsLayerFactory) @@ -47,7 +56,7 @@ void GraphicsLayerTextureMapper::notifyChange(TextureMapperLayer::ChangeMask cha m_changeMask |= changeMask; if (!client()) return; - client()->notifySyncRequired(this); + client()->notifyFlushRequired(this); } void GraphicsLayerTextureMapper::didSynchronize() @@ -358,16 +367,16 @@ void GraphicsLayerTextureMapper::setContentsToMedia(TextureMapperPlatformLayer* /* \reimp (GraphicsLayer.h) */ -void GraphicsLayerTextureMapper::syncCompositingStateForThisLayerOnly() +void GraphicsLayerTextureMapper::flushCompositingStateForThisLayerOnly() { - m_layer->syncCompositingState(this); + m_layer->flushCompositingState(this); } /* \reimp (GraphicsLayer.h) */ -void GraphicsLayerTextureMapper::syncCompositingState(const FloatRect&) +void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect&) { - m_layer->syncCompositingState(this, TextureMapperLayer::TraverseDescendants); + m_layer->flushCompositingState(this, TextureMapperLayer::TraverseDescendants); } bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset) diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h index 50070cc0f..637abd9d4 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h @@ -69,8 +69,8 @@ public: virtual void setContentsToImage(Image*); virtual void setContentsToMedia(PlatformLayer*); virtual void setContentsToCanvas(PlatformLayer* canvas) { setContentsToMedia(canvas); } - virtual void syncCompositingState(const FloatRect&); - virtual void syncCompositingStateForThisLayerOnly(); + virtual void flushCompositingState(const FloatRect&); + virtual void flushCompositingStateForThisLayerOnly(); virtual void setName(const String& name); virtual PlatformLayer* platformLayer() const { return 0; } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h index b4504682b..a90dbe4f1 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h @@ -28,6 +28,9 @@ #define TEXMAP_OPENGL_ES_2 #endif #endif +#if PLATFORM(GTK) && USE(OPENGL_ES_2) +#define TEXMAP_OPENGL_ES_2 +#endif #include "FilterOperations.h" #include "GraphicsContext.h" @@ -84,7 +87,7 @@ public: inline bool isOpaque() const { return !(m_flags & SupportsAlpha); } #if ENABLE(CSS_FILTERS) - virtual PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture& contentTexture, const FilterOperations&) { return this; } + virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations&) { return this; } #endif protected: diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp index b25372ce6..995cc79da 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp @@ -34,7 +34,7 @@ namespace WebCore { #if USE(GRAPHICS_SURFACE) -void TextureMapperSurfaceBackingStore::setGraphicsSurface(uint64_t graphicsSurfaceToken, const IntSize& surfaceSize, uint32_t frontBuffer) +void TextureMapperSurfaceBackingStore::setGraphicsSurface(const GraphicsSurfaceToken& graphicsSurfaceToken, const IntSize& surfaceSize, uint32_t frontBuffer) { if (graphicsSurfaceToken != m_graphicsSurfaceToken) { GraphicsSurface::Flags surfaceFlags = GraphicsSurface::SupportsTextureTarget @@ -68,7 +68,7 @@ void TextureMapperSurfaceBackingStore::setSurface(PassRefPtr<GraphicsSurface> su m_graphicsSurfaceToken = m_graphicsSurface->exportToken(); } else { m_graphicsSurface = RefPtr<GraphicsSurface>(); - m_graphicsSurfaceToken = 0; + m_graphicsSurfaceToken = GraphicsSurfaceToken(); } } #endif diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h index 9d002b48e..93de3da06 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h @@ -50,7 +50,7 @@ protected: class TextureMapperSurfaceBackingStore : public TextureMapperBackingStore { public: static PassRefPtr<TextureMapperSurfaceBackingStore> create() { return adoptRef(new TextureMapperSurfaceBackingStore); } - void setGraphicsSurface(uint64_t graphicsSurfaceToken, const IntSize& surfaceSize, uint32_t frontBuffer); + void setGraphicsSurface(const GraphicsSurfaceToken&, const IntSize& surfaceSize, uint32_t frontBuffer); PassRefPtr<WebCore::GraphicsSurface> graphicsSurface() const { return m_graphicsSurface; } virtual PassRefPtr<BitmapTexture> texture() const; virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float, BitmapTexture*); @@ -62,10 +62,9 @@ protected: private: TextureMapperSurfaceBackingStore() : TextureMapperBackingStore() - , m_graphicsSurfaceToken(0) { } - uint64_t m_graphicsSurfaceToken; + GraphicsSurfaceToken m_graphicsSurfaceToken; RefPtr<WebCore::GraphicsSurface> m_graphicsSurface; IntSize m_graphicsSurfaceSize; }; diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp index 7f10e31bb..94e449345 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp @@ -23,6 +23,7 @@ #include "GraphicsContext.h" #include "Image.h" +#include "LengthFunctions.h" #include "NotImplemented.h" #include "TextureMapperShaderManager.h" #include "Timer.h" @@ -72,7 +73,7 @@ public: { GLContextDataMap::iterator it = glContextDataMap().find(context->platformGraphicsContext3D()); if (it != glContextDataMap().end()) - return it->second; + return it->value; return adoptRef(new SharedGLData(context)); } @@ -92,7 +93,7 @@ public: GLContextDataMap::const_iterator end = glContextDataMap().end(); GLContextDataMap::iterator it; for (it = glContextDataMap().begin(); it != end; ++it) { - if (it->second == this) + if (it->value == this) break; } @@ -266,7 +267,7 @@ void TextureMapperGL::endPainting() void TextureMapperGL::drawQuad(const DrawQuad& quadToDraw, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram* shaderProgram, GC3Denum drawingMode, bool needsBlending) { - m_context3D->enableVertexAttribArray(shaderProgram->vertexAttrib()); + m_context3D->enableVertexAttribArray(shaderProgram->vertexLocation()); m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0); const GC3Dfloat quad[] = { @@ -275,7 +276,7 @@ void TextureMapperGL::drawQuad(const DrawQuad& quadToDraw, const TransformationM quadToDraw.targetRectMappedToUnitSquare.p3().x(), quadToDraw.targetRectMappedToUnitSquare.p3().y(), quadToDraw.targetRectMappedToUnitSquare.p4().x(), quadToDraw.targetRectMappedToUnitSquare.p4().y() }; - m_context3D->vertexAttribPointer(shaderProgram->vertexAttrib(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(quad)); + m_context3D->vertexAttribPointer(shaderProgram->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(quad)); TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multiply(modelViewMatrix).multiply(TransformationMatrix( quadToDraw.originalTargetRect.width(), 0, 0, 0, @@ -297,7 +298,7 @@ void TextureMapperGL::drawQuad(const DrawQuad& quadToDraw, const TransformationM m_context3D->disable(GraphicsContext3D::BLEND); m_context3D->drawArrays(drawingMode, 0, 4); - m_context3D->disableVertexAttribArray(shaderProgram->vertexAttrib()); + m_context3D->disableVertexAttribArray(shaderProgram->vertexLocation()); } void TextureMapperGL::drawBorder(const Color& color, float width, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix) @@ -305,15 +306,12 @@ void TextureMapperGL::drawBorder(const Color& color, float width, const FloatRec if (clipStack().current().scissorBox.isEmpty()) return; - RefPtr<TextureMapperShaderProgramSolidColor> program = data().sharedGLData().textureMapperShaderManager.solidColorProgram(); - m_context3D->useProgram(program->id()); + RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::SolidColor); + m_context3D->useProgram(program->programID()); - float alpha = color.alpha() / 255.0; - m_context3D->uniform4f(program->colorLocation(), - (color.red() / 255.0) * alpha, - (color.green() / 255.0) * alpha, - (color.blue() / 255.0) * alpha, - alpha); + float r, g, b, a; + color.getRGBA(r, g, b, a); + m_context3D->uniform4f(program->colorLocation(), r, g, b, a); m_context3D->lineWidth(width); drawQuad(targetRect, modelViewMatrix, program.get(), GraphicsContext3D::LINE_LOOP, color.hasAlpha()); @@ -368,27 +366,25 @@ void TextureMapperGL::drawTextureRectangleARB(uint32_t texture, Flags flags, con { RefPtr<TextureMapperShaderProgram> program; if (maskTexture) - program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::RectOpacityAndMask); + program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::MaskedRect); else - program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::RectSimple); - m_context3D->useProgram(program->id()); + program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Rect); + m_context3D->useProgram(program->programID()); - m_context3D->enableVertexAttribArray(program->vertexAttrib()); + m_context3D->enableVertexAttribArray(program->vertexLocation()); m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); m_context3D->bindTexture(GL_TEXTURE_RECTANGLE_ARB, texture); - m_context3D->uniform1i(program->sourceTextureLocation(), 0); + m_context3D->uniform1i(program->samplerLocation(), 0); m_context3D->uniform1f(program->flipLocation(), !!(flags & ShouldFlipTexture)); m_context3D->uniform2f(program->textureSizeLocation(), textureSize.width(), textureSize.height()); + m_context3D->uniform1f(program->opacityLocation(), opacity); - if (TextureMapperShaderProgram::isValidUniformLocation(program->opacityLocation())) - m_context3D->uniform1f(program->opacityLocation(), opacity); - - if (maskTexture && maskTexture->isValid() && TextureMapperShaderProgram::isValidUniformLocation(program->maskTextureLocation())) { + if (maskTexture && maskTexture->isValid()) { const BitmapTextureGL* maskTextureGL = static_cast<const BitmapTextureGL*>(maskTexture); m_context3D->activeTexture(GraphicsContext3D::TEXTURE1); m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, maskTextureGL->id()); - m_context3D->uniform1i(program->maskTextureLocation(), 1); + m_context3D->uniform1i(program->maskLocation(), 1); m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); } @@ -405,10 +401,10 @@ void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const IntSize& RefPtr<TextureMapperShaderProgram> program; if (maskTexture) - program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::OpacityAndMask); + program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Masked); else - program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Simple); - m_context3D->useProgram(program->id()); + program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Default); + m_context3D->useProgram(program->programID()); drawTexturedQuadWithProgram(program.get(), texture, flags, targetRect, modelViewMatrix, opacity, maskTexture); } @@ -536,8 +532,8 @@ bool TextureMapperGL::drawTextureWithAntialiasing(uint32_t texture, Flags flags, quadToEdgeArray(expandedQuadInScreenSpace, targetQuadEdges); quadToEdgeArray(inflateQuad(quadInScreenSpace.boundingBox(), inflationDistance), targetQuadEdges + 12); - RefPtr<TextureMapperShaderProgramAntialiasingNoMask> program = data().sharedGLData().textureMapperShaderManager.antialiasingNoMaskProgram(); - m_context3D->useProgram(program->id()); + RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Antialiased); + m_context3D->useProgram(program->programID()); m_context3D->uniform3fv(program->expandedQuadEdgesInScreenSpaceLocation(), 8, targetQuadEdges); drawTexturedQuadWithProgram(program.get(), texture, flags, DrawQuad(originalTargetRect, expandedQuadInTextureCoordinates), modelViewMatrix, opacity, 0 /* maskTexture */); @@ -546,21 +542,19 @@ bool TextureMapperGL::drawTextureWithAntialiasing(uint32_t texture, Flags flags, void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram* program, uint32_t texture, Flags flags, const DrawQuad& quadToDraw, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture) { - m_context3D->enableVertexAttribArray(program->vertexAttrib()); + m_context3D->enableVertexAttribArray(program->vertexLocation()); m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, texture); - m_context3D->uniform1i(program->sourceTextureLocation(), 0); + m_context3D->uniform1i(program->samplerLocation(), 0); m_context3D->uniform1f(program->flipLocation(), !!(flags & ShouldFlipTexture)); + m_context3D->uniform1f(program->opacityLocation(), opacity); - if (TextureMapperShaderProgram::isValidUniformLocation(program->opacityLocation())) - m_context3D->uniform1f(program->opacityLocation(), opacity); - - if (maskTexture && maskTexture->isValid() && TextureMapperShaderProgram::isValidUniformLocation(program->maskTextureLocation())) { + if (maskTexture && maskTexture->isValid()) { const BitmapTextureGL* maskTextureGL = static_cast<const BitmapTextureGL*>(maskTexture); m_context3D->activeTexture(GraphicsContext3D::TEXTURE1); m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, maskTextureGL->id()); - m_context3D->uniform1i(program->maskTextureLocation(), 1); + m_context3D->uniform1i(program->maskLocation(), 1); m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); } @@ -568,6 +562,15 @@ void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram* pr drawQuad(quadToDraw, modelViewMatrix, program, GraphicsContext3D::TRIANGLE_FAN, needsBlending); } +BitmapTextureGL::BitmapTextureGL(TextureMapperGL* textureMapper) + : m_id(0) + , m_fbo(0) + , m_rbo(0) + , m_shouldClear(true) + , m_context3D(textureMapper->graphicsContext3D()) +{ +} + bool BitmapTextureGL::canReuseWith(const IntSize& contentsSize, Flags) { return contentsSize == m_textureSize; @@ -611,10 +614,8 @@ static bool driverSupportsSubImage() void BitmapTextureGL::didReset() { - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - if (!m_id) - m_id = context3D->createTexture(); + m_id = m_context3D->createTexture(); m_shouldClear = true; if (m_textureSize == contentSize()) @@ -623,21 +624,19 @@ void BitmapTextureGL::didReset() Platform3DObject format = driverSupportsBGRASwizzling() ? GraphicsContext3D::BGRA : GraphicsContext3D::RGBA; m_textureSize = contentSize(); - context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id); - context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); - context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); - context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); - context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); - context3D->texImage2DDirect(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_textureSize.width(), m_textureSize.height(), 0, format, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, 0); + m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id); + m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + m_context3D->texImage2DDirect(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_textureSize.width(), m_textureSize.height(), 0, format, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, 0); } void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine) { - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - Platform3DObject glFormat = GraphicsContext3D::RGBA; - context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id); + m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id); const unsigned bytesPerPixel = 4; if (driverSupportsBGRASwizzling()) @@ -645,8 +644,8 @@ void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect else swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(const_cast<void*>(data)), IntRect(sourceOffset, targetRect.size()), bytesPerLine / bytesPerPixel); - if (bytesPerLine == targetRect.width() / 4 && sourceOffset == IntPoint::zero()) { - context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data); + if (bytesPerLine == targetRect.width() * bytesPerPixel && sourceOffset == IntPoint::zero()) { + m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data); return; } @@ -664,19 +663,19 @@ void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect dst += targetBytesPerLine; } - context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, temporaryData.data()); + m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, temporaryData.data()); return; } #if !defined(TEXMAP_OPENGL_ES_2) // Use the OpenGL sub-image extension, now that we know it's available. - context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerLine / bytesPerPixel); - context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, sourceOffset.y()); - context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, sourceOffset.x()); - context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data); - context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, 0); - context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, 0); - context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + m_context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerLine / bytesPerPixel); + m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, sourceOffset.y()); + m_context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, sourceOffset.x()); + m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data); + m_context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, 0); + m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, 0); + m_context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, 0); #endif } @@ -692,8 +691,9 @@ void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, co const char* imageData; #if PLATFORM(QT) - imageData = reinterpret_cast<const char*>(frameImage->constBits()); - bytesPerLine = frameImage->bytesPerLine(); + QImage qImage = frameImage->toImage(); + imageData = reinterpret_cast<const char*>(qImage.constBits()); + bytesPerLine = qImage.bytesPerLine(); #elif USE(CAIRO) cairo_surface_t* surface = frameImage->surface(); imageData = reinterpret_cast<const char*>(cairo_image_surface_get_data(surface)); @@ -704,48 +704,193 @@ void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, co } #if ENABLE(CSS_FILTERS) -void TextureMapperGL::drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture& contentTexture, const FilterOperation& filter, int pass) + +static TextureMapperShaderManager::ShaderKey keyForFilterType(FilterOperation::OperationType type, unsigned pass) +{ + switch (type) { + case FilterOperation::GRAYSCALE: + return TextureMapperShaderManager::GrayscaleFilter; + case FilterOperation::SEPIA: + return TextureMapperShaderManager::SepiaFilter; + case FilterOperation::SATURATE: + return TextureMapperShaderManager::SaturateFilter; + case FilterOperation::HUE_ROTATE: + return TextureMapperShaderManager::HueRotateFilter; + case FilterOperation::INVERT: + return TextureMapperShaderManager::InvertFilter; + case FilterOperation::BRIGHTNESS: + return TextureMapperShaderManager::BrightnessFilter; + case FilterOperation::CONTRAST: + return TextureMapperShaderManager::ContrastFilter; + case FilterOperation::OPACITY: + return TextureMapperShaderManager::OpacityFilter; + case FilterOperation::BLUR: + return TextureMapperShaderManager::BlurFilter; + case FilterOperation::DROP_SHADOW: + return pass ? TextureMapperShaderManager::ShadowFilterPass2 : TextureMapperShaderManager::ShadowFilterPass1; + default: + ASSERT_NOT_REACHED(); + return TextureMapperShaderManager::Invalid; + } +} + +static unsigned getPassesRequiredForFilter(FilterOperation::OperationType type) +{ + switch (type) { + case FilterOperation::GRAYSCALE: + case FilterOperation::SEPIA: + case FilterOperation::SATURATE: + case FilterOperation::HUE_ROTATE: + case FilterOperation::INVERT: + case FilterOperation::BRIGHTNESS: + case FilterOperation::CONTRAST: + case FilterOperation::OPACITY: + return 1; + case FilterOperation::BLUR: + case FilterOperation::DROP_SHADOW: + // We use two-passes (vertical+horizontal) for blur and drop-shadow. + return 2; + default: + return 0; + } +} + +// Create a normal distribution of 21 values between -2 and 2. +static const int GaussianKernelHalfWidth = 11; +static const float GaussianKernelStep = 0.2; + +static inline float gauss(float x) +{ + return exp(-(x * x) / 2.); +} + +static float* gaussianKernel() +{ + static bool prepared = false; + static float kernel[GaussianKernelHalfWidth] = {0, }; + + if (prepared) + return kernel; + + kernel[0] = gauss(0); + float sum = kernel[0]; + for (unsigned i = 1; i < GaussianKernelHalfWidth; ++i) { + kernel[i] = gauss(i * GaussianKernelStep); + sum += 2 * kernel[i]; + } + + // Normalize the kernel. + float scale = 1 / sum; + for (unsigned i = 0; i < GaussianKernelHalfWidth; ++i) + kernel[i] *= scale; + + prepared = true; + return kernel; +} + +static void prepareFilterProgram(TextureMapperShaderProgram* program, const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture) +{ + RefPtr<GraphicsContext3D> context = program->context(); + context->useProgram(program->programID()); + + switch (operation.getOperationType()) { + case FilterOperation::GRAYSCALE: + case FilterOperation::SEPIA: + case FilterOperation::SATURATE: + case FilterOperation::HUE_ROTATE: + context->uniform1f(program->amountLocation(), static_cast<const BasicColorMatrixFilterOperation&>(operation).amount()); + break; + case FilterOperation::INVERT: + case FilterOperation::BRIGHTNESS: + case FilterOperation::CONTRAST: + case FilterOperation::OPACITY: + context->uniform1f(program->amountLocation(), static_cast<const BasicComponentTransferFilterOperation&>(operation).amount()); + break; + case FilterOperation::BLUR: { + const BlurFilterOperation& blur = static_cast<const BlurFilterOperation&>(operation); + FloatSize radius; + + // Blur is done in two passes, first horizontally and then vertically. The same shader is used for both. + if (pass) + radius.setHeight(floatValueForLength(blur.stdDeviation(), size.height()) / size.height()); + else + radius.setWidth(floatValueForLength(blur.stdDeviation(), size.width()) / size.width()); + + context->uniform2f(program->blurRadiusLocation(), radius.width(), radius.height()); + context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel()); + break; + } + case FilterOperation::DROP_SHADOW: { + const DropShadowFilterOperation& shadow = static_cast<const DropShadowFilterOperation&>(operation); + context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel()); + switch (pass) { + case 0: + // First pass: vertical alpha blur. + context->uniform2f(program->shadowOffsetLocation(), float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height())); + context->uniform1f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.width())); + break; + case 1: + // Second pass: we need the shadow color and the content texture for compositing. + context->uniform1f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.height())); + context->activeTexture(GraphicsContext3D::TEXTURE1); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture); + context->uniform1i(program->contentTextureLocation(), 1); + float r, g, b, a; + shadow.color().getRGBA(r, g, b, a); + context->uniform4f(program->shadowColorLocation(), r, g, b, a); + break; + } + break; + } + default: + break; + } +} + +void TextureMapperGL::drawFiltered(const BitmapTexture& sampler, const BitmapTexture& contentTexture, const FilterOperation& filter, int pass) { // For standard filters, we always draw the whole texture without transformations. - RefPtr<StandardFilterProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderForFilter(filter, pass); + TextureMapperShaderManager::ShaderKey key = keyForFilterType(filter.getOperationType(), pass); + RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(key); ASSERT(program); - program->prepare(filter, pass, sourceTexture.contentSize(), static_cast<const BitmapTextureGL&>(contentTexture).id()); + prepareFilterProgram(program.get(), filter, pass, sampler.contentSize(), static_cast<const BitmapTextureGL&>(contentTexture).id()); - m_context3D->enableVertexAttribArray(program->vertexAttrib()); - m_context3D->enableVertexAttribArray(program->texCoordAttrib()); + m_context3D->enableVertexAttribArray(program->vertexLocation()); + m_context3D->enableVertexAttribArray(program->texCoordLocation()); m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); - m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, static_cast<const BitmapTextureGL&>(sourceTexture).id()); - m_context3D->uniform1i(program->textureUniform(), 0); + m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, static_cast<const BitmapTextureGL&>(sampler).id()); + m_context3D->uniform1i(program->samplerLocation(), 0); const GC3Dfloat targetVertices[] = {-1, -1, 1, -1, 1, 1, -1, 1}; const GC3Dfloat sourceVertices[] = {0, 0, 1, 0, 1, 1, 0, 1}; - m_context3D->vertexAttribPointer(program->vertexAttrib(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(targetVertices)); - m_context3D->vertexAttribPointer(program->texCoordAttrib(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(sourceVertices)); + m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(targetVertices)); + m_context3D->vertexAttribPointer(program->texCoordLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(sourceVertices)); m_context3D->disable(GraphicsContext3D::BLEND); m_context3D->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4); - m_context3D->disableVertexAttribArray(program->vertexAttrib()); - m_context3D->disableVertexAttribArray(program->texCoordAttrib()); + m_context3D->disableVertexAttribArray(program->vertexLocation()); + m_context3D->disableVertexAttribArray(program->texCoordLocation()); } -PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters) +PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(TextureMapper* textureMapper, const BitmapTexture& contentTexture, const FilterOperations& filters) { - RefPtr<BitmapTexture> previousSurface = m_textureMapper->data().currentSurface; + TextureMapperGL* textureMapperGL = static_cast<TextureMapperGL*>(textureMapper); + RefPtr<BitmapTexture> previousSurface = textureMapperGL->data().currentSurface; RefPtr<BitmapTexture> source = this; - RefPtr<BitmapTexture> target = m_textureMapper->acquireTextureFromPool(m_textureSize); - for (int i = 0; i < filters.size(); ++i) { + RefPtr<BitmapTexture> target = textureMapper->acquireTextureFromPool(m_textureSize); + for (size_t i = 0; i < filters.size(); ++i) { const FilterOperation* filter = filters.at(i); ASSERT(filter); - int numPasses = m_textureMapper->data().sharedGLData().textureMapperShaderManager.getPassesRequiredForFilter(*filter); + int numPasses = getPassesRequiredForFilter(filter->getOperationType()); for (int j = 0; j < numPasses; ++j) { - m_textureMapper->bindSurface(target.get()); - m_textureMapper->drawFiltered((i || j) ? *source : contentTexture, contentTexture, *filter, j); + textureMapperGL->bindSurface(target.get()); + textureMapperGL->drawFiltered((i || j) ? *source : contentTexture, contentTexture, *filter, j); std::swap(source, target); } } - m_textureMapper->bindSurface(previousSurface.get()); + textureMapperGL->bindSurface(previousSurface.get()); return source; } #endif @@ -766,18 +911,17 @@ void BitmapTextureGL::initializeStencil() if (m_rbo) return; - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - m_rbo = context3D->createRenderbuffer(); - context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_rbo); + m_rbo = m_context3D->createRenderbuffer(); + m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_rbo); #ifdef TEXMAP_OPENGL_ES_2 - context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, m_textureSize.width(), m_textureSize.height()); + m_context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, m_textureSize.width(), m_textureSize.height()); #else - context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_STENCIL, m_textureSize.width(), m_textureSize.height()); + m_context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_STENCIL, m_textureSize.width(), m_textureSize.height()); #endif - context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); - context3D->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_rbo); - context3D->clearStencil(0); - context3D->clear(GraphicsContext3D::STENCIL_BUFFER_BIT); + m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); + m_context3D->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_rbo); + m_context3D->clearStencil(0); + m_context3D->clear(GraphicsContext3D::STENCIL_BUFFER_BIT); } void BitmapTextureGL::clearIfNeeded() @@ -785,12 +929,10 @@ void BitmapTextureGL::clearIfNeeded() if (!m_shouldClear) return; - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - m_clipStack.init(IntRect(IntPoint::zero(), m_textureSize)); - m_clipStack.apply(context3D); - context3D->clearColor(0, 0, 0, 0); - context3D->clear(GraphicsContext3D::COLOR_BUFFER_BIT); + m_clipStack.apply(m_context3D.get()); + m_context3D->clearColor(0, 0, 0, 0); + m_context3D->clear(GraphicsContext3D::COLOR_BUFFER_BIT); m_shouldClear = false; } @@ -799,37 +941,33 @@ void BitmapTextureGL::createFboIfNeeded() if (m_fbo) return; - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - m_fbo = context3D->createFramebuffer(); - context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); - context3D->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, id(), 0); + m_fbo = m_context3D->createFramebuffer(); + m_context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); + m_context3D->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, id(), 0); m_shouldClear = true; } -void BitmapTextureGL::bind() +void BitmapTextureGL::bind(TextureMapperGL* textureMapper) { - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); + m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); createFboIfNeeded(); - context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); - context3D->viewport(0, 0, m_textureSize.width(), m_textureSize.height()); + m_context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); + m_context3D->viewport(0, 0, m_textureSize.width(), m_textureSize.height()); clearIfNeeded(); - m_textureMapper->data().projectionMatrix = createProjectionMatrix(m_textureSize, true /* mirrored */); - m_clipStack.apply(context3D); + textureMapper->data().projectionMatrix = createProjectionMatrix(m_textureSize, true /* mirrored */); + m_clipStack.apply(m_context3D.get()); } BitmapTextureGL::~BitmapTextureGL() { - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - if (m_id) - context3D->deleteTexture(m_id); + m_context3D->deleteTexture(m_id); if (m_fbo) - context3D->deleteFramebuffer(m_fbo); + m_context3D->deleteFramebuffer(m_fbo); if (m_rbo) - context3D->deleteRenderbuffer(m_rbo); + m_context3D->deleteRenderbuffer(m_rbo); } bool BitmapTextureGL::isValid() const @@ -864,7 +1002,7 @@ void TextureMapperGL::bindSurface(BitmapTexture *surface) return; } - static_cast<BitmapTextureGL*>(surface)->bind(); + static_cast<BitmapTextureGL*>(surface)->bind(this); data().currentSurface = surface; } @@ -895,12 +1033,12 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con data().initializeStencil(); - RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Simple); + RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Default); - m_context3D->useProgram(program->id()); - m_context3D->enableVertexAttribArray(program->vertexAttrib()); + m_context3D->useProgram(program->programID()); + m_context3D->enableVertexAttribArray(program->vertexLocation()); const GC3Dfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1}; - m_context3D->vertexAttribPointer(program->vertexAttrib(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(unitRect)); + m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(unitRect)); TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix) .multiply(modelViewMatrix) @@ -944,7 +1082,7 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con m_context3D->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4); // Clear the state. - m_context3D->disableVertexAttribArray(program->vertexAttrib()); + m_context3D->disableVertexAttribArray(program->vertexLocation()); m_context3D->stencilMask(0); // Increase stencilIndex and apply stencil testing. diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h index 8a72d67af..64bffafe5 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h @@ -133,19 +133,18 @@ public: virtual bool isValid() const; virtual bool canReuseWith(const IntSize& contentsSize, Flags = 0); virtual void didReset(); - void bind(); + void bind(TextureMapperGL*); void initializeStencil(); ~BitmapTextureGL(); virtual uint32_t id() const { return m_id; } uint32_t textureTarget() const { return GraphicsContext3D::TEXTURE_2D; } IntSize textureSize() const { return m_textureSize; } - void setTextureMapper(TextureMapperGL* texmap) { m_textureMapper = texmap; } void updateContents(Image*, const IntRect&, const IntPoint&); virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine); virtual bool isBackedByOpenGL() const { return true; } #if ENABLE(CSS_FILTERS) - virtual PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture& contentTexture, const FilterOperations&); + virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations&); #endif private: @@ -156,17 +155,10 @@ private: Platform3DObject m_rbo; bool m_shouldClear; TextureMapperGL::ClipStack m_clipStack; - TextureMapperGL* m_textureMapper; + RefPtr<GraphicsContext3D> m_context3D; + BitmapTextureGL(TextureMapperGL*); BitmapTextureGL(); - BitmapTextureGL(TextureMapperGL* textureMapper) - : m_id(0) - , m_fbo(0) - , m_rbo(0) - , m_shouldClear(true) - , m_textureMapper(textureMapper) - { - } void clearIfNeeded(); void createFboIfNeeded(); @@ -174,8 +166,6 @@ private: friend class TextureMapperGL; }; -typedef uint64_t ImageUID; -ImageUID uidForImage(Image*); BitmapTextureGL* toBitmapTextureGL(BitmapTexture*); } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp index 9b0c9a56f..9282959de 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp @@ -121,7 +121,7 @@ void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const F } #if ENABLE(CSS_FILTERS) -PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters) +PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations& filters) { RefPtr<FilterEffectRenderer> renderer = FilterEffectRenderer::create(); renderer->setSourceImageRect(FloatRect(FloatPoint::zero(), contentTexture.size())); diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h index 71511fc12..7d51e8805 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h @@ -37,7 +37,7 @@ public: virtual void updateContents(Image*, const IntRect&, const IntPoint&); virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine); #if ENABLE(CSS_FILTERS) - PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture&, const FilterOperations&); + PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture&, const FilterOperations&); #endif private: diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp index 36958987d..e36dbc948 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp @@ -342,7 +342,7 @@ static PassRefPtr<BitmapTexture> applyFilters(const FilterOperations& filters, T return source; RefPtr<BitmapTexture> filterSurface = shouldKeepContentTexture(filters) ? textureMapper->acquireTextureFromPool(source->size()) : source; - return filterSurface->applyFilters(*source, filters); + return filterSurface->applyFilters(textureMapper, *source, filters); } #endif @@ -402,12 +402,12 @@ TextureMapperLayer::~TextureMapperLayer() m_parent->m_children.remove(m_parent->m_children.find(this)); } -void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, int options) +void TextureMapperLayer::flushCompositingState(GraphicsLayerTextureMapper* graphicsLayer, int options) { - syncCompositingState(graphicsLayer, rootLayer()->m_textureMapper, options); + flushCompositingState(graphicsLayer, rootLayer()->m_textureMapper, options); } -void TextureMapperLayer::syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper) +void TextureMapperLayer::flushCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper) { int changeMask = graphicsLayer->changeMask(); @@ -519,18 +519,18 @@ void TextureMapperLayer::syncAnimations() setOpacity(m_state.opacity); } -void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper, int options) +void TextureMapperLayer::flushCompositingState(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper, int options) { if (!textureMapper) return; if (graphicsLayer && !(options & ComputationsOnly)) { - syncCompositingStateSelf(graphicsLayer, textureMapper); + flushCompositingStateSelf(graphicsLayer, textureMapper); graphicsLayer->didSynchronize(); } if (graphicsLayer && m_state.maskLayer) { - m_state.maskLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), textureMapper); + m_state.maskLayer->flushCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), textureMapper); // A mask layer has its parent's size by default, in case it's not set specifically. if (m_state.maskLayer->m_size.isEmpty()) @@ -538,7 +538,7 @@ void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphi } if (m_state.replicaLayer) - m_state.replicaLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), textureMapper); + m_state.replicaLayer->flushCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), textureMapper); syncAnimations(); updateBackingStore(textureMapper, graphicsLayer); @@ -552,11 +552,11 @@ void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphi TextureMapperLayer* layer = toTextureMapperLayer(children[i]); if (!layer) continue; - layer->syncCompositingState(toGraphicsLayerTextureMapper(children[i]), textureMapper, options); + layer->flushCompositingState(toGraphicsLayerTextureMapper(children[i]), textureMapper, options); } } else { for (int i = m_children.size() - 1; i >= 0; --i) - m_children[i]->syncCompositingState(0, textureMapper, options); + m_children[i]->flushCompositingState(0, textureMapper, options); } } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h index 2f7f4b821..5740acf52 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h @@ -114,8 +114,8 @@ public: virtual ~TextureMapperLayer(); - void syncCompositingState(GraphicsLayerTextureMapper*, int syncOptions = 0); - void syncCompositingState(GraphicsLayerTextureMapper*, TextureMapper*, int syncOptions = 0); + void flushCompositingState(GraphicsLayerTextureMapper*, int syncOptions = 0); + void flushCompositingState(GraphicsLayerTextureMapper*, TextureMapper*, int syncOptions = 0); IntSize size() const { return IntSize(m_size.width(), m_size.height()); } void setTransform(const TransformationMatrix&); void setOpacity(float value) { m_opacity = value; } @@ -144,7 +144,7 @@ private: FloatRect targetRectForTileRect(const FloatRect& totalTargetRect, const FloatRect& tileRect) const; void invalidateViewport(const FloatRect&); void notifyChange(ChangeMask); - void syncCompositingStateSelf(GraphicsLayerTextureMapper*, TextureMapper*); + void flushCompositingStateSelf(GraphicsLayerTextureMapper*, TextureMapper*); static int compareGraphicsLayersZValue(const void* a, const void* b); static void sortByZOrder(Vector<TextureMapperLayer* >& array, int first, int last); diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h index 2292f4eb4..db3f0bec6 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h @@ -20,6 +20,10 @@ #ifndef TextureMapperPlatformLayer_h #define TextureMapperPlatformLayer_h +#if USE(GRAPHICS_SURFACE) +#include "GraphicsSurface.h" +#endif + #include "TransformationMatrix.h" namespace WebCore { @@ -34,7 +38,7 @@ public: virtual void swapBuffers() { } #if USE(GRAPHICS_SURFACE) virtual uint32_t copyToGraphicsSurface() { return 0; } - virtual uint64_t graphicsSurfaceToken() const { return 0; } + virtual GraphicsSurfaceToken graphicsSurfaceToken() const { return GraphicsSurfaceToken(); } #endif }; diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp index 73d6fefbb..27e786713 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp @@ -28,249 +28,69 @@ #include "Logging.h" #include "TextureMapperGL.h" +#define STRINGIFY(...) #__VA_ARGS__ + namespace WebCore { -#define STRINGIFY(...) #__VA_ARGS__ -static const char* fragmentShaderSourceOpacityAndMask = - STRINGIFY( - precision mediump float; - uniform sampler2D s_source; - uniform sampler2D s_mask; - uniform lowp float u_opacity; - varying highp vec2 v_sourceTexCoord; - varying highp vec2 v_maskTexCoord; - void main(void) - { - lowp vec4 color = texture2D(s_source, v_sourceTexCoord); - lowp vec4 maskColor = texture2D(s_mask, v_maskTexCoord); - lowp float fragmentAlpha = u_opacity * maskColor.a; - gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha); - } - ); - -static const char* fragmentShaderSourceRectOpacityAndMask = - STRINGIFY( - precision mediump float; - uniform sampler2DRect s_source; - uniform sampler2DRect s_mask; - uniform lowp float u_opacity; - varying highp vec2 v_sourceTexCoord; - varying highp vec2 v_maskTexCoord; - void main(void) - { - lowp vec4 color = texture2DRect(s_source, v_sourceTexCoord); - lowp vec4 maskColor = texture2DRect(s_mask, v_maskTexCoord); - lowp float fragmentAlpha = u_opacity * maskColor.a; - gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha); - } - ); - -static const char* vertexShaderSourceOpacityAndMask = - STRINGIFY( - uniform mat4 u_matrix; - uniform lowp float u_flip; - attribute vec4 a_vertex; - varying highp vec2 v_sourceTexCoord; - varying highp vec2 v_maskTexCoord; - void main(void) - { - v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip)); - v_maskTexCoord = vec2(a_vertex); - gl_Position = u_matrix * a_vertex; - } - ); - -static const char* fragmentShaderSourceSimple = - STRINGIFY( - precision mediump float; - uniform sampler2D s_source; - uniform lowp float u_opacity; - varying highp vec2 v_sourceTexCoord; - void main(void) - { - lowp vec4 color = texture2D(s_source, v_sourceTexCoord); - gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity); - } - ); - -static const char* fragmentShaderSourceAntialiasingNoMask = - STRINGIFY( - precision mediump float; - 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 = - STRINGIFY( - precision mediump float; - 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, u_textureSize * v_sourceTexCoord); - gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity); - } - ); - -static const char* vertexShaderSourceSimple = - STRINGIFY( - uniform mat4 u_matrix; - uniform lowp float u_flip; - attribute vec4 a_vertex; - varying highp vec2 v_sourceTexCoord; - void main(void) - { - v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip)); - gl_Position = u_matrix * a_vertex; - } - ); - -static const char* vertexShaderSourceSolidColor = - STRINGIFY( - uniform mat4 u_matrix; - attribute vec4 a_vertex; - void main(void) - { - gl_Position = u_matrix * a_vertex; - } - ); - - -static const char* fragmentShaderSourceSolidColor = - STRINGIFY( - precision mediump float; - uniform vec4 u_color; - void main(void) - { - gl_FragColor = u_color; - } - ); - -PassRefPtr<TextureMapperShaderProgramSolidColor> TextureMapperShaderManager::solidColorProgram() +static inline bool compositingLogEnabled() { - return static_pointer_cast<TextureMapperShaderProgramSolidColor>(getShaderProgram(SolidColor)); +#if !LOG_DISABLED + return LogCompositing.state == WTFLogChannelOn; +#else + return false; +#endif } -PassRefPtr<TextureMapperShaderProgramAntialiasingNoMask> TextureMapperShaderManager::antialiasingNoMaskProgram() +TextureMapperShaderProgram::TextureMapperShaderProgram(PassRefPtr<GraphicsContext3D> context, const String& vertex, const String& fragment) + : m_context(context) { - return static_pointer_cast<TextureMapperShaderProgramAntialiasingNoMask>(getShaderProgram(AntialiasingNoMask)); + m_vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER); + m_fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER); + m_context->shaderSource(m_vertexShader, vertex); + m_context->shaderSource(m_fragmentShader, fragment); + m_id = m_context->createProgram(); + m_context->compileShader(m_vertexShader); + m_context->compileShader(m_fragmentShader); + m_context->attachShader(m_id, m_vertexShader); + m_context->attachShader(m_id, m_fragmentShader); + m_context->linkProgram(m_id); + + if (!compositingLogEnabled()) + return; + + if (m_context->getError() == GraphicsContext3D::NO_ERROR) + return; + + String log = m_context->getShaderInfoLog(m_vertexShader); + LOG(Compositing, "Vertex shader log: %s\n", log.utf8().data()); + log = m_context->getShaderInfoLog(m_fragmentShader); + LOG(Compositing, "Fragment shader log: %s\n", log.utf8().data()); + log = m_context->getProgramInfoLog(m_id); + LOG(Compositing, "Program log: %s\n", log.utf8().data()); } -PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProgram(ShaderType shaderType) +GC3Duint TextureMapperShaderProgram::getLocation(const AtomicString& name, VariableType type) { - RefPtr<TextureMapperShaderProgram> program; - if (shaderType == Invalid) - return program; + HashMap<AtomicString, GC3Duint>::iterator it = m_variables.find(name); + if (it != m_variables.end()) + return it->value; - TextureMapperShaderProgramMap::iterator it = m_textureMapperShaderProgramMap.find(shaderType); - if (it != m_textureMapperShaderProgramMap.end()) - return it->second; - - switch (shaderType) { - case Simple: - program = TextureMapperShaderProgramSimple::create(m_context); - break; - case RectSimple: - program = TextureMapperShaderProgramRectSimple::create(m_context); - break; - case AntialiasingNoMask: - program = TextureMapperShaderProgramAntialiasingNoMask::create(m_context); - break; - case OpacityAndMask: - program = TextureMapperShaderProgramOpacityAndMask::create(m_context); - break; - case RectOpacityAndMask: - program = TextureMapperShaderProgramRectOpacityAndMask::create(m_context); + GC3Duint location = 0; + switch (type) { + case UniformVariable: + location = m_context->getUniformLocation(m_id, name); break; - case SolidColor: - program = TextureMapperShaderProgramSolidColor::create(m_context); + case AttribVariable: + location = m_context->getAttribLocation(m_id, name); break; - case Invalid: + default: ASSERT_NOT_REACHED(); + break; } - m_textureMapperShaderProgramMap.add(shaderType, program); - return program; -} - -TextureMapperShaderProgram::TextureMapperShaderProgram(GraphicsContext3D* context, const char* vertexShaderSource, const char* fragmentShaderSource) - : m_context(context) - , m_id(0) - , m_vertexAttrib(0) - , m_vertexShader(0) - , m_fragmentShader(0) - , m_matrixLocation(-1) - , m_flipLocation(-1) - , m_textureSizeLocation(-1) - , m_sourceTextureLocation(-1) - , m_opacityLocation(-1) - , m_maskTextureLocation(-1) - , m_vertexShaderSource(vertexShaderSource) - , m_fragmentShaderSource(fragmentShaderSource) -{ -} - -void TextureMapperShaderProgram::initializeProgram() -{ - const char* vertexShaderSourceProgram = vertexShaderSource(); - const char* fragmentShaderSourceProgram = fragmentShaderSource(); - Platform3DObject vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER); - Platform3DObject fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER); - m_context->shaderSource(vertexShader, vertexShaderSourceProgram); - m_context->shaderSource(fragmentShader, fragmentShaderSourceProgram); - Platform3DObject programID = m_context->createProgram(); - m_context->compileShader(vertexShader); - m_context->compileShader(fragmentShader); - - m_context->attachShader(programID, vertexShader); - m_context->attachShader(programID, fragmentShader); - m_context->linkProgram(programID); - - m_vertexAttrib = m_context->getAttribLocation(programID, "a_vertex"); - - m_id = programID; - m_vertexShader = vertexShader; - m_fragmentShader = fragmentShader; -} -void TextureMapperShaderProgram::getUniformLocation(GC3Dint &variable, const char* name) -{ - variable = m_context->getUniformLocation(m_id, name); - ASSERT(variable >= 0); + m_variables.add(name, location); + return location; } TextureMapperShaderProgram::~TextureMapperShaderProgram() @@ -286,120 +106,189 @@ TextureMapperShaderProgram::~TextureMapperShaderProgram() m_context->deleteProgram(programID); } -TextureMapperShaderProgramSimple::TextureMapperShaderProgramSimple(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceSimple, fragmentShaderSourceSimple) -{ - initializeProgram(); - getUniformLocation(m_flipLocation, "u_flip"); - getUniformLocation(m_matrixLocation, "u_matrix"); - getUniformLocation(m_sourceTextureLocation, "s_source"); - getUniformLocation(m_opacityLocation, "u_opacity"); -} +struct ShaderSpec { + String vertexShader; + String fragmentShader; + ShaderSpec(const char* vertex = 0, const char* fragment = 0) + : vertexShader(vertex ? String(ASCIILiteral(vertex)) : String()) + , fragmentShader(fragment ? String(ASCIILiteral(fragment)) : String()) + { + } +}; -TextureMapperShaderProgramSolidColor::TextureMapperShaderProgramSolidColor(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceSolidColor, fragmentShaderSourceSolidColor) +static void getShaderSpec(TextureMapperShaderManager::ShaderKey key, String& vertexSource, String& fragmentSource) { - initializeProgram(); - getUniformLocation(m_matrixLocation, "u_matrix"); - getUniformLocation(m_colorLocation, "u_color"); -} + static Vector<ShaderSpec> specs = Vector<ShaderSpec>(); + static const char* fragmentOpacityAndMask = + STRINGIFY( + precision mediump float; + uniform sampler2D s_sampler; + uniform sampler2D s_mask; + uniform lowp float u_opacity; + varying highp vec2 v_sourceTexCoord; + varying highp vec2 v_maskTexCoord; + void main(void) + { + lowp vec4 color = texture2D(s_sampler, v_sourceTexCoord); + lowp vec4 maskColor = texture2D(s_mask, v_maskTexCoord); + lowp float fragmentAlpha = u_opacity * maskColor.a; + gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha); + } + ); -TextureMapperShaderProgramRectSimple::TextureMapperShaderProgramRectSimple(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceSimple, fragmentShaderSourceRectSimple) -{ - initializeProgram(); - 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"); -} + static const char* fragmentRectOpacityAndMask = + STRINGIFY( + precision mediump float; + uniform sampler2DRect s_sampler; + uniform sampler2DRect s_mask; + uniform lowp float u_opacity; + varying highp vec2 v_sourceTexCoord; + varying highp vec2 v_maskTexCoord; + void main(void) + { + lowp vec4 color = texture2DRect(s_sampler, v_sourceTexCoord); + lowp vec4 maskColor = texture2DRect(s_mask, v_maskTexCoord); + lowp float fragmentAlpha = u_opacity * maskColor.a; + gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha); + } + ); -TextureMapperShaderProgramOpacityAndMask::TextureMapperShaderProgramOpacityAndMask(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceOpacityAndMask, fragmentShaderSourceOpacityAndMask) -{ - initializeProgram(); - getUniformLocation(m_matrixLocation, "u_matrix"); - getUniformLocation(m_flipLocation, "u_flip"); - getUniformLocation(m_sourceTextureLocation, "s_source"); - getUniformLocation(m_maskTextureLocation, "s_mask"); - getUniformLocation(m_opacityLocation, "u_opacity"); -} + static const char* vertexOpacityAndMask = + STRINGIFY( + uniform mat4 u_matrix; + uniform lowp float u_flip; + attribute vec4 a_vertex; + varying highp vec2 v_sourceTexCoord; + varying highp vec2 v_maskTexCoord; + void main(void) + { + v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip)); + v_maskTexCoord = vec2(a_vertex); + gl_Position = u_matrix * a_vertex; + } + ); -TextureMapperShaderProgramRectOpacityAndMask::TextureMapperShaderProgramRectOpacityAndMask(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceOpacityAndMask, fragmentShaderSourceRectOpacityAndMask) -{ - initializeProgram(); - getUniformLocation(m_matrixLocation, "u_matrix"); - getUniformLocation(m_flipLocation, "u_flip"); - getUniformLocation(m_sourceTextureLocation, "s_source"); - getUniformLocation(m_maskTextureLocation, "s_mask"); - getUniformLocation(m_opacityLocation, "u_opacity"); -} + static const char* fragmentSimple = + STRINGIFY( + precision mediump float; + uniform sampler2D s_sampler; + uniform lowp float u_opacity; + varying highp vec2 v_sourceTexCoord; + void main(void) + { + lowp vec4 color = texture2D(s_sampler, v_sourceTexCoord); + gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity); + } + ); -TextureMapperShaderProgramAntialiasingNoMask::TextureMapperShaderProgramAntialiasingNoMask(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, 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"); -} + static const char* fragmentAntialiasingNoMask = + STRINGIFY( + precision mediump float; + uniform sampler2D s_sampler; + varying highp vec2 v_sourceTexCoord; + uniform lowp float u_opacity; + uniform vec3 u_expandedQuadEdgesInScreenSpace[8]; + void main() + { + vec4 sampledColor = texture2D(s_sampler, 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)); + } + ); -TextureMapperShaderManager::TextureMapperShaderManager(GraphicsContext3D* context) - : m_context(context) -{ -} + static const char* fragmentRectSimple = + STRINGIFY( + precision mediump float; + uniform sampler2DRect s_sampler; + uniform lowp vec2 s_samplerSize; + uniform lowp float u_opacity; + varying highp vec2 v_sourceTexCoord; + void main(void) + { + lowp vec4 color = texture2DRect(s_sampler, s_samplerSize * v_sourceTexCoord); + gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity); + } + ); -TextureMapperShaderManager::~TextureMapperShaderManager() -{ -} + static const char* vertexSimple = + STRINGIFY( + uniform mat4 u_matrix; + uniform lowp float u_flip; + attribute vec4 a_vertex; + varying highp vec2 v_sourceTexCoord; + void main(void) + { + v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip)); + gl_Position = u_matrix * a_vertex; + } + ); -#if ENABLE(CSS_FILTERS) + static const char* vertexSolidColor = + STRINGIFY( + uniform mat4 u_matrix; + attribute vec4 a_vertex; + void main(void) + { + gl_Position = u_matrix * a_vertex; + } + ); -// Create a normal distribution of 21 values between -2 and 2. -#define GAUSSIAN_KERNEL_HALF_WIDTH 11 -#define GAUSSIAN_KERNEL_STEP 0.2 -StandardFilterProgram::~StandardFilterProgram() -{ - m_context->detachShader(m_id, m_vertexShader); - m_context->deleteShader(m_vertexShader); - m_context->detachShader(m_id, m_fragmentShader); - m_context->deleteShader(m_fragmentShader); - m_context->deleteProgram(m_id); -} + static const char* fragmentSolidColor = + STRINGIFY( + precision mediump float; + uniform vec4 u_color; + void main(void) + { + gl_FragColor = u_color; + } + ); -StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterOperation::OperationType type, unsigned pass) - : m_context(context) - , m_id(0) -{ - const char* vertexShaderSource = - STRINGIFY( - attribute vec4 a_vertex; - attribute vec4 a_texCoord; - varying highp vec2 v_texCoord; - void main(void) - { - v_texCoord = vec2(a_texCoord); - gl_Position = a_vertex; - } - ); + static const char* vertexFilter = + STRINGIFY( + attribute vec4 a_vertex; + attribute vec4 a_texCoord; + varying highp vec2 v_texCoord; + void main(void) + { + v_texCoord = vec2(a_texCoord); + gl_Position = a_vertex; + } + ); #define STANDARD_FILTER(...) \ "precision mediump float;\n"\ "varying highp vec2 v_texCoord;\n"\ "uniform highp float u_amount;\n"\ - "uniform sampler2D u_texture;\n"\ - #__VA_ARGS__ \ - "void main(void)\n { gl_FragColor = shade(texture2D(u_texture, v_texCoord)); }" + "uniform sampler2D s_sampler;\n"#__VA_ARGS__ \ + "void main(void)\n { gl_FragColor = shade(texture2D(s_sampler, v_texCoord)); }" - const char* fragmentShaderSource = 0; - switch (type) { - case FilterOperation::GRAYSCALE: - fragmentShaderSource = STANDARD_FILTER( + static const char* fragmentGrayscaleFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { lowp float amount = 1.0 - u_amount; @@ -409,9 +298,9 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO color.a); } ); - break; - case FilterOperation::SEPIA: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentSepiaFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { lowp float amount = 1.0 - u_amount; @@ -421,9 +310,9 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO color.a); } ); - break; - case FilterOperation::SATURATE: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentSaturateFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { return vec4((0.213 + 0.787 * u_amount) * color.r + (0.715 - 0.715 * u_amount) * color.g + (0.072 - 0.072 * u_amount) * color.b, @@ -432,9 +321,9 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO color.a); } ); - break; - case FilterOperation::HUE_ROTATE: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentHueRotateFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { highp float pi = 3.14159265358979323846; @@ -446,58 +335,62 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO color.a); } ); - break; - case FilterOperation::INVERT: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentInvertFilter = + STANDARD_FILTER( lowp float invert(lowp float n) { return (1.0 - n) * u_amount + n * (1.0 - u_amount); } lowp vec4 shade(lowp vec4 color) { return vec4(invert(color.r), invert(color.g), invert(color.b), color.a); } ); - break; - case FilterOperation::BRIGHTNESS: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentBrightnessFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { return vec4(color.rgb * (1.0 + u_amount), color.a); } ); - break; - case FilterOperation::CONTRAST: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentContrastFilter = + STANDARD_FILTER( lowp float contrast(lowp float n) { return (n - 0.5) * u_amount + 0.5; } lowp vec4 shade(lowp vec4 color) { return vec4(contrast(color.r), contrast(color.g), contrast(color.b), color.a); } ); - break; - case FilterOperation::OPACITY: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentOpacityFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { return vec4(color.r, color.g, color.b, color.a * u_amount); } ); - break; - case FilterOperation::BLUR: - fragmentShaderSource = STRINGIFY( + +#define BLUR_CONSTANTS "#define GAUSSIAN_KERNEL_HALF_WIDTH 11\n#define GAUSSIAN_KERNEL_STEP 0.2\n" + + static const char* fragmentBlurFilter = + BLUR_CONSTANTS + STRINGIFY( + // Create a normal distribution of 21 values between -2 and 2. precision mediump float; varying highp vec2 v_texCoord; uniform lowp vec2 u_blurRadius; - uniform sampler2D u_texture; + uniform sampler2D s_sampler; uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; lowp vec4 sampleColor(float radius) { vec2 coord = v_texCoord + radius * u_blurRadius; - return texture2D(u_texture, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); + return texture2D(s_sampler, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); } vec4 blur() { - vec4 total = sampleColor(0) * u_gaussianKernel[0]; + vec4 total = sampleColor(0.) * u_gaussianKernel[0]; for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { total += sampleColor(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; total += sampleColor(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; @@ -511,282 +404,130 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO gl_FragColor = blur(); } ); - break; - case FilterOperation::DROP_SHADOW: - switch (pass) { - case 0: { - // First pass: horizontal alpha blur. - fragmentShaderSource = STRINGIFY( - precision mediump float; - varying highp vec2 v_texCoord; - uniform lowp float u_shadowBlurRadius; - uniform lowp vec2 u_shadowOffset; - uniform sampler2D u_texture; - uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; - - lowp float sampleAlpha(float radius) - { - vec2 coord = v_texCoord - u_shadowOffset + vec2(radius * u_shadowBlurRadius, 0.); - return texture2D(u_texture, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); - } - lowp float shadowBlurHorizontal() - { - float total = sampleAlpha(0) * u_gaussianKernel[0]; - for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { - total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; - total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; - } - - return total; - } + static const char* fragmentShadowFilter1 = + BLUR_CONSTANTS + STRINGIFY( + precision mediump float; + varying highp vec2 v_texCoord; + uniform lowp float u_blurRadius; + uniform lowp vec2 u_shadowOffset; + uniform sampler2D s_sampler; + uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; - void main(void) - { - gl_FragColor = vec4(1., 1., 1., 1.) * shadowBlurHorizontal(); - } - ); - break; + lowp float sampleAlpha(float radius) + { + vec2 coord = v_texCoord - u_shadowOffset + vec2(radius * u_blurRadius, 0.); + return texture2D(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); } - case 1: { - // Second pass: vertical alpha blur and composite with origin. - fragmentShaderSource = STRINGIFY( - precision mediump float; - varying highp vec2 v_texCoord; - uniform lowp float u_shadowBlurRadius; - uniform lowp vec4 u_shadowColor; - uniform sampler2D u_texture; - uniform sampler2D u_contentTexture; - uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; - - lowp float sampleAlpha(float r) - { - vec2 coord = v_texCoord + vec2(0., r * u_shadowBlurRadius); - return texture2D(u_texture, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); - } - - lowp float shadowBlurVertical() - { - float total = sampleAlpha(0) * u_gaussianKernel[0]; - for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { - total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; - total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; - } - return total; - } - - lowp vec4 sourceOver(lowp vec4 source, lowp vec4 destination) - { - // Composite the shadow with the original texture. - return source + destination * (1. - source.a); + lowp float shadowBlurHorizontal() + { + float total = sampleAlpha(0.) * u_gaussianKernel[0]; + for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { + total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; + total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; } - void main(void) - { - gl_FragColor = sourceOver(texture2D(u_contentTexture, v_texCoord), shadowBlurVertical() * u_shadowColor); - } - ); - break; + return total; } - break; - } - default: - break; - } - if (!fragmentShaderSource) - return; - Platform3DObject vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER); - Platform3DObject fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER); - m_context->shaderSource(vertexShader, vertexShaderSource); - m_context->shaderSource(fragmentShader, fragmentShaderSource); - Platform3DObject programID = m_context->createProgram(); - m_context->compileShader(vertexShader); - m_context->compileShader(fragmentShader); -#if !LOG_DISABLED - String log; - m_context->getShaderInfoLog(fragmentShader); - WTFLog(&LogCompositing, "%s\n", log.ascii().data()); -#endif - m_context->attachShader(programID, vertexShader); - m_context->attachShader(programID, fragmentShader); - m_context->linkProgram(programID); + void main(void) + { + gl_FragColor = vec4(1., 1., 1., 1.) * shadowBlurHorizontal(); + } + ); - m_vertexAttrib = m_context->getAttribLocation(programID, "a_vertex"); - m_texCoordAttrib = m_context->getAttribLocation(programID, "a_texCoord"); - m_textureUniformLocation = m_context->getUniformLocation(programID, "u_texture"); - switch (type) { - case FilterOperation::GRAYSCALE: - case FilterOperation::SEPIA: - case FilterOperation::SATURATE: - case FilterOperation::HUE_ROTATE: - case FilterOperation::INVERT: - case FilterOperation::BRIGHTNESS: - case FilterOperation::CONTRAST: - case FilterOperation::OPACITY: - m_uniformLocations.amount = m_context->getUniformLocation(programID, "u_amount"); - break; - case FilterOperation::BLUR: - m_uniformLocations.blur.radius = m_context->getUniformLocation(programID, "u_blurRadius"); - m_uniformLocations.blur.gaussianKernel = m_context->getUniformLocation(programID, "u_gaussianKernel"); - break; - case FilterOperation::DROP_SHADOW: - m_uniformLocations.shadow.blurRadius = m_context->getUniformLocation(programID, "u_shadowBlurRadius"); - m_uniformLocations.shadow.gaussianKernel = m_context->getUniformLocation(programID, "u_gaussianKernel"); - if (!pass) - m_uniformLocations.shadow.offset = m_context->getUniformLocation(programID, "u_shadowOffset"); - else { - // We only need the color and the content texture in the second pass, the first pass is only a horizontal alpha blur. - m_uniformLocations.shadow.color = m_context->getUniformLocation(programID, "u_shadowColor"); - m_uniformLocations.shadow.contentTexture = m_context->getUniformLocation(programID, "u_contentTexture"); - } - break; - default: - break; - } - m_id = programID; - m_vertexShader = vertexShader; - m_fragmentShader = fragmentShader; -} + // Second pass: vertical alpha blur and composite with origin. + static const char* fragmentShadowFilter2 = + BLUR_CONSTANTS + STRINGIFY( + precision mediump float; + varying highp vec2 v_texCoord; + uniform lowp float u_blurRadius; + uniform lowp vec4 u_shadowColor; + uniform sampler2D s_sampler; + uniform sampler2D s_contentTexture; + uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; -PassRefPtr<StandardFilterProgram> StandardFilterProgram::create(GraphicsContext3D* context, FilterOperation::OperationType type, unsigned pass) -{ - RefPtr<StandardFilterProgram> program = adoptRef(new StandardFilterProgram(context, type, pass)); - if (!program->m_id) - return 0; + lowp float sampleAlpha(float r) + { + vec2 coord = v_texCoord + vec2(0., r * u_blurRadius); + return texture2D(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); + } - return program; -} + lowp float shadowBlurVertical() + { + float total = sampleAlpha(0.) * u_gaussianKernel[0]; + for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { + total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; + total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; + } -static inline float gauss(float x) -{ - return exp(-(x * x) / 2.); -} + return total; + } -static float* gaussianKernel() -{ - static bool prepared = false; - static float kernel[GAUSSIAN_KERNEL_HALF_WIDTH] = {0, }; + lowp vec4 sourceOver(lowp vec4 source, lowp vec4 destination) + { + // Composite the shadow with the original texture. + return source + destination * (1. - source.a); + } - if (prepared) - return kernel; + void main(void) + { + gl_FragColor = sourceOver(texture2D(s_contentTexture, v_texCoord), shadowBlurVertical() * u_shadowColor); + } + ); - kernel[0] = gauss(0); - float sum = kernel[0]; - for (unsigned i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; ++i) { - kernel[i] = gauss(i * GAUSSIAN_KERNEL_STEP); - sum += 2 * kernel[i]; + if (specs.isEmpty()) { + specs.resize(TextureMapperShaderManager::LastFilter); + specs[TextureMapperShaderManager::Default] = ShaderSpec(vertexSimple, fragmentSimple); + specs[TextureMapperShaderManager::SolidColor] = ShaderSpec(vertexSolidColor, fragmentSolidColor); + specs[TextureMapperShaderManager::Rect] = ShaderSpec(vertexSimple, fragmentRectSimple); + specs[TextureMapperShaderManager::Masked] = ShaderSpec(vertexOpacityAndMask, fragmentOpacityAndMask); + specs[TextureMapperShaderManager::MaskedRect] = ShaderSpec(vertexOpacityAndMask, fragmentRectOpacityAndMask); + specs[TextureMapperShaderManager::Antialiased] = ShaderSpec(vertexSimple, fragmentAntialiasingNoMask); + specs[TextureMapperShaderManager::GrayscaleFilter] = ShaderSpec(vertexFilter, fragmentGrayscaleFilter); + specs[TextureMapperShaderManager::SepiaFilter] = ShaderSpec(vertexFilter, fragmentSepiaFilter); + specs[TextureMapperShaderManager::SaturateFilter] = ShaderSpec(vertexFilter, fragmentSaturateFilter); + specs[TextureMapperShaderManager::HueRotateFilter] = ShaderSpec(vertexFilter, fragmentHueRotateFilter); + specs[TextureMapperShaderManager::BrightnessFilter] = ShaderSpec(vertexFilter, fragmentBrightnessFilter); + specs[TextureMapperShaderManager::ContrastFilter] = ShaderSpec(vertexFilter, fragmentContrastFilter); + specs[TextureMapperShaderManager::InvertFilter] = ShaderSpec(vertexFilter, fragmentInvertFilter); + specs[TextureMapperShaderManager::OpacityFilter] = ShaderSpec(vertexFilter, fragmentOpacityFilter); + specs[TextureMapperShaderManager::BlurFilter] = ShaderSpec(vertexFilter, fragmentBlurFilter); + specs[TextureMapperShaderManager::ShadowFilterPass1] = ShaderSpec(vertexFilter, fragmentShadowFilter1); + specs[TextureMapperShaderManager::ShadowFilterPass2] = ShaderSpec(vertexFilter, fragmentShadowFilter2); } - // Normalize the kernel - float scale = 1 / sum; - for (unsigned i = 0; i < GAUSSIAN_KERNEL_HALF_WIDTH; ++i) - kernel[i] *= scale; - - prepared = true; - return kernel; + ASSERT(specs.size() > key); + ShaderSpec& spec = specs[key]; + vertexSource = spec.vertexShader; + fragmentSource = spec.fragmentShader; } -void StandardFilterProgram::prepare(const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture) +TextureMapperShaderManager::TextureMapperShaderManager(GraphicsContext3D* context) + : m_context(context) { - m_context->useProgram(m_id); - switch (operation.getOperationType()) { - case FilterOperation::GRAYSCALE: - case FilterOperation::SEPIA: - case FilterOperation::SATURATE: - case FilterOperation::HUE_ROTATE: - m_context->uniform1f(m_uniformLocations.amount, static_cast<const BasicColorMatrixFilterOperation&>(operation).amount()); - break; - case FilterOperation::INVERT: - case FilterOperation::BRIGHTNESS: - case FilterOperation::CONTRAST: - case FilterOperation::OPACITY: - m_context->uniform1f(m_uniformLocations.amount, static_cast<const BasicComponentTransferFilterOperation&>(operation).amount()); - break; - case FilterOperation::BLUR: { - const BlurFilterOperation& blur = static_cast<const BlurFilterOperation&>(operation); - FloatSize radius; - - // Blur is done in two passes, first horizontally and then vertically. The same shader is used for both. - if (pass) - radius.setHeight(floatValueForLength(blur.stdDeviation(), size.height()) / size.height()); - else - radius.setWidth(floatValueForLength(blur.stdDeviation(), size.width()) / size.width()); - - m_context->uniform2f(m_uniformLocations.blur.radius, radius.width(), radius.height()); - m_context->uniform1fv(m_uniformLocations.blur.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel()); - break; - } - case FilterOperation::DROP_SHADOW: { - const DropShadowFilterOperation& shadow = static_cast<const DropShadowFilterOperation&>(operation); - switch (pass) { - case 0: - // First pass: vertical alpha blur. - m_context->uniform2f(m_uniformLocations.shadow.offset, float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height())); - m_context->uniform1f(m_uniformLocations.shadow.blurRadius, shadow.stdDeviation() / float(size.width())); - m_context->uniform1fv(m_uniformLocations.shadow.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel()); - break; - case 1: - // Second pass: we need the shadow color and the content texture for compositing. - m_context->uniform1f(m_uniformLocations.shadow.blurRadius, shadow.stdDeviation() / float(size.height())); - m_context->uniform1fv(m_uniformLocations.shadow.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel()); - m_context->activeTexture(GraphicsContext3D::TEXTURE1); - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture); - m_context->uniform1i(m_uniformLocations.shadow.contentTexture, 1); - float r, g, b, a; - shadow.color().getRGBA(r, g, b, a); - m_context->uniform4f(m_uniformLocations.shadow.color, r, g, b, a); - break; - } - break; - } - default: - break; - } } -PassRefPtr<StandardFilterProgram> TextureMapperShaderManager::getShaderForFilter(const FilterOperation& filter, unsigned pass) +TextureMapperShaderManager::~TextureMapperShaderManager() { - RefPtr<StandardFilterProgram> program; - FilterOperation::OperationType type = filter.getOperationType(); - int key = int(type) | (pass << 16); - FilterMap::iterator iterator = m_filterMap.find(key); - if (iterator == m_filterMap.end()) { - program = StandardFilterProgram::create(m_context, type, pass); - if (!program) - return 0; - - m_filterMap.add(key, program); - } else - program = iterator->second; - - return program; } -unsigned TextureMapperShaderManager::getPassesRequiredForFilter(const FilterOperation& operation) const +PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProgram(ShaderKey key) { - switch (operation.getOperationType()) { - case FilterOperation::GRAYSCALE: - case FilterOperation::SEPIA: - case FilterOperation::SATURATE: - case FilterOperation::HUE_ROTATE: - case FilterOperation::INVERT: - case FilterOperation::BRIGHTNESS: - case FilterOperation::CONTRAST: - case FilterOperation::OPACITY: - return 1; - case FilterOperation::BLUR: - case FilterOperation::DROP_SHADOW: - // We use two-passes (vertical+horizontal) for blur and drop-shadow. - return 2; - default: - return 0; - } - + TextureMapperShaderProgramMap::iterator it = m_programs.find(key); + if (it != m_programs.end()) + return it->value; + + String vertexShader; + String fragmentShader; + getShaderSpec(key, vertexShader, fragmentShader); + RefPtr<TextureMapperShaderProgram> program = TextureMapperShaderProgram::create(m_context, vertexShader, fragmentShader); + m_programs.add(key, program); + return program; } - -#endif }; #endif diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h index 1ffb7100b..b1f8d6107 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h @@ -21,233 +21,102 @@ #ifndef TextureMapperShaderManager_h #define TextureMapperShaderManager_h -#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) - -#include "FloatQuad.h" +#if USE(TEXTURE_MAPPER) #include "GraphicsContext3D.h" -#include "IntSize.h" #include "TextureMapperGL.h" -#include "TransformationMatrix.h" #include <wtf/HashMap.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> -#include <wtf/text/CString.h> - -#if ENABLE(CSS_FILTERS) -#include "FilterOperations.h" -#endif +#include <wtf/text/AtomicStringHash.h> namespace WebCore { - -class BitmapTexture; -class TextureMapperShaderManager; +#define TEXMAP_DECLARE_VARIABLE(Accessor, Name, Type) GC3Duint Accessor##Location() { static const AtomicString name(Name); return getLocation(name, Type); } +#define TEXMAP_DECLARE_UNIFORM(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "u_"#Accessor, UniformVariable) +#define TEXMAP_DECLARE_ATTRIBUTE(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "a_"#Accessor, AttribVariable) +#define TEXMAP_DECLARE_SAMPLER(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "s_"#Accessor, UniformVariable) class TextureMapperShaderProgram : public RefCounted<TextureMapperShaderProgram> { public: - Platform3DObject id() { return m_id; } - GC3Duint vertexAttrib() { return m_vertexAttrib; } + Platform3DObject programID() const { return m_id; } + GraphicsContext3D* context() { return m_context.get(); } + static PassRefPtr<TextureMapperShaderProgram> create(PassRefPtr<GraphicsContext3D> context, const String& vertex, const String& fragment) + { + return adoptRef(new TextureMapperShaderProgram(context, vertex, fragment)); + } - TextureMapperShaderProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource); virtual ~TextureMapperShaderProgram(); - virtual void prepare(float opacity, const BitmapTexture*) { } - GC3Dint matrixLocation() const { return m_matrixLocation; } - GC3Dint flipLocation() const { return m_flipLocation; } - GC3Dint textureSizeLocation() const { return m_textureSizeLocation; } - GC3Dint sourceTextureLocation() const { return m_sourceTextureLocation; } - GC3Dint maskTextureLocation() const { return m_maskTextureLocation; } - GC3Dint opacityLocation() const { return m_opacityLocation; } - - static bool isValidUniformLocation(GC3Dint location) { return location >= 0; } - -protected: - void getUniformLocation(GC3Dint& var, const char* name); - void initializeProgram(); - virtual void initialize() { } - const char* vertexShaderSource() const { return m_vertexShaderSource.data(); } - const char* fragmentShaderSource() const { return m_fragmentShaderSource.data(); } + TEXMAP_DECLARE_ATTRIBUTE(vertex) + TEXMAP_DECLARE_ATTRIBUTE(texCoord) - GraphicsContext3D* m_context; - Platform3DObject m_id; - GC3Duint m_vertexAttrib; - Platform3DObject m_vertexShader; - Platform3DObject m_fragmentShader; - GC3Dint m_matrixLocation; - GC3Dint m_flipLocation; - GC3Dint m_textureSizeLocation; - GC3Dint m_sourceTextureLocation; - GC3Dint m_opacityLocation; - GC3Dint m_maskTextureLocation; - -private: - CString m_vertexShaderSource; - CString m_fragmentShaderSource; -}; + TEXMAP_DECLARE_UNIFORM(matrix) + TEXMAP_DECLARE_UNIFORM(flip) + TEXMAP_DECLARE_UNIFORM(textureSize) + TEXMAP_DECLARE_UNIFORM(opacity) + TEXMAP_DECLARE_UNIFORM(color) + TEXMAP_DECLARE_UNIFORM(expandedQuadEdgesInScreenSpace) + TEXMAP_DECLARE_SAMPLER(sampler) + TEXMAP_DECLARE_SAMPLER(mask) #if ENABLE(CSS_FILTERS) -class StandardFilterProgram : public RefCounted<StandardFilterProgram> { -public: - virtual ~StandardFilterProgram(); - virtual void prepare(const FilterOperation&, unsigned pass, const IntSize&, GC3Duint contentTexture); - static PassRefPtr<StandardFilterProgram> create(GraphicsContext3D*, FilterOperation::OperationType, unsigned pass); - GC3Duint vertexAttrib() const { return m_vertexAttrib; } - GC3Duint texCoordAttrib() const { return m_texCoordAttrib; } - GC3Duint textureUniform() const { return m_textureUniformLocation; } -protected: - GraphicsContext3D* m_context; -private: - StandardFilterProgram(); - StandardFilterProgram(GraphicsContext3D*, FilterOperation::OperationType, unsigned pass); - Platform3DObject m_id; - Platform3DObject m_vertexShader; - Platform3DObject m_fragmentShader; - GC3Duint m_vertexAttrib; - GC3Duint m_texCoordAttrib; - GC3Duint m_textureUniformLocation; - union { - GC3Duint amount; - - struct { - GC3Duint radius; - GC3Duint gaussianKernel; - } blur; - - struct { - GC3Duint blurRadius; - GC3Duint color; - GC3Duint offset; - GC3Duint contentTexture; - GC3Duint gaussianKernel; - } shadow; - } m_uniformLocations; -}; + TEXMAP_DECLARE_UNIFORM(amount) + TEXMAP_DECLARE_UNIFORM(gaussianKernel) + TEXMAP_DECLARE_UNIFORM(blurRadius) + TEXMAP_DECLARE_UNIFORM(shadowColor) + TEXMAP_DECLARE_UNIFORM(shadowOffset) + TEXMAP_DECLARE_SAMPLER(contentTexture) #endif -class TextureMapperShaderProgramSimple : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramSimple> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramSimple(context)); - } - -protected: - TextureMapperShaderProgramSimple(GraphicsContext3D*); -private: - TextureMapperShaderProgramSimple(); -}; - -class TextureMapperShaderProgramRectSimple : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramRectSimple> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramRectSimple(context)); - } - -protected: - TextureMapperShaderProgramRectSimple(GraphicsContext3D*); private: - TextureMapperShaderProgramRectSimple(); -}; - -class TextureMapperShaderProgramOpacityAndMask : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramOpacityAndMask> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramOpacityAndMask(context)); - } - -protected: - TextureMapperShaderProgramOpacityAndMask(GraphicsContext3D*); -private: - TextureMapperShaderProgramOpacityAndMask(); -}; - -class TextureMapperShaderProgramRectOpacityAndMask : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramRectOpacityAndMask> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramRectOpacityAndMask(context)); - } - -protected: - TextureMapperShaderProgramRectOpacityAndMask(GraphicsContext3D*); -private: - TextureMapperShaderProgramRectOpacityAndMask(); -}; - -class TextureMapperShaderProgramSolidColor : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramSolidColor> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramSolidColor(context)); - } - - GC3Dint colorLocation() const { return m_colorLocation; } - -protected: - TextureMapperShaderProgramSolidColor(GraphicsContext3D*); -private: - TextureMapperShaderProgramSolidColor(); - GC3Dint m_colorLocation; -}; - -class TextureMapperShaderProgramAntialiasingNoMask : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramAntialiasingNoMask> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramAntialiasingNoMask(context)); - } - - GC3Dint expandedQuadVerticesInTextureCoordinatesLocation() { return m_expandedQuadVerticesInTextureCordinatesLocation; } - GC3Dint expandedQuadEdgesInScreenSpaceLocation() { return m_expandedQuadEdgesInScreenSpaceLocation; } + TextureMapperShaderProgram(PassRefPtr<GraphicsContext3D>, const String& vertexShaderSource, const String& fragmentShaderSource); + Platform3DObject m_vertexShader; + Platform3DObject m_fragmentShader; -protected: - TextureMapperShaderProgramAntialiasingNoMask(GraphicsContext3D*); -private: - TextureMapperShaderProgramAntialiasingNoMask(); + enum VariableType { UniformVariable, AttribVariable }; + GC3Duint getLocation(const AtomicString&, VariableType); - GC3Dint m_expandedQuadVerticesInTextureCordinatesLocation; - GC3Dint m_expandedQuadEdgesInScreenSpaceLocation; + RefPtr<GraphicsContext3D> m_context; + Platform3DObject m_id; + HashMap<AtomicString, GC3Duint> m_variables; }; class TextureMapperShaderManager { public: - enum ShaderType { - Invalid = 0, // HashMaps do not like 0 as a key. - Simple, - AntialiasingNoMask, - RectSimple, - OpacityAndMask, - RectOpacityAndMask, - SolidColor + enum ShaderKey { + Invalid = 0, + Default, + Rect, + Masked, + MaskedRect, + SolidColor, + Antialiased, + GrayscaleFilter, + SepiaFilter, + SaturateFilter, + HueRotateFilter, + BrightnessFilter, + ContrastFilter, + OpacityFilter, + InvertFilter, + BlurFilter, + ShadowFilterPass1, + ShadowFilterPass2, + LastFilter }; TextureMapperShaderManager() { } TextureMapperShaderManager(GraphicsContext3D*); virtual ~TextureMapperShaderManager(); -#if ENABLE(CSS_FILTERS) - unsigned getPassesRequiredForFilter(const FilterOperation&) const; - PassRefPtr<StandardFilterProgram> getShaderForFilter(const FilterOperation&, unsigned pass); -#endif - - PassRefPtr<TextureMapperShaderProgram> getShaderProgram(ShaderType); - PassRefPtr<TextureMapperShaderProgramSolidColor> solidColorProgram(); - PassRefPtr<TextureMapperShaderProgramAntialiasingNoMask> antialiasingNoMaskProgram(); + PassRefPtr<TextureMapperShaderProgram> getShaderProgram(ShaderKey); private: - typedef HashMap<ShaderType, RefPtr<TextureMapperShaderProgram>, DefaultHash<int>::Hash, HashTraits<int> > TextureMapperShaderProgramMap; - TextureMapperShaderProgramMap m_textureMapperShaderProgramMap; - GraphicsContext3D* m_context; - -#if ENABLE(CSS_FILTERS) - typedef HashMap<int, RefPtr<StandardFilterProgram> > FilterMap; - FilterMap m_filterMap; -#endif + typedef HashMap<ShaderKey, RefPtr<TextureMapperShaderProgram>, DefaultHash<int>::Hash, HashTraits<int> > TextureMapperShaderProgramMap; + TextureMapperShaderProgramMap m_programs; + RefPtr<GraphicsContext3D> m_context; }; } - #endif #endif // TextureMapperShaderManager_h diff --git a/Source/WebCore/platform/graphics/win/FontCGWin.cpp b/Source/WebCore/platform/graphics/win/FontCGWin.cpp index b367bb79d..170c9f07c 100644 --- a/Source/WebCore/platform/graphics/win/FontCGWin.cpp +++ b/Source/WebCore/platform/graphics/win/FontCGWin.cpp @@ -197,19 +197,19 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative. float shadowTextY = point.y() + translation.height() + shadowOffset.height() * (graphicsContext->shadowsIgnoreTransforms() ? -1 : 1); CGContextSetTextPosition(cgContext, shadowTextX, shadowTextY); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); if (font->syntheticBoldOffset()) { CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowOffset.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowOffset.height()); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); } graphicsContext->setFillColor(fillColor, ColorSpaceDeviceRGB); } CGContextSetTextPosition(cgContext, point.x() + translation.width(), point.y() + translation.height()); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); if (font->syntheticBoldOffset()) { CGContextSetTextPosition(cgContext, point.x() + translation.width() + font->syntheticBoldOffset(), point.y() + translation.height()); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); } if (hasSimpleShadow) diff --git a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp index f54897a9b..2540fae97 100644 --- a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp +++ b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp @@ -186,10 +186,10 @@ static HFONT createMLangFont(IMLangFontLink2* langFontLink, HDC hdc, DWORD codeP return hfont; } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { UChar character = characters[0]; - SimpleFontData* fontData = 0; + RefPtr<SimpleFontData> fontData; HWndDC hdc(0); HFONT primaryFont = font.primaryFont()->fontDataForCharacter(character)->platformData().hfont(); HGDIOBJ oldFont = SelectObject(hdc, primaryFont); @@ -293,24 +293,24 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons DeleteObject(hfont); } - return fontData; + return fontData.release(); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::fontDataFromDescriptionAndLogFont(const FontDescription& fontDescription, ShouldRetain shouldRetain, const LOGFONT& font, AtomicString& outFontFamilyName) +PassRefPtr<SimpleFontData> FontCache::fontDataFromDescriptionAndLogFont(const FontDescription& fontDescription, ShouldRetain shouldRetain, const LOGFONT& font, AtomicString& outFontFamilyName) { AtomicString familyName = String(font.lfFaceName, wcsnlen(font.lfFaceName, LF_FACESIZE)); - SimpleFontData* fontData = getCachedFontData(fontDescription, familyName, false, shouldRetain); + RefPtr<SimpleFontData> fontData = getCachedFontData(fontDescription, familyName, false, shouldRetain); if (fontData) outFontFamilyName = familyName; - return fontData; + return fontData.release(); } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { DEFINE_STATIC_LOCAL(AtomicString, fallbackFontName, ()); if (!fallbackFontName.isEmpty()) @@ -329,11 +329,11 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font AtomicString("Lucida Sans Unicode"), AtomicString("Arial") }; - SimpleFontData* simpleFont; + RefPtr<SimpleFontData> simpleFont; for (size_t i = 0; i < WTF_ARRAY_LENGTH(fallbackFonts); ++i) { if (simpleFont = getCachedFontData(fontDescription, fallbackFonts[i], false, shouldRetain)) { fallbackFontName = fallbackFonts[i]; - return simpleFont; + return simpleFont.release(); } } @@ -342,7 +342,7 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font LOGFONT defaultGUILogFont; GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont); if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, defaultGUILogFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); } // Fall back to Non-client metrics fonts. @@ -350,15 +350,15 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font nonClientMetrics.cbSize = sizeof(nonClientMetrics); if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) { if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfMessageFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfMenuFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfStatusFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfCaptionFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfSmCaptionFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); } ASSERT_NOT_REACHED(); diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp index c33cce58d..35c3d7778 100644 --- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp +++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp @@ -101,7 +101,7 @@ private: virtual GraphicsLayer::CompositingCoordinatesOrientation platformCALayerContentsOrientation() const { return GraphicsLayer::CompositingCoordinatesBottomUp; } virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& inClip) { } virtual bool platformCALayerShowDebugBorders() const { return false; } - virtual bool platformCALayerShowRepaintCounter() const { return false; } + virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const { return false; } virtual int platformCALayerIncrementRepaintCount() { return 0; } virtual bool platformCALayerContentsOpaque() const { return false; } diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp index 53af06d64..72323518f 100644 --- a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp +++ b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp @@ -132,40 +132,40 @@ void SimpleFontData::platformDestroy() delete m_scriptFontProperties; } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { float scaledSize = scaleFactor * m_platformData.size(); if (isCustomFont()) { FontPlatformData scaledFont(m_platformData); scaledFont.setSize(scaledSize); - return adoptPtr(new SimpleFontData(scaledFont, true, false)); + return SimpleFontData::create(scaledFont, true, false); } LOGFONT winfont; GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winfont); winfont.lfHeight = -lroundf(scaledSize * (m_platformData.useGDI() ? 1 : 32)); HFONT hfont = CreateFontIndirect(&winfont); - return adoptPtr(new SimpleFontData(FontPlatformData(hfont, scaledSize, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()), isCustomFont(), false)); + return SimpleFontData::create(FontPlatformData(hfont, scaledSize, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()), isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, cSmallCapsFontSizeMultiplier); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const diff --git a/Source/WebCore/platform/graphics/wince/FontCacheWinCE.cpp b/Source/WebCore/platform/graphics/wince/FontCacheWinCE.cpp index 86c61455a..7641edd2d 100644 --- a/Source/WebCore/platform/graphics/wince/FontCacheWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/FontCacheWinCE.cpp @@ -225,7 +225,7 @@ void FontCache::comUninitialize() } } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { String familyName; WCHAR name[LF_FACESIZE]; @@ -235,10 +235,11 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons unsigned unicodeRange = findCharUnicodeRange(character); #if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2) - if (IMLangFontLink2* langFontLink = getFontLinkInterface()) { + if (IMLangFontLink2* langFontLink = getFontLinkInterface()) #else - if (IMLangFontLink* langFontLink = getFontLinkInterface()) { + if (IMLangFontLink* langFontLink = getFontLinkInterface()) #endif + { HGDIOBJ oldFont = GetCurrentObject(g_screenDC, OBJ_FONT); HFONT hfont = 0; DWORD codePages = 0; @@ -267,10 +268,11 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons // We asked about a code page that is not one of the code pages // returned by MLang, so the font might not contain the character. #if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2) - if (!currentFontContainsCharacter(langFontLink, g_screenDC, character)) { + if (!currentFontContainsCharacter(langFontLink, g_screenDC, character)) #else - if (!currentFontContainsCharacter(langFontLink, g_screenDC, hfont, character, name)) { + if (!currentFontContainsCharacter(langFontLink, g_screenDC, hfont, character, name)) #endif + { SelectObject(g_screenDC, oldFont); langFontLink->ReleaseFont(hfont); hfont = 0; @@ -308,20 +310,20 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons FontPlatformData* result = getCachedFontPlatformData(fontDescription, familyName); if (result && result->hash() != origFont.hash()) { - if (SimpleFontData* fontData = getCachedFontData(result, DoNotRetain)) - return fontData; + if (RefPtr<SimpleFontData> fontData = getCachedFontData(result, DoNotRetain)) + return fontData.release(); } } return 0; } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font&) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDesc, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDesc, ShouldRetain shouldRetain) { // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick // the default that the user would get without changing any prefs. diff --git a/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp b/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp index 1266c5c1b..5a295bb40 100644 --- a/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp +++ b/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp @@ -287,9 +287,9 @@ static PassRefPtr<FixedSizeFontData> createFixedSizeFontData(const AtomicString& FixedSizeFontDataKey key(family, weight, italic); FixedSizeFontCache::AddResult result = g_fixedSizeFontCache.add(key, RefPtr<FixedSizeFontData>()); if (result.isNewEntry) - result.iterator->second = FixedSizeFontData::create(family, weight, italic); + result.iterator->value = FixedSizeFontData::create(family, weight, italic); - return result.iterator->second; + return result.iterator->value; } static LONG toGDIFontWeight(FontWeight fontWeight) @@ -463,11 +463,6 @@ const LOGFONT& FontPlatformData::logFont() const return m_private->m_rootFontData->m_font; } -int FontPlatformData::averageCharWidth() const -{ - return (m_private->m_rootFontData->m_metrics.tmAveCharWidth * size() + 36) / 72; -} - bool FontPlatformData::isDisabled() const { return !isValid() || m_private->m_disabled; diff --git a/Source/WebCore/platform/graphics/wince/FontPlatformData.h b/Source/WebCore/platform/graphics/wince/FontPlatformData.h index 9c3f73345..00c946832 100644 --- a/Source/WebCore/platform/graphics/wince/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/wince/FontPlatformData.h @@ -67,7 +67,6 @@ namespace WebCore { bool operator==(const FontPlatformData& other) const { return m_private == other.m_private; } HFONT getScaledFontHandle(int height, int width) const; const LOGFONT& logFont() const; - int averageCharWidth() const; bool isDisabled() const; bool discardFontHandle(); DWORD codePages() const; diff --git a/Source/WebCore/platform/graphics/wince/FontWinCE.cpp b/Source/WebCore/platform/graphics/wince/FontWinCE.cpp index 7aae13fb2..b98c46671 100644 --- a/Source/WebCore/platform/graphics/wince/FontWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/FontWinCE.cpp @@ -313,7 +313,8 @@ static float cursorToX(const Font* font, const TextRunComponents& components, in return xs + pos * comp.m_width / comp.m_spaces; } WidthIterator it(font, comp.m_textRun); - it.advance(pos); + GlyphBuffer glyphBuffer; + it.advance(pos, &glyphBuffer); return xs + it.m_runWidthSoFar; } return width; diff --git a/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp b/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp index 4e5f7e86e..1c93496f0 100644 --- a/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp @@ -1598,7 +1598,7 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer double scaleY = m_data->m_transform.d(); int height = fontData->platformData().size() * scaleY; - int width = fontData->platformData().averageCharWidth() * scaleX; + int width = fontData->avgCharWidth() * scaleX; if (!height || !width) return; @@ -1626,10 +1626,10 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer const GlyphBufferAdvance* advance = glyphBuffer.advances(from); if (scaleX == 1.) for (int i = 1; i < numGlyphs; ++i) - offset += *advance++; + offset += (*advance++).width(); else for (int i = 1; i < numGlyphs; ++i) - offset += *advance++ * scaleX; + offset += (*advance++).width() * scaleX; offset += width; @@ -1687,7 +1687,7 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer bool drawOneByOne = false; if (scaleX == 1.) { for (; srcChar < srcCharEnd; ++srcChar) { - offset += *advance++; + offset += (*advance++).width(); int offsetInt = stableRound(offset); if (isCharVisible(*srcChar)) { if (!drawOneByOne && WTF::Unicode::direction(*srcChar) == WTF::Unicode::RightToLeft) @@ -1699,7 +1699,7 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer } } else { for (; srcChar < srcCharEnd; ++srcChar) { - offset += *advance++ * scaleX; + offset += (*advance++).width() * scaleX; int offsetInt = stableRound(offset); if (isCharVisible(*srcChar)) { if (!drawOneByOne && WTF::Unicode::direction(*srcChar) == WTF::Unicode::RightToLeft) diff --git a/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp b/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp index e3b842463..5925c7aa9 100644 --- a/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp @@ -63,7 +63,7 @@ void SimpleFontData::platformDestroy() { } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { FontDescription fontDesc(fontDescription); fontDesc.setComputedSize(lroundf(scaleFactor * fontDesc.computedSize())); @@ -71,28 +71,28 @@ PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri fontDesc.setKeywordSize(lroundf(scaleFactor * fontDesc.keywordSize())); FontPlatformData* result = fontCache()->getCachedFontPlatformData(fontDesc, m_platformData.family()); if (!result) - return nullptr; - return adoptPtr(new SimpleFontData(*result)); + return 0; + return SimpleFontData::create(*result); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } DWORD getKnownFontCodePages(const wchar_t* family); diff --git a/Source/WebCore/platform/graphics/wx/FontCacheWx.cpp b/Source/WebCore/platform/graphics/wx/FontCacheWx.cpp index e0034ecd6..acd1dc3e1 100644 --- a/Source/WebCore/platform/graphics/wx/FontCacheWx.cpp +++ b/Source/WebCore/platform/graphics/wx/FontCacheWx.cpp @@ -43,9 +43,9 @@ void FontCache::platformInit() { } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { - SimpleFontData* fontData = 0; + RefPtr<SimpleFontData> fontData = 0; fontData = getCachedFontData(font.fontDescription(), font.family().family(), false, DoNotRetain); if (!fontData->containsCharacters(characters, length)) fontData = getSimilarFontPlatformData(font); @@ -53,12 +53,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons fontData = getLastResortFallbackFont(font.fontDescription()); ASSERT(fontData); - return fontData; + return fontData.release(); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { - SimpleFontData* simpleFontData = 0; + RefPtr<SimpleFontData> simpleFontData = 0; #if OS(DARWIN) // Attempt to find an appropriate font using a match based on // the presence of keywords in the the requested names. For example, we'll @@ -78,14 +78,14 @@ SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) if (!simpleFontData) simpleFontData = getCachedFontData(font.fontDescription(), font.family().family()); - return simpleFontData; + return simpleFontData.release(); } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick // the default that the user would get without changing any prefs. - SimpleFontData* fallback = 0; + RefPtr<SimpleFontData> fallback = 0; #if OS(WINDOWS) static AtomicString fallbackName("Arial Unicode MS"); #else @@ -94,7 +94,7 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font fallback = getCachedFontData(fontDescription, fallbackName, false, shouldRetain); ASSERT(fallback); - return fallback; + return fallback.release(); } FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) diff --git a/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp index c2e4f2b84..e08a1540c 100644 --- a/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp +++ b/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp @@ -90,32 +90,32 @@ void SimpleFontData::platformDestroy() #endif } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { FontDescription desc = FontDescription(fontDescription); desc.setSpecifiedSize(scaleFactor * fontDescription.computedSize()); FontPlatformData platformData(desc, desc.family().family()); - return adoptPtr(new SimpleFontData(platformData, isCustomFont(), false)); + return SimpleFontData::create(platformData, isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const |