diff options
Diffstat (limited to 'WebCore/platform/graphics/chromium')
14 files changed, 511 insertions, 1243 deletions
diff --git a/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h b/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h new file mode 100644 index 0000000..e1fb740 --- /dev/null +++ b/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CrossProcessFontLoading_h +#define CrossProcessFontLoading_h + +#import <wtf/RefCounted.h> +#import <wtf/RetainPtr.h> + +typedef struct CGFont* CGFontRef; +typedef UInt32 ATSFontContainerRef; +typedef UInt32 ATSFontRef; + +namespace WebCore { + +// MemoryActivatedFont encapsulates a font loaded from another process and +// activated from memory. +// +// Responsibilities: +// * Holder for the CGFontRef & ATSFontRef belonging to the activated font. +// * Responsible for unloading the font container when done. +// +// Memory Management: +// The class is reference counted, with each instance of FontPlatformData that +// uses this class holding a reference to it. +// Entries are kept track of internally in a hash to allow quick lookup +// of existing instances for reuse: +// - fontCacheBySrcFontContainerRef() - key is the ATSFontContainerRef +// corresponding to the *original in-process NSFont* whose loading was blocked +// by the sandbox. +// This is needed to allow lookup of a pre-existing MemoryActivatedFont when +// creating a new FontPlatformData object. +// +// Assumptions: +// This code assumes that an ATSFontRef is a unique identifier tied to an +// activated font. i.e. After we activate a font, its ATSFontRef doesn't +// change. +// It also assumes that the ATSFoncontainerRef for two in-memory NSFonts that +// correspond to the same on-disk font file are always the same and don't change +// with time. +// +// Flushing caches: +// When the system notifies us of a system font cache flush, all FontDataCache +// objects are destroyed. This should in turn dereference all +// MemoryActivatedFonts and thus unload all in-memory fonts. +class MemoryActivatedFont : public RefCounted<MemoryActivatedFont> { +public: + // Use to create a new object, see docs on constructor below. + static PassRefPtr<MemoryActivatedFont> create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container); + ~MemoryActivatedFont(); + + // Get cached CGFontRef corresponding to the in-memory font. + CGFontRef cgFont() { return m_cgFont.get(); } + + // Get cached ATSFontRef corresponding to the in-memory font. + ATSFontRef atsFontRef() { return m_atsFontRef; } + +private: + // srcFontRef - ATSFontRef belonging to the NSFont object that failed to + // load in-process. + // container - a font container corresponding to an identical font that + // we loaded cross-process. + MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container); + + ATSFontContainerRef m_fontContainer; + WTF::RetainPtr<CGFontRef> m_cgFont; + ATSFontRef m_atsFontRef; + ATSFontContainerRef m_srcFontContainerRef; +}; + +} // namespace WebCore + +#endif // CrossProcessFontLoading_h diff --git a/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm new file mode 100644 index 0000000..a7ec03a --- /dev/null +++ b/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm @@ -0,0 +1,217 @@ +/* + * This file is part of the internal font implementation. + * + * Copyright (c) 2010 Google Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * 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. + * + */ + +// This file provides additional functionality to the Mac FontPlatformData class +// defined in WebCore/platform/cocoa/FontPlatformDataCocoa.mm . +// Because we want to support loading fonts between processes in the face of +// font loading being blocked by the sandbox, we need a mechnasim to both +// do the loading of in-memory fonts and keep track of them. + +#import "config.h" +#import "CrossProcessFontLoading.h" + +#import "../graphics/cocoa/FontPlatformData.h" +#import "ChromiumBridge.h" +#import <AppKit/NSFont.h> +#import <wtf/HashMap.h> + +namespace WebCore { + +namespace { + +typedef HashMap<ATSFontContainerRef, MemoryActivatedFont*> FontContainerRefMemoryFontHash; + +// On 10.5, font loading is not blocked by the sandbox and thus there is no +// need for the cross-process font loading mechanim. +// On system versions >=10.6 cross-process font loading is required. +bool OutOfProcessFontLoadingEnabled() +{ + static SInt32 systemVersion = 0; + if (!systemVersion) { + if (Gestalt(gestaltSystemVersion, &systemVersion) != noErr) + return false; + } + + return systemVersion >= 0x1060; +} + +FontContainerRefMemoryFontHash& fontCacheBySrcFontContainerRef() +{ + DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontRefCache, ()); + return srcFontRefCache; +} + +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) +{ + NSString* fontName = (NSString*)CGFontCopyPostScriptName(cgFont); + return [fontName isEqualToString:@"LastResort"]; +} + +// Given an in-process font which has failed to load, return a +// MemoryActivatedFont* corresponding to an in-memory representation of the +// same font loaded from the browser process. +// On failure this function returns a PassRefPtr pointing to 0. +PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont) +{ + ATSFontContainerRef container; + // Send cross-process request to load font. + if (!ChromiumBridge::loadFont(nsFont, &container)) + return 0; + + ATSFontContainerRef srcFontContainerRef = fontContainerRefFromNSFont(nsFont); + if (!srcFontContainerRef) { + ATSFontDeactivate(container, 0, kATSOptionFlagsDefault); + return 0; + } + + PassRefPtr<MemoryActivatedFont> font = adoptRef(fontCacheBySrcFontContainerRef().get(srcFontContainerRef)); + if (font.get()) + return font; + + return MemoryActivatedFont::create(srcFontContainerRef, container); +} + +} // namespace + +PassRefPtr<MemoryActivatedFont> MemoryActivatedFont::create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container) +{ + MemoryActivatedFont* font = new MemoryActivatedFont(srcFontContainerRef, container); + if (!font->cgFont()) // Object construction failed. + { + delete font; + return 0; + } + return adoptRef(font); +} + +MemoryActivatedFont::MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container) + : m_fontContainer(container) + , m_atsFontRef(kATSFontRefUnspecified) + , m_srcFontContainerRef(srcFontContainerRef) +{ + if (!container) + return; + + // Count the number of fonts in the container. + ItemCount fontCount = 0; + OSStatus err = ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0, 0, &fontCount); + if (err != noErr || fontCount < 1) + return; + + // For now always assume that we want the first font in the container. + ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 1, &m_atsFontRef, 0); + + if (!m_atsFontRef) + return; + + // Cache CGFont representation of the font. + m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&m_atsFontRef)); + + if (!m_cgFont.get()) + return; + + // Add ourselves to cache. + fontCacheBySrcFontContainerRef().add(m_srcFontContainerRef, this); +} + +// Destructor - Unload font container from memory and remove ourselves +// from cache. +MemoryActivatedFont::~MemoryActivatedFont() +{ + if (m_cgFont.get()) { + // First remove ourselves from the caches. + ASSERT(fontCacheBySrcFontContainerRef().contains(m_srcFontContainerRef)); + + fontCacheBySrcFontContainerRef().remove(m_srcFontContainerRef); + + // Make sure the CGFont is destroyed before its font container. + m_cgFont.releaseRef(); + } + + if (m_fontContainer != kATSFontContainerRefUnspecified) + ATSFontDeactivate(m_fontContainer, 0, kATSOptionFlagsDefault); +} + +// Given an NSFont, try to load a representation of that font into the cgFont +// parameter. If loading is blocked by the sandbox, the font may be loaded +// cross-process. +// If sandbox loading also fails, a fallback font is loaded. +// +// Considerations: +// * cgFont must be CFRelease()ed by the caller when done. +// +// Parameters: +// * nsFont - The font we wish to load. +// * fontSize - point size of the font we wish to load. +// * outNSFont - The font that was actually loaded, may be different from nsFont +// if a fallback font was used. +// * cgFont - on output this contains the CGFontRef corresponding to the NSFont +// that was picked in the end. The caller is responsible for calling +// CFRelease() on this parameter when done with it. +// * fontID - on output, the ID corresponding to nsFont. +void FontPlatformData::loadFont(NSFont* nsFont, float fontSize, NSFont*& outNSFont, CGFontRef& cgFont, ATSUFontID& fontID) +{ + outNSFont = nsFont; + cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); + MemoryActivatedFont* memFont = 0; + if (OutOfProcessFontLoadingEnabled() && outNSFont && cgFont && isLastResortFont(cgFont)) { + // Release old CGFontRef since it points at the LastResort font which we don't want. + CFRelease(cgFont); + cgFont = 0; + + // Font loading was blocked by the Sandbox. + m_inMemoryFont = loadFontFromBrowserProcess(outNSFont); + if (m_inMemoryFont.get()) { + cgFont = m_inMemoryFont->cgFont(); + + // Need to add an extra retain so output semantics of this function + // are consistent. + CFRetain(cgFont); + } else { + // If we still can't load the font, then return Times, + // rather than the LastResort font. + outNSFont = [NSFont fontWithName:@"Times" size:fontSize]; + cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); + } + } + + if (memFont) { + fontID = m_inMemoryFont->atsFontRef(); + } else { + fontID = CTFontGetPlatformFont(toCTFontRef(outNSFont), 0); + } +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp index 5b8bad3..78b7517 100644 --- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp @@ -273,10 +273,10 @@ bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs, // If there is a non-blur shadow and both the fill color and shadow color // are opaque, handle without skia. - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - if (m_graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor)) { + if (m_graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor)) { // If there is a shadow and this code is reached, windowsCanHandleDrawTextShadow() // will have already returned true during the ctor initiatization of m_useGDI ASSERT(shadowColor.alpha() == 255); @@ -285,7 +285,7 @@ bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs, COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue())); COLORREF savedTextColor = GetTextColor(m_hdc); SetTextColor(m_hdc, textColor); - ExtTextOut(m_hdc, x + shadowSize.width(), y + shadowSize.height(), ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]); + ExtTextOut(m_hdc, x + shadowOffset.width(), y + shadowOffset.height(), ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]); SetTextColor(m_hdc, savedTextColor); } @@ -483,15 +483,15 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, // If there is a non-blur shadow and both the fill color and shadow color // are opaque, handle without skia. - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - if (graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor) && windowsCanHandleDrawTextShadow(graphicsContext)) { + if (graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor) && windowsCanHandleDrawTextShadow(graphicsContext)) { COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue())); COLORREF savedTextColor = GetTextColor(hdc); SetTextColor(hdc, textColor); - state.draw(graphicsContext, hdc, static_cast<int>(point.x()) + shadowSize.width(), - static_cast<int>(point.y() - ascent()) + shadowSize.height(), from, to); + state.draw(graphicsContext, hdc, static_cast<int>(point.x()) + shadowOffset.width(), + static_cast<int>(point.y() - ascent()) + shadowOffset.height(), from, to); SetTextColor(hdc, savedTextColor); } diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumMac.mm b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumMac.mm deleted file mode 100644 index ad7ebba..0000000 --- a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumMac.mm +++ /dev/null @@ -1,458 +0,0 @@ -/* - * This file is part of the internal font implementation. - * - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (c) 2010 Google Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * 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. - * - */ - -// This file is a clone of platform/graphics/mac/FontPlatformDataMac.mm. -// Because we want to support loading fonts between processes in the face of -// font loading being blocked by the sandbox, we must maintain a fork. -// Please maintain this file by performing parallel changes to it. -// -// The only changes from FontPlatformDataMac should be: -// - The functions at the top of this file for loading and caching fonts -// cross-process. -// - Changes to FontPlatformData::FontPlatformData(NSFont,bool,bool) -// - Changes to FontPlatformData::setFont() -// - Changes to FontPlatformData::~FontPlatformData() -// - Calls to refMemoryFont() in FontPlatformData::operator= and copy -// constructor. -// -// All changes are marked with "Start/End Chromium Change" -// -// For all other differences, if it was introduced in this file, then the -// maintainer forgot to include it in the list; otherwise it is an update that -// should have been applied to this file but was not. - - -// Start Chromium Change -#import "config.h" -#import "../graphics/mac/FontPlatformData.h" - -#import "ChromiumBridge.h" -#import "PlatformString.h" -#import "WebCoreSystemInterface.h" -#import <AppKit/NSFont.h> -#import <wtf/HashMap.h> -#import <wtf/RefCounted.h> -#import <wtf/RetainPtr.h> -#import <wtf/Vector.h> - -namespace WebCore { - -namespace { - -class MemoryActivatedFont; -typedef HashMap<ATSFontRef, MemoryActivatedFont*> FontRefMemoryFontHash; -typedef HashMap<ATSFontContainerRef, MemoryActivatedFont*> FontContainerRefMemoryFontHash; - -// On 10.5, font loading is not blocked by the sandbox and thus there is no -// need for the cross-process font loading mechanim. -// On system versions >=10.6 cross-process font loading is required. -bool OutOfProcessFontLoadingEnabled() -{ - static SInt32 systemVersion = 0; - if (!systemVersion) { - if (Gestalt(gestaltSystemVersion, &systemVersion) != noErr) - return false; - } - - return systemVersion >= 0x1060; -} - -FontContainerRefMemoryFontHash& fontCacheBySrcFontContainerRef() -{ - DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontRefCache, ()); - return srcFontRefCache; -} - -FontRefMemoryFontHash& fontCacheByActualFontRef() -{ - DEFINE_STATIC_LOCAL(FontRefMemoryFontHash, realFontRefCache, ()); - return realFontRefCache; -} - -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; -} - -// MemoryActivatedFont encapsulates a font loaded from another process and -// activated from memory. -// -// Responsibilities: -// * Holder for the CGFontRef & ATSFontRef belonging to the activated font. -// * Responsible for unloading the font container when done. -// -// Memory Management: -// The class is reference counted, with each instance of FontPlatformData that -// uses this class holding a reference to it. -// Entries in 2 hashes are maintained internally to allow quick lookup -// of existing instances for reuse: -// - fontCacheBySrcFontContainerRef() - key is the ATSFontContainerRef -// corresponding to the *original in-process NSFont* whose loading was blocked -// by the sandbox. -// This is needed to allow lookup of a pre-existing MemoryActivatedFont when -// creating a new FontPlatformData object. -// - fontCacheByActualFontRef() - key is the ATSFontRef corresponding to the -// *new in-memory font* that we got from the browser process. -// This is needed so that a FontPlatformData object can refer back to the -// MemoryActivatedFont it's using. Currently this is only needed to release -// the font on FontPlatformData destruction. -// -// Assumptions: -// This code assumes that an ATSFontRef is a unique identifier tied to an -// activated font. i.e. After we activate a font, its ATSFontRef doesn't -// change. -// It also assumes that the ATSFoncontainerRef for two in-memory NSFonts that -// correspond to the same on-disk font file are always the same and don't change -// with time. -// -// Flushing caches: -// When the system notifies us of a system font cache flush, all FontDataCache -// objects are destroyed. This should in turn dereference all -// MemoryActivatedFonts and thus unload all in-memory fonts. -class MemoryActivatedFont : public RefCounted<MemoryActivatedFont> { -public: - // srcFontRef - ATSFontRef belonging to the NSFont object that failed to - // load in-process. - // container - a font container corresponding to an identical font that - // we loaded cross-process. - MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container) - : m_fontContainer(container) - , m_atsFontRef(kATSFontRefUnspecified) - , m_srcFontContainerRef(srcFontContainerRef) - { - if (!container) - return; - - // Count the number of fonts in the container. - ItemCount fontCount = 0; - OSStatus err = ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0, 0, &fontCount); - if (err != noErr || fontCount < 1) - return; - - // For now always assume that we want the first font in the container. - ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 1, &m_atsFontRef, 0); - - if (!m_atsFontRef) - return; - - // Cache CGFont representation of the font. - m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&m_atsFontRef)); - - if (!m_cgFont.get()) - return; - - // Add ourselves to caches. - fontCacheBySrcFontContainerRef().add(m_srcFontContainerRef, this); - fontCacheByActualFontRef().add(m_atsFontRef, this); - } - - // Get cached CGFontRef corresponding to the in-memory font. - CGFontRef cgFont() - { - return m_cgFont.get(); - } - - // Get cached ATSFontRef corresponding to the in-memory font. - ATSFontRef atsFontRef() - { - return m_atsFontRef; - } - - // Destructor - Unload font container from memory and remove ourselves - // from hashes. - ~MemoryActivatedFont() - { - if (m_cgFont.get()) { // Object construction succeeded. - // First remove ourselves from the caches. - ASSERT(fontCacheBySrcFontContainerRef().contains(m_srcFontContainerRef)); - ASSERT(fontCacheByActualFontRef().contains(m_atsFontRef)); - - fontCacheBySrcFontContainerRef().remove(m_srcFontContainerRef); - fontCacheByActualFontRef().remove(m_atsFontRef); - - // Make sure the CGFont is destroyed before its font container. - m_cgFont.releaseRef(); - } - - if (m_fontContainer != kATSFontContainerRefUnspecified) - ATSFontDeactivate(m_fontContainer, 0, kATSOptionFlagsDefault); - } - -private: - ATSFontContainerRef m_fontContainer; - WTF::RetainPtr<CGFontRef> m_cgFont; - ATSFontRef m_atsFontRef; - ATSFontContainerRef m_srcFontContainerRef; -}; - -// 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) -{ - NSString* fontName = (NSString*)CGFontCopyPostScriptName(cgFont); - return [fontName isEqualToString:@"LastResort"]; -} - -// Given an in-process font which has failed to load, return a -// MemoryActivatedFont* corresponding to an in-memory representation of the -// same font loaded from the browser process. -// The caller is responsbile for calling derefMemoryFont() on the ATSFontRef -// of the returned font. -// On failure this function returns 0, in which case the caller doesn't need -// to perform any additional cleanup. -MemoryActivatedFont* loadFontFromBrowserProcess(NSFont* nsFont) -{ - ATSFontContainerRef container; - // Send cross-process request to load font. - if (!ChromiumBridge::loadFont(nsFont, &container)) - return 0; - - ATSFontContainerRef srcFontContainerRef = fontContainerRefFromNSFont(nsFont); - if (!srcFontContainerRef) { - ATSFontDeactivate(container, 0, kATSOptionFlagsDefault); - return 0; - } - - MemoryActivatedFont* font = fontCacheBySrcFontContainerRef().get(srcFontContainerRef); - if (!font) { - font = new MemoryActivatedFont(srcFontContainerRef, container); - if (!font->cgFont()) { - delete font; - return 0; - } - } else { - font->ref(); - } - - return font; -} - -// deref() the MemoryActivatedFont corresponding to the given ATSFontRef. If no -// corresponding MemoryActivatedFont object exists, no action is performed. -void derefMemoryFont(ATSFontRef fontRef) -{ - if (fontRef == kATSFontRefUnspecified) - return; - MemoryActivatedFont* font = fontCacheByActualFontRef().get(fontRef); - if (font) - font->deref(); -} - -// ref() the MemoryActivatedFont corresponding to the given ATSFontRef. If no -// corresponding MemoryActivatedFont object exists, no action is performed. -void refMemoryFont(ATSFontRef fontRef) -{ - if (fontRef == kATSFontRefUnspecified) - return; - MemoryActivatedFont* font = fontCacheByActualFontRef().get(fontRef); - if (font) - font->ref(); -} - -// Given an NSFont, try to load a representation of that font into the cgFont -// parameter. If loading is blocked by the sandbox, the font may be loaded -// cross-process. -// If sandbox loading also fails, a fallback font is loaded. -// -// Considerations: -// * cgFont must be CFReleas()ed by the caller when done. -// -// Parameters: -// * nsFont - The font we wish to load. -// * fontSize - point size of the font we wish to load. -// * outNSFont - The font that was actually loaded, may be different from nsFont -// if a fallback font was used. -// * cgFont - on output this contains the CGFontRef corresponding to the NSFont -// that was picked in the end. The caller is responsible for calling -// CFRelease() on this parameter when done with it. -// * fontID - on output, the ID corresponding to nsFont. -void loadFont(NSFont* nsFont, float fontSize, NSFont*& outNSFont, CGFontRef& cgFont, ATSUFontID& fontID) -{ - outNSFont = nsFont; - cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); - MemoryActivatedFont* memFont = 0; - if (OutOfProcessFontLoadingEnabled() && outNSFont && cgFont && isLastResortFont(cgFont)) { - // Release old CGFontRef since it points at the LastResort font which we don't want. - CFRelease(cgFont); - cgFont = 0; - - // Font loading was blocked by the Sandbox. - memFont = loadFontFromBrowserProcess(outNSFont); - if (memFont) { - cgFont = memFont->cgFont(); - - // Need to add an extra retain so output semantics of this function - // are consistent. - CFRetain(cgFont); - } else { - // If we still can't load the font, then return Times, - // rather than the LastResort font. - outNSFont = [NSFont fontWithName:@"Times" size:fontSize]; - cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); - } - } - - if (memFont) { - fontID = memFont->atsFontRef(); - } else { - fontID = CTFontGetPlatformFont(toCTFontRef(outNSFont), 0); - } -} - -} // namespace -// End Chromium Change - -FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool syntheticOblique) - : m_syntheticBold(syntheticBold) - , m_syntheticOblique(syntheticOblique) - , m_font(nsFont) -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) - , m_isColorBitmapFont(CTFontGetSymbolicTraits(toCTFontRef(nsFont)) & kCTFontColorGlyphsTrait) -#else - , m_isColorBitmapFont(false) -#endif -{ -// Start Chromium Change - m_size = nsFont ? [nsFont pointSize] : 0.0f; - CGFontRef cgFont = 0; - NSFont* loadedFont = 0; - loadFont(nsFont, m_size, loadedFont, cgFont, m_atsuFontID); - m_font = loadedFont; - if (m_font) - CFRetain(m_font); - m_cgFont.adoptCF(cgFont); -// End Chromium Change -} - -FontPlatformData::FontPlatformData(const FontPlatformData& f) -{ - m_font = f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1) ? const_cast<NSFont *>(static_cast<const NSFont *>(CFRetain(f.m_font))) : f.m_font; - - m_syntheticBold = f.m_syntheticBold; - m_syntheticOblique = f.m_syntheticOblique; - m_size = f.m_size; - m_cgFont = f.m_cgFont; - m_atsuFontID = f.m_atsuFontID; - m_isColorBitmapFont = f.m_isColorBitmapFont; - // Start Chromium Change - refMemoryFont(m_atsuFontID); - // End Chromium Change -} - -FontPlatformData::~FontPlatformData() -{ - if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) - CFRelease(m_font); - - // Start Chromium Change - derefMemoryFont(m_atsuFontID); - // End Chromium Change -} - -const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f) -{ - m_syntheticBold = f.m_syntheticBold; - m_syntheticOblique = f.m_syntheticOblique; - m_size = f.m_size; - m_cgFont = f.m_cgFont; - m_atsuFontID = f.m_atsuFontID; - if (m_font == f.m_font) - return *this; - if (f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1)) - CFRetain(f.m_font); - if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) - CFRelease(m_font); - m_font = f.m_font; - m_isColorBitmapFont = f.m_isColorBitmapFont; - // Start Chromium Change - refMemoryFont(m_atsuFontID); - // End Chromium Change - return *this; -} - -void FontPlatformData::setFont(NSFont *font) -{ - if (m_font == font) - return; - if (font) - CFRetain(font); - if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) - CFRelease(m_font); - m_font = font; - m_size = font ? [font pointSize] : 0.0f; - - // Start Chromium Change - CGFontRef cgFont = 0; - NSFont* loadedFont = 0; - loadFont(m_font, m_size, loadedFont, cgFont, m_atsuFontID); - - // If loadFont replaced m_font with a fallback font, then release the - // previous font to counter the retain above. Then retain the new font. - if (loadedFont != m_font) { - CFRelease(m_font); - m_font = loadedFont; - CFRetain(m_font); - } - m_cgFont.adoptCF(cgFont); -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) - m_isColorBitmapFont = CTFontGetSymbolicTraits(toCTFontRef(m_font)) & kCTFontColorGlyphsTrait; -#endif - // End Chromium Change -} - -bool FontPlatformData::roundsGlyphAdvances() const -{ - return [m_font renderingMode] == NSFontAntialiasedIntegerAdvancementsRenderingMode; -} - -bool FontPlatformData::allowsLigatures() const -{ - return ![[m_font coveredCharacterSet] characterIsMember:'a']; -} - -#if USE(CORE_TEXT) -CTFontRef FontPlatformData::ctFont() const -{ - if (m_font) - return toCTFontRef(m_font); - if (!m_CTFont) - m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0)); - return m_CTFont.get(); -} -#endif // USE(CORE_TEXT) - -#ifndef NDEBUG -String FontPlatformData::description() const -{ - RetainPtr<CFStringRef> cgFontDescription(AdoptCF, CFCopyDescription(cgFont())); - return String(cgFontDescription.get()) + " " + String::number(m_size) + (m_syntheticBold ? " synthetic bold" : "") + (m_syntheticOblique ? " synthetic oblique" : ""); -} -#endif - -} // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp index c0cb87c..82d4c0b 100644 --- a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp +++ b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp @@ -30,15 +30,15 @@ #include "config.h" -#if USE(GLES2_RENDERING) - #include "GLES2Canvas.h" #include "FloatRect.h" -#include "GLES2Texture.h" #include "GraphicsContext3D.h" #include "IntRect.h" #include "PlatformString.h" +#include "SolidFillShader.h" +#include "TexShader.h" +#include "Texture.h" #define _USE_MATH_DEFINES #include <math.h> @@ -48,19 +48,6 @@ namespace WebCore { -static inline void affineTo3x3(const AffineTransform& transform, float mat[9]) -{ - mat[0] = transform.a(); - mat[1] = transform.b(); - mat[2] = 0.0f; - mat[3] = transform.c(); - mat[4] = transform.d(); - mat[5] = 0.0f; - mat[6] = transform.e(); - mat[7] = transform.f(); - mat[8] = 1.0f; -} - struct GLES2Canvas::State { State() : m_fillColor(0, 0, 0, 255) @@ -76,18 +63,10 @@ struct GLES2Canvas::State { GLES2Canvas::GLES2Canvas(GraphicsContext3D* context, const IntSize& size) : m_context(context) - , m_quadVertices(0) - , m_simpleProgram(0) - , m_texProgram(0) - , m_simpleMatrixLocation(-1) - , m_simpleColorLocation(-1) - , m_simplePositionLocation(-1) - , m_texMatrixLocation(-1) - , m_texTexMatrixLocation(-1) - , m_texSamplerLocation(-1) - , m_texAlphaLocation(-1) - , m_texPositionLocation(-1) , m_state(0) + , m_quadVertices(0) + , m_solidFillShader(SolidFillShader::create(context)) + , m_texShader(TexShader::create(context)) { m_flipMatrix.translate(-1.0f, 1.0f); m_flipMatrix.scale(2.0f / size.width(), -2.0f / size.height()); @@ -105,8 +84,6 @@ GLES2Canvas::GLES2Canvas(GraphicsContext3D* context, const IntSize& size) GLES2Canvas::~GLES2Canvas() { - m_context->deleteProgram(m_simpleProgram); - m_context->deleteProgram(m_texProgram); m_context->deleteBuffer(m_quadVertices); } @@ -131,23 +108,11 @@ void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, getQuadVertices()); - m_context->useProgram(getSimpleProgram()); - - float rgba[4]; - color.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]); - m_context->uniform4f(m_simpleColorLocation, rgba[0] * rgba[3], rgba[1] * rgba[3], rgba[2] * rgba[3], rgba[3]); - AffineTransform matrix(m_flipMatrix); matrix.multLeft(m_state->m_ctm); matrix.translate(rect.x(), rect.y()); matrix.scale(rect.width(), rect.height()); - float mat[9]; - affineTo3x3(matrix, mat); - m_context->uniformMatrix3fv(m_simpleMatrixLocation, false /*transpose*/, mat, 1 /*count*/); - - m_context->vertexAttribPointer(m_simplePositionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); - - m_context->enableVertexAttribArray(m_simplePositionLocation); + m_solidFillShader->use(matrix, color); m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); } @@ -200,49 +165,35 @@ void GLES2Canvas::restore() m_state = &m_stateStack.last(); } -void GLES2Canvas::drawTexturedRect(GLES2Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) +void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) { drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp); } -void GLES2Canvas::drawTexturedRect(GLES2Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp) +void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp) { applyCompositeOperator(compositeOp); m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, getQuadVertices()); checkGLError("glBindBuffer"); - m_context->useProgram(getTexProgram()); - checkGLError("glUseProgram"); - - m_context->activeTexture(GraphicsContext3D::TEXTURE0); - - m_context->uniform1i(m_texSamplerLocation, 0); - checkGLError("glUniform1i"); - - m_context->uniform1f(m_texAlphaLocation, alpha); - checkGLError("glUniform1f for alpha"); - - m_context->vertexAttribPointer(m_texPositionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); - - m_context->enableVertexAttribArray(m_texPositionLocation); - const TilingData& tiles = texture->tiles(); IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect); for (int y = tileIdxRect.y(); y <= tileIdxRect.bottom(); y++) { for (int x = tileIdxRect.x(); x <= tileIdxRect.right(); x++) - drawTexturedRectTile(texture, tiles.tileIndex(x, y), srcRect, dstRect, transform); + drawTexturedRectTile(texture, tiles.tileIndex(x, y), srcRect, dstRect, transform, alpha); } } -void GLES2Canvas::drawTexturedRectTile(GLES2Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform) +void GLES2Canvas::drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) { if (dstRect.isEmpty()) return; const TilingData& tiles = texture->tiles(); + m_context->activeTexture(GraphicsContext3D::TEXTURE0); texture->bindTile(tile); FloatRect srcRectClippedInTileSpace; @@ -255,19 +206,13 @@ void GLES2Canvas::drawTexturedRectTile(GLES2Texture* texture, int tile, const Fl matrix.multLeft(transform); matrix.translate(dstRectIntersected.x(), dstRectIntersected.y()); matrix.scale(dstRectIntersected.width(), dstRectIntersected.height()); - float mat[9]; - affineTo3x3(matrix, mat); - m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, mat, 1 /*count*/); - checkGLError("glUniformMatrix3fv"); AffineTransform texMatrix; texMatrix.scale(1.0f / tileBoundsWithBorder.width(), 1.0f / tileBoundsWithBorder.height()); texMatrix.translate(srcRectClippedInTileSpace.x(), srcRectClippedInTileSpace.y()); texMatrix.scale(srcRectClippedInTileSpace.width(), srcRectClippedInTileSpace.height()); - float texMat[9]; - affineTo3x3(texMatrix, texMat); - m_context->uniformMatrix3fv(m_texTexMatrixLocation, false /*transpose*/, texMat, 1 /*count*/); - checkGLError("glUniformMatrix3fv"); + + m_texShader->use(matrix, texMatrix, 0, alpha); m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); checkGLError("glDrawArrays"); @@ -354,131 +299,21 @@ unsigned GLES2Canvas::getQuadVertices() return m_quadVertices; } - -static unsigned loadShader(GraphicsContext3D* context, unsigned type, const char* shaderSource) +Texture* GLES2Canvas::createTexture(NativeImagePtr ptr, Texture::Format format, int width, int height) { - unsigned shader = context->createShader(type); - if (!shader) - return 0; - - String shaderSourceStr(shaderSource); - context->shaderSource(shader, shaderSourceStr); - context->compileShader(shader); - int compileStatus; - context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compileStatus); - if (!compileStatus) { - String infoLog = context->getShaderInfoLog(shader); - LOG_ERROR(infoLog.utf8().data()); - context->deleteShader(shader); - return 0; - } - return shader; -} - -unsigned GLES2Canvas::getSimpleProgram() -{ - if (!m_simpleProgram) { - unsigned vertexShader = loadShader(m_context, GraphicsContext3D::VERTEX_SHADER, - "uniform mat3 matrix;\n" - "uniform vec4 color;\n" - "attribute vec3 position;\n" - "void main() {\n" - " gl_Position = vec4(matrix * position, 1.0);\n" - "}\n"); - if (!vertexShader) - return 0; - unsigned fragmentShader = loadShader(m_context, GraphicsContext3D::FRAGMENT_SHADER, - "precision mediump float;\n" - "uniform mat3 matrix;\n" - "uniform vec4 color;\n" - "void main() {\n" - " gl_FragColor = color;\n" - "}\n"); - if (!fragmentShader) - return 0; - m_simpleProgram = m_context->createProgram(); - if (!m_simpleProgram) - return 0; - m_context->attachShader(m_simpleProgram, vertexShader); - m_context->attachShader(m_simpleProgram, fragmentShader); - m_context->linkProgram(m_simpleProgram); - int linkStatus; - m_context->getProgramiv(m_simpleProgram, GraphicsContext3D::LINK_STATUS, &linkStatus); - if (!linkStatus) { - m_context->deleteProgram(m_simpleProgram); - m_simpleProgram = 0; - } - m_context->deleteShader(vertexShader); - m_context->deleteShader(fragmentShader); - m_simplePositionLocation = m_context->getAttribLocation(m_simpleProgram, "position"); - m_simpleMatrixLocation = m_context->getUniformLocation(m_simpleProgram, "matrix"); - m_simpleColorLocation = m_context->getUniformLocation(m_simpleProgram, "color"); - } - return m_simpleProgram; -} - -unsigned GLES2Canvas::getTexProgram() -{ - if (!m_texProgram) { - unsigned vertexShader = loadShader(m_context, GraphicsContext3D::VERTEX_SHADER, - "uniform mat3 matrix;\n" - "uniform mat3 texMatrix;\n" - "attribute vec3 position;\n" - "varying vec3 texCoord;\n" - "void main() {\n" - " texCoord = texMatrix * position;\n" - " gl_Position = vec4(matrix * position, 1.0);\n" - "}\n"); - if (!vertexShader) - return 0; - unsigned fragmentShader = loadShader(m_context, GraphicsContext3D::FRAGMENT_SHADER, - "precision mediump float;\n" - "uniform sampler2D sampler;\n" - "uniform float alpha;\n" - "varying vec3 texCoord;\n" - "void main() {\n" - " gl_FragColor = texture2D(sampler, texCoord.xy)* vec4(alpha);\n" - "}\n"); - if (!fragmentShader) - return 0; - m_texProgram = m_context->createProgram(); - if (!m_texProgram) - return 0; - m_context->attachShader(m_texProgram, vertexShader); - m_context->attachShader(m_texProgram, fragmentShader); - m_context->linkProgram(m_texProgram); - int linkStatus; - m_context->getProgramiv(m_texProgram, GraphicsContext3D::LINK_STATUS, &linkStatus); - if (!linkStatus) { - m_context->deleteProgram(m_texProgram); - m_texProgram = 0; - } - m_context->deleteShader(vertexShader); - m_context->deleteShader(fragmentShader); - m_texMatrixLocation = m_context->getUniformLocation(m_texProgram, "matrix"); - m_texSamplerLocation = m_context->getUniformLocation(m_texProgram, "sampler"); - m_texTexMatrixLocation = m_context->getUniformLocation(m_texProgram, "texMatrix"); - m_texPositionLocation = m_context->getAttribLocation(m_texProgram, "position"); - m_texAlphaLocation = m_context->getUniformLocation(m_texProgram, "alpha"); - } - return m_texProgram; -} - -GLES2Texture* GLES2Canvas::createTexture(NativeImagePtr ptr, GLES2Texture::Format format, int width, int height) -{ - PassRefPtr<GLES2Texture> texture = m_textures.get(ptr); + PassRefPtr<Texture> texture = m_textures.get(ptr); if (texture) return texture.get(); - texture = GLES2Texture::create(m_context, format, width, height); - GLES2Texture* t = texture.get(); + texture = Texture::create(m_context, format, width, height); + Texture* t = texture.get(); m_textures.set(ptr, texture); return t; } -GLES2Texture* GLES2Canvas::getTexture(NativeImagePtr ptr) +Texture* GLES2Canvas::getTexture(NativeImagePtr ptr) { - PassRefPtr<GLES2Texture> texture = m_textures.get(ptr); + PassRefPtr<Texture> texture = m_textures.get(ptr); return texture ? texture.get() : 0; } @@ -515,4 +350,3 @@ void GLES2Canvas::checkGLError(const char* header) } -#endif diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.h b/WebCore/platform/graphics/chromium/GLES2Canvas.h index d00510a..f49ac8b 100644 --- a/WebCore/platform/graphics/chromium/GLES2Canvas.h +++ b/WebCore/platform/graphics/chromium/GLES2Canvas.h @@ -31,14 +31,12 @@ #ifndef GLES2Canvas_h #define GLES2Canvas_h -#if USE(GLES2_RENDERING) - #include "AffineTransform.h" #include "Color.h" #include "ColorSpace.h" -#include "GLES2Texture.h" #include "GraphicsTypes.h" #include "ImageSource.h" +#include "Texture.h" #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> @@ -49,8 +47,10 @@ namespace WebCore { class Color; class FloatRect; class GraphicsContext3D; +class SolidFillShader; +class TexShader; -typedef HashMap<NativeImagePtr, RefPtr<GLES2Texture> > TextureHashMap; +typedef HashMap<NativeImagePtr, RefPtr<Texture> > TextureHashMap; class GLES2Canvas : public Noncopyable { public: @@ -74,35 +74,25 @@ public: // non-standard functions // These are not standard GraphicsContext functions, and should be pushed // down into a PlatformContextGLES2 at some point. - void drawTexturedRect(GLES2Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator); - void drawTexturedRect(GLES2Texture*, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator); + void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator); + void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator); GraphicsContext3D* context() { return m_context; } - GLES2Texture* createTexture(NativeImagePtr, GLES2Texture::Format, int width, int height); - GLES2Texture* getTexture(NativeImagePtr); + Texture* createTexture(NativeImagePtr, Texture::Format, int width, int height); + Texture* getTexture(NativeImagePtr); private: - void drawTexturedRectTile(GLES2Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&); + void drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); void applyCompositeOperator(CompositeOperator); void checkGLError(const char* header); unsigned getQuadVertices(); - unsigned getSimpleProgram(); - unsigned getTexProgram(); GraphicsContext3D* m_context; struct State; WTF::Vector<State> m_stateStack; State* m_state; unsigned m_quadVertices; - unsigned m_simpleProgram; - unsigned m_texProgram; - int m_simpleMatrixLocation; - int m_simpleColorLocation; - int m_simplePositionLocation; - int m_texMatrixLocation; - int m_texTexMatrixLocation; - int m_texSamplerLocation; - int m_texAlphaLocation; - int m_texPositionLocation; + OwnPtr<SolidFillShader> m_solidFillShader; + OwnPtr<TexShader> m_texShader; AffineTransform m_flipMatrix; TextureHashMap m_textures; CompositeOperator m_lastCompositeOp; // This is the one last set, not necessarily the one in the state stack. @@ -110,6 +100,4 @@ private: } -#endif - #endif // GLES2Canvas_h diff --git a/WebCore/platform/graphics/chromium/GLES2Texture.cpp b/WebCore/platform/graphics/chromium/GLES2Texture.cpp deleted file mode 100644 index ae230db..0000000 --- a/WebCore/platform/graphics/chromium/GLES2Texture.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if USE(GLES2_RENDERING) - -#include "GLES2Texture.h" - -#include "GraphicsContext3D.h" -#include "IntRect.h" -#include <wtf/OwnArrayPtr.h> - -namespace WebCore { - - -GLES2Texture::GLES2Texture(GraphicsContext3D* context, PassOwnPtr<Vector<unsigned int> > tileTextureIds, Format format, int width, int height, int maxTextureSize) - : m_context(context) - , m_format(format) - , m_tiles(maxTextureSize, width, height, true) - , m_tileTextureIds(tileTextureIds) -{ -} - -GLES2Texture::~GLES2Texture() -{ - for (unsigned int i = 0; i < m_tileTextureIds->size(); i++) - m_context->deleteTexture(m_tileTextureIds->at(i)); -} - -static void convertFormat(GraphicsContext3D* context, GLES2Texture::Format format, unsigned int* glFormat, unsigned int* glType, bool* swizzle) -{ - *swizzle = false; - switch (format) { - case GLES2Texture::RGBA8: - *glFormat = GraphicsContext3D::RGBA; - *glType = GraphicsContext3D::UNSIGNED_BYTE; - break; - case GLES2Texture::BGRA8: - if (context->supportsBGRA()) { - *glFormat = GraphicsContext3D::BGRA_EXT; - *glType = GraphicsContext3D::UNSIGNED_BYTE; - } else { - *glFormat = GraphicsContext3D::RGBA; - *glType = GraphicsContext3D::UNSIGNED_BYTE; - *swizzle = true; - } - break; - default: - ASSERT_NOT_REACHED(); - break; - } -} - -PassRefPtr<GLES2Texture> GLES2Texture::create(GraphicsContext3D* context, Format format, int width, int height) -{ - int maxTextureSize = 0; - context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize); - - TilingData tiling(maxTextureSize, width, height, true); - int numTiles = tiling.numTiles(); - - OwnPtr<Vector<unsigned int> > textureIds(new Vector<unsigned int>(numTiles)); - textureIds->fill(0, numTiles); - - for (int i = 0; i < numTiles; i++) { - int textureId = context->createTexture(); - if (!textureId) { - for (int i = 0; i < numTiles; i++) - context->deleteTexture(textureIds->at(i)); - return 0; - } - textureIds->at(i) = textureId; - - IntRect tileBoundsWithBorder = tiling.tileBoundsWithBorder(i); - - unsigned int glFormat, glType; - bool swizzle; - convertFormat(context, format, &glFormat, &glType, &swizzle); - context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); - context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, glFormat, - tileBoundsWithBorder.width(), - tileBoundsWithBorder.height(), - 0, glFormat, glType, 0); - } - return adoptRef(new GLES2Texture(context, textureIds.leakPtr(), format, width, height, maxTextureSize)); -} - -template <bool swizzle> -static uint32_t* copySubRect(uint32_t* src, int srcX, int srcY, uint32_t* dst, int width, int height, int srcStride) -{ - uint32_t* srcOffset = src + srcX + srcY * srcStride; - - if (!swizzle && width == srcStride) - return srcOffset; - - uint32_t* dstPixel = dst; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width ; x++) { - uint32_t pixel = srcOffset[x + y * srcStride]; - if (swizzle) - *dstPixel = pixel & 0xFF00FF00 | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16); - else - *dstPixel = pixel; - dstPixel++; - } - } - return dst; -} - -void GLES2Texture::load(void* pixels) -{ - uint32_t* pixels32 = static_cast<uint32_t*>(pixels); - unsigned int glFormat, glType; - bool swizzle; - convertFormat(m_context, m_format, &glFormat, &glType, &swizzle); - if (swizzle) { - ASSERT(glFormat == GraphicsContext3D::RGBA && glType == GraphicsContext3D::UNSIGNED_BYTE); - // FIXME: This could use PBO's to save doing an extra copy here. - } - OwnArrayPtr<uint32_t> tempBuff(new uint32_t[m_tiles.maxTextureSize() * m_tiles.maxTextureSize()]); - - for (int i = 0; i < m_tiles.numTiles(); i++) { - IntRect tileBoundsWithBorder = m_tiles.tileBoundsWithBorder(i); - - uint32_t* uploadBuff = 0; - if (swizzle) { - uploadBuff = copySubRect<true>( - pixels32, tileBoundsWithBorder.x(), tileBoundsWithBorder.y(), - tempBuff.get(), tileBoundsWithBorder.width(), tileBoundsWithBorder.height(), m_tiles.totalSizeX()); - } else { - uploadBuff = copySubRect<false>( - pixels32, tileBoundsWithBorder.x(), tileBoundsWithBorder.y(), - tempBuff.get(), tileBoundsWithBorder.width(), tileBoundsWithBorder.height(), m_tiles.totalSizeX()); - } - - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_tileTextureIds->at(i)); - m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, - tileBoundsWithBorder.width(), - tileBoundsWithBorder.height(), glFormat, glType, uploadBuff); - } -} - -void GLES2Texture::bindTile(int tile) -{ - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_tileTextureIds->at(tile)); - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); -} - -} - -#endif diff --git a/WebCore/platform/graphics/chromium/GLES2Texture.h b/WebCore/platform/graphics/chromium/GLES2Texture.h deleted file mode 100644 index 43a4955..0000000 --- a/WebCore/platform/graphics/chromium/GLES2Texture.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GLES2Texture_h -#define GLES2Texture_h - -#if USE(GLES2_RENDERING) - -#include "RefCounted.h" -#include "RefPtr.h" -#include "TilingData.h" -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/Vector.h> - -namespace WebCore { -class GraphicsContext3D; - -class GLES2Texture : public RefCounted<GLES2Texture> { -public: - ~GLES2Texture(); - enum Format { RGBA8, BGRA8 }; - static PassRefPtr<GLES2Texture> create(GraphicsContext3D*, Format, int width, int height); - void bindTile(int tile); - void load(void* pixels); - Format format() const { return m_format; } - const TilingData& tiles() const { return m_tiles; } -private: - GLES2Texture(GraphicsContext3D*, PassOwnPtr<Vector<unsigned int> > tileTextureIds, Format format, int width, int height, int maxTextureSize); - GraphicsContext3D* m_context; - Format m_format; - TilingData m_tiles; - OwnPtr<Vector<unsigned int> > m_tileTextureIds; -}; - -} - -#endif - -#endif // GLES2Texture_h diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index 3553878..6519f1f 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -109,7 +109,7 @@ LayerChromium::SharedValues::SharedValues() "uniform vec4 color; \n" "void main() \n" "{ \n" - " gl_FragColor = color; \n" + " gl_FragColor = vec4(color.xyz * color.w, color.w);\n" "} \n"; m_borderShaderProgram = createShaderProgram(borderVertexShaderString, borderFragmentShaderString); @@ -431,6 +431,37 @@ void LayerChromium::drawDebugBorder() GLC(glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, (void*)(6 * sizeof(unsigned short)))); } +const FloatRect LayerChromium::getDrawRect() const +{ + // Form the matrix used by the shader to map the corners of the layer's + // bounds into the view space. + TransformationMatrix renderMatrix = drawTransform(); + renderMatrix.scale3d(bounds().width(), bounds().height(), 1); + + FloatRect layerRect(-0.5, -0.5, 1, 1); + FloatRect mappedRect = renderMatrix.mapRect(layerRect); + return mappedRect; +} + +// Draws the layer with a single colored shader. This method is used to do +// quick draws into the stencil buffer. +void LayerChromium::drawAsMask() +{ + ASSERT(layerRenderer()); + const SharedValues* sv = layerRenderer()->layerSharedValues(); + ASSERT(sv && sv->initialized()); + layerRenderer()->useShader(sv->borderShaderProgram()); + + // We reuse the border shader here as all we need a single colored shader pass. + // The color specified here is only for debug puproses as typically when we call this + // method, writes to the color channels are disabled. + GLC(glUniform4f(sv->borderShaderColorLocation(), 0, 1 , 0, 0.7)); + + drawTexturedQuad(layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + sv->borderShaderMatrixLocation(), -1); +} + // static void LayerChromium::prepareForDraw(const SharedValues* sv) { diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index 0d0d362..ba15088 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -151,6 +151,9 @@ public: bool contentsDirty() { return m_contentsDirty; } + // Returns the rect containtaining this layer in the current view's coordinate system. + const FloatRect getDrawRect() const; + // These methods typically need to be overwritten by derived classes. virtual bool drawsContent() { return false; } virtual void updateContents() { }; @@ -158,6 +161,9 @@ public: void drawDebugBorder(); + // Draws the layer without a texture. This is used for stencil operations. + void drawAsMask(); + // Stores values that are shared between instances of this class that are // associated with the same LayerRendererChromium (and hence the same GL // context). diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index cf23871..50338d2 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -183,9 +183,11 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& // Bind the common vertex attributes used for drawing all the layers. LayerChromium::prepareForDraw(layerSharedValues()); + // FIXME: These calls can be made once, when the compositor context is initialized. GLC(glDisable(GL_DEPTH_TEST)); GLC(glDisable(GL_CULL_FACE)); GLC(glDepthFunc(GL_LEQUAL)); + GLC(glClearStencil(0)); if (m_scrollPosition == IntPoint(-1, -1)) m_scrollPosition = scrollPosition; @@ -299,14 +301,23 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& for (i = 0; i < sublayers.size(); i++) updateLayersRecursive(sublayers[i].get(), matrix, opacity); + m_rootVisibleRect = visibleRect; + // Enable scissoring to avoid rendering composited layers over the scrollbars. GLC(glEnable(GL_SCISSOR_TEST)); - GLC(glScissor(0, visibleRect.height() - contentRect.height(), contentRect.width(), contentRect.height())); + FloatRect scissorRect(contentRect); + // The scissorRect should not include the scroll offset. + scissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y()); + scissorToRect(scissorRect); + + // Clear the stencil buffer to 0. + GLC(glClear(GL_STENCIL_BUFFER_BIT)); + // Disable writes to the stencil buffer. + GLC(glStencilMask(0)); // Traverse the layer tree one more time to draw the layers. - m_visibleRect = visibleRect; for (i = 0; i < sublayers.size(); i++) - drawLayersRecursive(sublayers[i].get()); + drawLayersRecursive(sublayers[i].get(), scissorRect); GLC(glDisable(GL_SCISSOR_TEST)); @@ -419,13 +430,35 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr layer->setLayerRenderer(this); } +// Does a quick draw of the given layer into the stencil buffer. If decrement +// is true then it decrements the current stencil values otherwise it increments them. +void LayerRendererChromium::drawLayerIntoStencilBuffer(LayerChromium* layer, bool decrement) +{ + // Enable writes to the stencil buffer and increment the stencil values + // by one for every pixel under the current layer. + GLC(glStencilMask(0xff)); + GLC(glStencilFunc(GL_ALWAYS, 1, 0xff)); + GLenum stencilOp = (decrement ? GL_DECR : GL_INCR); + GLC(glStencilOp(stencilOp, stencilOp, stencilOp)); + + GLC(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)); + + layer->drawAsMask(); + + // Disable writes to the stencil buffer. + GLC(glStencilMask(0)); + GLC(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)); +} + // Recursively walk the layer tree and draw the layers. -void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer) +void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const FloatRect& scissorRect) { static bool depthTestEnabledForSubtree = false; + static int currentStencilValue = 0; // Check if the layer falls within the visible bounds of the page. - bool layerVisible = isLayerVisible(layer, layer->drawTransform(), m_visibleRect); + FloatRect layerRect = layer->getDrawRect(); + bool isLayerVisible = scissorRect.intersects(layerRect); // Enable depth testing for this layer and all its descendants if preserves3D is set. bool mustClearDepth = false; @@ -439,9 +472,50 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer) } } - if (layerVisible) + if (isLayerVisible) drawLayer(layer); + // FIXME: We should check here if the layer has descendants that draw content + // before we setup for clipping. + FloatRect currentScissorRect = scissorRect; + bool mustResetScissorRect = false; + bool didStencilDraw = false; + if (layer->masksToBounds()) { + // If the layer isn't rotated then we can use scissoring otherwise we need + // to clip using the stencil buffer. + if (layer->drawTransform().isIdentityOrTranslation()) { + currentScissorRect.intersect(layerRect); + if (currentScissorRect != scissorRect) { + scissorToRect(currentScissorRect); + mustResetScissorRect = true; + } + } else if (currentStencilValue < ((1 << m_numStencilBits) - 1)) { + // Clipping using the stencil buffer works as follows: When we encounter + // a clipping layer we increment the stencil buffer values for all the pixels + // the layer touches. As a result 1's will be stored in the stencil buffer for pixels under + // the first clipping layer found in a traversal, 2's for pixels in the intersection + // of two nested clipping layers, etc. When the sublayers of a clipping layer are drawn + // we turn on stencil testing to render only pixels that have the correct stencil + // value (one that matches the value of currentStencilValue). As the recursion unravels, + // we decrement the stencil buffer values for each clipping layer. When the entire layer tree + // is rendered, the stencil values should be all back to zero. An 8 bit stencil buffer + // will allow us up to 255 nested clipping layers which is hopefully enough. + if (!currentStencilValue) + GLC(glEnable(GL_STENCIL_TEST)); + + drawLayerIntoStencilBuffer(layer, false); + + currentStencilValue++; + didStencilDraw = true; + } + } + // Sublayers will render only if the value in the stencil buffer is equal to + // currentStencilValue. + if (didStencilDraw) { + // The sublayers will render only if the stencil test passes. + GLC(glStencilFunc(GL_EQUAL, currentStencilValue, 0xff)); + } + // If we're using depth testing then we need to sort the children in Z to // get the transparency to work properly. if (depthTestEnabledForSubtree) { @@ -456,11 +530,27 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer) std::stable_sort(sublayerList.begin(), sublayerList.end(), compareLayerZ); for (i = 0; i < sublayerList.size(); i++) - drawLayersRecursive(sublayerList[i]); + drawLayersRecursive(sublayerList[i], currentScissorRect); } else { const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); for (size_t i = 0; i < sublayers.size(); i++) - drawLayersRecursive(sublayers[i].get()); + drawLayersRecursive(sublayers[i].get(), currentScissorRect); + } + + if (didStencilDraw) { + // Draw into the stencil buffer subtracting 1 for every pixel hit + // effectively removing this mask + drawLayerIntoStencilBuffer(layer, true); + currentStencilValue--; + if (!currentStencilValue) { + // Disable stencil testing. + GLC(glDisable(GL_STENCIL_TEST)); + GLC(glStencilFunc(GL_ALWAYS, 0, 0xff)); + } + } + + if (mustResetScissorRect) { + scissorToRect(scissorRect); } if (mustClearDepth) { @@ -494,6 +584,15 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer) layer->drawDebugBorder(); } +// Sets the scissor region to the given rectangle. The coordinate system for the +// scissorRect has its origin at the top left corner of the current visible rect. +void LayerRendererChromium::scissorToRect(const FloatRect& scissorRect) +{ + // Compute the lower left corner of the scissor rect. + float bottom = std::max((float)m_rootVisibleRect.height() - scissorRect.bottom(), 0.f); + GLC(glScissor(scissorRect.x(), bottom, scissorRect.width(), scissorRect.height())); +} + bool LayerRendererChromium::makeContextCurrent() { return m_gles2Context->makeCurrent(); @@ -565,6 +664,9 @@ bool LayerRendererChromium::initializeSharedObjects() // Get the max texture size supported by the system. GLC(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize)); + // Get the number of bits available in the stencil buffer. + GLC(glGetIntegerv(GL_STENCIL_BITS, &m_numStencilBits)); + m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues()); m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues()); m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues()); diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h index 24bbe65..8f44afe 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -93,12 +93,16 @@ public: private: void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity); - void drawLayersRecursive(LayerChromium*); + void drawLayersRecursive(LayerChromium*, const FloatRect& scissorRect); void drawLayer(LayerChromium*); bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect); + void drawLayerIntoStencilBuffer(LayerChromium*, bool decrement); + + void scissorToRect(const FloatRect&); + bool makeContextCurrent(); bool initializeSharedObjects(); @@ -135,10 +139,12 @@ private: IntSize m_rootLayerCanvasSize; - IntRect m_visibleRect; + IntRect m_rootVisibleRect; int m_maxTextureSize; + int m_numStencilBits; + // Store values that are shared between instances of each layer type // associated with this instance of the compositor. Since there can be // multiple instances of the compositor running in the same renderer process diff --git a/WebCore/platform/graphics/chromium/TilingData.cpp b/WebCore/platform/graphics/chromium/TilingData.cpp deleted file mode 100755 index 4da242b..0000000 --- a/WebCore/platform/graphics/chromium/TilingData.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "TilingData.h" - -#include "FloatRect.h" -#include "IntRect.h" -#include <algorithm> - -using namespace std; - -namespace WebCore { - -static int computeNumTiles(int maxTextureSize, int totalSize, int borderTexels) -{ - return max(1, 1 + (totalSize - 1 - 2 * borderTexels) / (maxTextureSize - 2 * borderTexels)); -} - -TilingData::TilingData(int maxTextureSize, int totalSizeX, int totalSizeY, bool hasBorderTexels) - : m_maxTextureSize(maxTextureSize) - , m_totalSizeX(totalSizeX) - , m_totalSizeY(totalSizeY) - , m_borderTexels(hasBorderTexels ? 1 : 0) -{ - m_numTilesX = computeNumTiles(maxTextureSize, m_totalSizeX, m_borderTexels); - m_numTilesY = computeNumTiles(maxTextureSize, m_totalSizeY, m_borderTexels); -} - -int TilingData::tileXIndexFromSrcCoord(int srcPos) const -{ - int x = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels); - return min(max(x, 0), numTilesX() - 1); -} - -int TilingData::tileYIndexFromSrcCoord(int srcPos) const -{ - int y = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels); - return min(max(y, 0), numTilesY() - 1); -} - -IntRect TilingData::tileBounds(int tile) const -{ - assertTile(tile); - int ix = tileXIndex(tile); - int iy = tileYIndex(tile); - int x = tilePositionX(ix); - int y = tilePositionY(iy); - int width = tileSizeX(ix); - int height = tileSizeY(iy); - ASSERT(x >= 0 && y >= 0 && width >= 0 && height >= 0); - ASSERT(x <= totalSizeX() && y <= totalSizeY()); - return IntRect(x, y, width, height); -} - -IntRect TilingData::tileBoundsWithBorder(int tile) const -{ - IntRect bounds = tileBounds(tile); - - if (m_borderTexels) { - int x1 = bounds.x(); - int x2 = bounds.right(); - int y1 = bounds.y(); - int y2 = bounds.bottom(); - - if (tileXIndex(tile) > 0) - x1--; - if (tileXIndex(tile) < (numTilesX() - 1)) - x2++; - if (tileYIndex(tile) > 0) - y1--; - if (tileYIndex(tile) < (numTilesY() - 1)) - y2++; - - bounds = IntRect(x1, y1, x2 - x1, y2 - y1); - } - - return bounds; -} - -FloatRect TilingData::tileBoundsNormalized(int tile) const -{ - assertTile(tile); - FloatRect bounds(tileBounds(tile)); - bounds.scale(1.0f / m_totalSizeX, 1.0f / m_totalSizeY); - return bounds; -} - -int TilingData::tilePositionX(int xIndex) const -{ - ASSERT(xIndex >= 0 && xIndex < numTilesX()); - - int pos = 0; - for (int i = 0; i < xIndex; i++) - pos += tileSizeX(i); - - return pos; -} - -int TilingData::tilePositionY(int yIndex) const -{ - ASSERT(yIndex >= 0 && yIndex < numTilesY()); - - int pos = 0; - for (int i = 0; i < yIndex; i++) - pos += tileSizeY(i); - - return pos; -} - -int TilingData::tileSizeX(int xIndex) const -{ - ASSERT(xIndex >= 0 && xIndex < numTilesX()); - - int size = maxTextureSize(); - size = min(size, totalSizeX()); - - if (!xIndex && m_numTilesX == 1) - return m_totalSizeX; - if (!xIndex && m_numTilesX > 1) - return m_maxTextureSize - m_borderTexels; - if (xIndex < numTilesX() - 1) - return m_maxTextureSize - 2 * m_borderTexels; - if (xIndex == numTilesX() - 1) - return m_totalSizeX - tilePositionX(xIndex); - - ASSERT_NOT_REACHED(); - return 0; -} - -int TilingData::tileSizeY(int yIndex) const -{ - ASSERT(yIndex >= 0 && yIndex < numTilesY()); - - int size = maxTextureSize(); - size = min(size, totalSizeY()); - - if (!yIndex && m_numTilesY == 1) - return m_totalSizeY; - if (!yIndex && m_numTilesY > 1) - return m_maxTextureSize - m_borderTexels; - if (yIndex < numTilesY() - 1) - return m_maxTextureSize - 2 * m_borderTexels; - if (yIndex == numTilesY() - 1) - return m_totalSizeY - tilePositionY(yIndex); - - ASSERT_NOT_REACHED(); - return 0; -} - -IntRect TilingData::overlappedTileIndices(const WebCore::IntRect &srcRect) const -{ - int x = tileXIndexFromSrcCoord(srcRect.x()); - int y = tileYIndexFromSrcCoord(srcRect.y()); - int r = tileXIndexFromSrcCoord(srcRect.right()); - int b = tileYIndexFromSrcCoord(srcRect.bottom()); - return IntRect(x, y, r - x, b - y); -} - -IntRect TilingData::overlappedTileIndices(const WebCore::FloatRect &srcRect) const -{ - return overlappedTileIndices(enclosingIntRect(srcRect)); -} - -void TilingData::intersectDrawQuad(const FloatRect& srcRect, const FloatRect& dstRect, int tile, - FloatRect* newSrc, FloatRect* newDst) const -{ - // Intersect with tile - FloatRect tileBounds = this->tileBounds(tile); - FloatRect srcRectIntersected = srcRect; - srcRectIntersected.intersect(tileBounds); - - if (srcRectIntersected.isEmpty()) { - *newSrc = *newDst = FloatRect(0, 0, 0, 0); - return; - } - - float srcRectIntersectedNormX = (srcRectIntersected.x() - srcRect.x()) / srcRect.width(); - float srcRectIntersectedNormY = (srcRectIntersected.y() - srcRect.y()) / srcRect.height(); - float srcRectIntersectedNormW = srcRectIntersected.width() / srcRect.width(); - float srcRectIntersectedNormH = srcRectIntersected.height() / srcRect.height(); - - *newSrc = srcRectIntersected; - newSrc->move( - -tileBounds.x() + ((tileXIndex(tile) > 0) ? m_borderTexels : 0), - -tileBounds.y() + ((tileYIndex(tile) > 0) ? m_borderTexels : 0)); - - *newDst = FloatRect( - srcRectIntersectedNormX * dstRect.width() + dstRect.x(), - srcRectIntersectedNormY * dstRect.height() + dstRect.y(), - srcRectIntersectedNormW * dstRect.width(), - srcRectIntersectedNormH * dstRect.height()); -} - -} diff --git a/WebCore/platform/graphics/chromium/TilingData.h b/WebCore/platform/graphics/chromium/TilingData.h deleted file mode 100755 index f12e66e..0000000 --- a/WebCore/platform/graphics/chromium/TilingData.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TilingData_h -#define TilingData_h - -#include <wtf/Noncopyable.h> - -namespace WebCore { - -class FloatRect; -class IntRect; - -class TilingData : public Noncopyable { -public: - TilingData(int maxTextureSize, int totalSizeX, int totalSizeY, bool hasBorderTexels); - int maxTextureSize() const { return m_maxTextureSize; } - int totalSizeX() const { return m_totalSizeX; } - int totalSizeY() const { return m_totalSizeY; } - - int numTiles() const { return numTilesX() * numTilesY(); } - int numTilesX() const { return m_numTilesX; } - int numTilesY() const { return m_numTilesY; } - int tileIndex(int x, int y) const { return x + y * numTilesX(); } - int tileXIndex(int tile) const { assertTile(tile); return tile % numTilesX(); } - int tileYIndex(int tile) const { assertTile(tile); return tile / numTilesX(); } - int tileXIndexFromSrcCoord(int) const; - int tileYIndexFromSrcCoord(int) const; - - IntRect tileBounds(int tile) const; - IntRect tileBoundsWithBorder(int tile) const; - FloatRect tileBoundsNormalized(int tile) const; - int tilePositionX(int xIndex) const; - int tilePositionY(int yIndex) const; - int tileSizeX(int xIndex) const; - int tileSizeY(int yIndex) const; - IntRect overlappedTileIndices(const IntRect& srcRect) const; - IntRect overlappedTileIndices(const FloatRect& srcRect) const; - - // Given a set of source and destination coordinates for a drawing quad - // in texel units, returns adjusted data to render just the one tile. - void intersectDrawQuad(const FloatRect& srcRect, const FloatRect& dstRect, int tile, FloatRect* newSrc, FloatRect* newDst) const; - -private: - TilingData() : m_maxTextureSize(0), m_totalSizeX(0), m_totalSizeY(0) {} - void assertTile(int tile) const { ASSERT(tile >= 0 && tile < numTiles()); } - - int m_maxTextureSize; - int m_totalSizeX; - int m_totalSizeY; - int m_borderTexels; // 0 or 1 - - // computed values: - int m_numTilesX; - int m_numTilesY; -}; - -} - -#endif // TilingData_h |