diff options
author | Ben Murdoch <benm@google.com> | 2011-05-16 16:25:10 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-05-23 18:54:14 +0100 |
commit | ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb (patch) | |
tree | db769fadd053248f85db67434a5b275224defef7 /Source/WebCore/platform/graphics/chromium | |
parent | 52e2557aeb8477967e97fd24f20f8f407a10fa15 (diff) | |
download | external_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.zip external_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.tar.gz external_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.tar.bz2 |
Merge WebKit at r76408: Initial merge by git.
Change-Id: I5b91decbd693ccbf5c1b8354b37cd68cc9a1ea53
Diffstat (limited to 'Source/WebCore/platform/graphics/chromium')
26 files changed, 501 insertions, 181 deletions
diff --git a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp index 99159e6..92861fc 100644 --- a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp @@ -32,6 +32,7 @@ #include "ComplexTextControllerLinux.h" #include "Font.h" +#include "TextRun.h" #include <unicode/normlzr.h> @@ -47,8 +48,6 @@ static int truncateFixedPointToInteger(HB_Fixed value) ComplexTextController::ComplexTextController(const TextRun& run, unsigned startingX, const Font* font) : m_font(font) - , m_startingX(startingX) - , m_offsetX(m_startingX) , m_run(getNormalizedTextRun(run, m_normalizedRun, m_normalizedBuffer)) , m_wordSpacingAdjustment(0) , m_padding(0) @@ -75,7 +74,7 @@ ComplexTextController::ComplexTextController(const TextRun& run, unsigned starti m_item.string = m_run.characters(); m_item.stringLength = m_run.length(); - reset(); + reset(startingX); } ComplexTextController::~ComplexTextController() @@ -137,10 +136,10 @@ void ComplexTextController::setPadding(int padding) m_padPerWordBreak = 0; } -void ComplexTextController::reset() +void ComplexTextController::reset(unsigned offset) { m_indexOfNextScriptRun = 0; - m_offsetX = m_startingX; + m_offsetX = offset; } // Advance to the next script run, returning false when the end of the @@ -277,8 +276,7 @@ void ComplexTextController::setGlyphXPositions(bool isRTL) int logClustersIndex = 0; // Iterate through the glyphs in logical order, flipping for RTL where necessary. - // In RTL mode all variables are positive except m_xPositions, which starts from m_offsetX and runs negative. - // It is fixed up in a second pass below. + // Glyphs are positioned starting from m_offsetX; in RTL mode they go leftwards from there. for (size_t i = 0; i < m_item.num_glyphs; ++i) { while (static_cast<unsigned>(logClustersIndex) < m_item.item.length && logClusters()[logClustersIndex] < i) logClustersIndex++; @@ -303,16 +301,8 @@ void ComplexTextController::setGlyphXPositions(bool isRTL) position += advance; } - const double width = position; - - // Now that we've computed the total width, do another pass to fix positioning for RTL. - if (isRTL) { - for (size_t i = 0; i < m_item.num_glyphs; ++i) - m_xPositions[i] += width; - } - - m_pixelWidth = std::max(width, 0.0); - m_offsetX += m_pixelWidth; + m_pixelWidth = std::max(position, 0.0); + m_offsetX += m_pixelWidth * rtlFlip; } void ComplexTextController::normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, UChar* destination, int length) diff --git a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h index e264b99..a2aea60 100644 --- a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h +++ b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h @@ -68,7 +68,7 @@ public: // setPadding sets a number of pixels to be distributed across the TextRun. // WebKit uses this to justify text. void setPadding(int); - void reset(); + void reset(unsigned offset); // Advance to the next script run, returning false when the end of the // TextRun has been reached. bool nextScriptRun(); @@ -86,7 +86,6 @@ public: // Set the x offset for the next script run. This affects the values in // |xPositions| - void setXOffsetToZero() { m_offsetX = 0; } bool rtl() const { return m_run.rtl(); } const uint16_t* glyphs() const { return m_glyphs16; } @@ -114,6 +113,9 @@ public: // return the number of code points in the current script run const unsigned numCodePoints() const { return m_numCodePoints; } + // Return the current pixel position of the controller. + const unsigned offsetX() const { return m_offsetX; } + const FontPlatformData* fontPlatformDataForScriptRun() { return reinterpret_cast<FontPlatformData*>(m_item.font->userData); } private: @@ -137,7 +139,6 @@ private: uint16_t* m_glyphs16; // A vector of 16-bit glyph ids. SkScalar* m_xPositions; // A vector of x positions for each glyph. ssize_t m_indexOfNextScriptRun; // Indexes the script run in |m_run|. - const unsigned m_startingX; // Offset in pixels of the first script run. unsigned m_offsetX; // Offset in pixels to the start of the next script run. unsigned m_pixelWidth; // Width (in px) of the current script run. unsigned m_numCodePoints; // Code points in current script run. diff --git a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm index 72e3369..227fbe4 100644 --- a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm +++ b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm @@ -30,7 +30,7 @@ #import "CrossProcessFontLoading.h" #import "../graphics/cocoa/FontPlatformData.h" -#import "ChromiumBridge.h" +#import "PlatformBridge.h" #import <AppKit/NSFont.h> #import <wtf/HashMap.h> @@ -87,7 +87,7 @@ PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont) { ATSFontContainerRef container; // Send cross-process request to load font. - if (!ChromiumBridge::loadFont(nsFont, &container)) + if (!PlatformBridge::loadFont(nsFont, &container)) return 0; ATSFontContainerRef srcFontContainerRef = fontContainerRefFromNSFont(nsFont); diff --git a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp index 569dff4..2d4ca41 100644 --- a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp @@ -72,15 +72,16 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, bool multisampleExtensionSupported, bool packedDepthStencilExtensionSupported) : m_context(context) - , m_size(size) + , m_size(-1, -1) , m_multisampleExtensionSupported(multisampleExtensionSupported) , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported) , m_fbo(0) , m_colorBuffer(0) , m_depthStencilBuffer(0) + , m_depthBuffer(0) + , m_stencilBuffer(0) , m_multisampleFBO(0) , m_multisampleColorBuffer(0) - , m_multisampleDepthStencilBuffer(0) , m_internal(new DrawingBufferInternal) { if (!m_context->getExtensions()->supports("GL_CHROMIUM_copy_texture_to_parent_texture")) { @@ -91,6 +92,7 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_colorBuffer = generateColorTexture(context, size); createSecondaryBuffers(); + reset(size); } DrawingBuffer::~DrawingBuffer() diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp index 2c79815..f4c0dee 100644 --- a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp @@ -32,11 +32,11 @@ #include "config.h" #include "FontCache.h" -#include "ChromiumBridge.h" #include "Font.h" #include "FontUtilsChromiumWin.h" #include "HashMap.h" #include "HashSet.h" +#include "PlatformBridge.h" #include "SimpleFontData.h" #include <unicode/uniset.h> #include <wtf/text/StringHash.h> @@ -288,9 +288,9 @@ static bool fontContainsCharacter(const FontPlatformData* fontData, HDC hdc = GetDC(0); HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(hdc, hfont)); int count = GetFontUnicodeRanges(hdc, 0); - if (count == 0 && ChromiumBridge::ensureFontLoaded(hfont)) + if (!count && PlatformBridge::ensureFontLoaded(hfont)) count = GetFontUnicodeRanges(hdc, 0); - if (count == 0) { + if (!count) { LOG_ERROR("Unable to get the font unicode range after second attempt"); SelectObject(hdc, oldFont); ReleaseDC(0, hdc); @@ -362,7 +362,7 @@ static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont winfont->lfStrikeOut = false; winfont->lfCharSet = DEFAULT_CHARSET; winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS; - winfont->lfQuality = ChromiumBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings. + winfont->lfQuality = PlatformBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings. winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; winfont->lfItalic = fontDescription.italic(); winfont->lfWeight = toGDIFontWeight(fontDescription.weight()); diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp index bd33927..a849a6c 100644 --- a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp @@ -31,12 +31,12 @@ #include "config.h" #include "FontCache.h" -#include "ChromiumBridge.h" #include "Font.h" #include "FontDescription.h" #include "FontPlatformData.h" #include "Logging.h" #include "NotImplemented.h" +#include "PlatformBridge.h" #include "SimpleFontData.h" #include "SkPaint.h" @@ -57,7 +57,7 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { - String family = ChromiumBridge::getFontFamilyForCharacters(characters, length); + String family = PlatformBridge::getFontFamilyForCharacters(characters, length); if (family.isEmpty()) return 0; diff --git a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp index 1a00833..5da4d5a 100644 --- a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp @@ -32,10 +32,10 @@ #include "config.h" #include "Font.h" -#include "ChromiumBridge.h" #include "FontFallbackList.h" #include "GlyphBuffer.h" #include "NotImplemented.h" +#include "PlatformBridge.h" #include "PlatformContextSkia.h" #include "SimpleFontData.h" #include "SkiaFontWin.h" @@ -424,7 +424,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], curAdvance); if (!success && executions == 0) { // Ask the browser to load the font for us and retry. - ChromiumBridge::ensureFontLoaded(font->platformData().hfont()); + PlatformBridge::ensureFontLoaded(font->platformData().hfont()); continue; } break; diff --git a/Source/WebCore/platform/graphics/chromium/FontLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp index f1eadf2..822bbbb 100644 --- a/Source/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -206,6 +206,16 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run, controller.setLetterSpacingAdjustment(letterSpacing()); controller.setPadding(run.padding()); + if (run.rtl()) { + // FIXME: this causes us to shape the text twice -- once to compute the width and then again + // below when actually rendering. Change ComplexTextController to match platform/mac and + // platform/chromium/win by having it store the shaped runs, so we can reuse the results. + controller.reset(point.x() + controller.widthOfFullRun()); + // We need to set the padding again because ComplexTextController layout consumed the value. + // Fixing the above problem would help here too. + controller.setPadding(run.padding()); + } + while (controller.nextScriptRun()) { if (fill) { controller.fontPlatformDataForScriptRun()->setupPaint(&fillPaint); @@ -231,6 +241,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon ComplexTextController controller(run, 0, this); controller.setWordSpacingAdjustment(wordSpacing()); controller.setLetterSpacingAdjustment(letterSpacing()); + controller.setPadding(run.padding()); return controller.widthOfFullRun(); } @@ -239,7 +250,7 @@ static int glyphIndexForXPositionInScriptRun(const ComplexTextController& contro // Iterate through the glyphs in logical order, seeing whether targetX falls between the previous // position and halfway through the current glyph. // FIXME: this code probably belongs in ComplexTextController. - int lastX = controller.rtl() ? controller.width() : 0; + int lastX = controller.offsetX() - (controller.rtl() ? -controller.width() : controller.width()); for (int glyphIndex = 0; static_cast<unsigned>(glyphIndex) < controller.length(); ++glyphIndex) { int advance = truncateFixedPointToInteger(controller.advances()[glyphIndex]); int nextX = static_cast<int>(controller.xPositions()[glyphIndex]) + advance / 2; @@ -257,53 +268,29 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, { // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem. - int x = static_cast<int>(xFloat); + int targetX = static_cast<int>(xFloat); // (Mac code ignores includePartialGlyphs, and they don't know what it's // supposed to do, so we just ignore it as well.) ComplexTextController controller(run, 0, this); controller.setWordSpacingAdjustment(wordSpacing()); controller.setLetterSpacingAdjustment(letterSpacing()); - - // If this is RTL text, the first glyph from the left is actually the last - // code point. So we need to know how many code points there are total in - // order to subtract. This is different from the length of the TextRun - // because UTF-16 surrogate pairs are a single code point, but 32-bits long. - // In LTR we leave this as 0 so that we get the correct value for - // |basePosition|, below. - unsigned totalCodePoints = 0; - if (controller.rtl()) { - ssize_t offset = 0; - while (offset < run.length()) { - utf16_to_code_point(run.characters(), run.length(), &offset); - totalCodePoints++; - } + controller.setPadding(run.padding()); + if (run.rtl()) { + // See FIXME in drawComplexText. + controller.reset(controller.widthOfFullRun()); + controller.setPadding(run.padding()); } - unsigned basePosition = totalCodePoints; - - // For RTL: - // code-point order: abcd efg hijkl - // on screen: lkjih gfe dcba - // ^ ^ - // | | - // basePosition--| | - // totalCodePoints----| - // Since basePosition is currently the total number of code-points, the - // first thing we do is decrement it so that it's pointing to the start of - // the current script-run. - // - // For LTR, basePosition is zero so it already points to the start of the - // first script run. + unsigned basePosition = 0; + + int x = controller.offsetX(); while (controller.nextScriptRun()) { - if (controller.rtl()) - basePosition -= controller.numCodePoints(); + int nextX = controller.offsetX(); - if (x >= 0 && static_cast<unsigned>(x) < controller.width()) { - // The x value in question is within this script run. We consider - // each glyph in presentation order and stop when we find the one - // covering this position. - const int glyphIndex = glyphIndexForXPositionInScriptRun(controller, x); + if (std::min(x, nextX) <= targetX && targetX <= std::max(x, nextX)) { + // The x value in question is within this script run. + const int glyphIndex = glyphIndexForXPositionInScriptRun(controller, targetX); // Now that we have a glyph index, we have to turn that into a // code-point index. Because of ligatures, several code-points may @@ -324,10 +311,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, return basePosition + controller.numCodePoints() - 1; } - x -= controller.width(); - - if (!controller.rtl()) - basePosition += controller.numCodePoints(); + basePosition += controller.numCodePoints(); } return basePosition; @@ -342,27 +326,21 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, ComplexTextController controller(run, 0, this); controller.setWordSpacingAdjustment(wordSpacing()); controller.setLetterSpacingAdjustment(letterSpacing()); + controller.setPadding(run.padding()); + if (run.rtl()) { + // See FIXME in drawComplexText. + controller.reset(controller.widthOfFullRun()); + controller.setPadding(run.padding()); + } - // Base will point to the x offset for the start of the current script run. Note that, in - // the LTR case, width will be 0. - int base = controller.rtl() ? controller.widthOfFullRun() : 0; - - controller.reset(); + // Iterate through the script runs in logical order, searching for the run covering the positions of interest. while (controller.nextScriptRun() && (fromX == -1 || toX == -1)) { - // ComplexTextController will helpfully accululate the x offsets for different - // script runs for us. For this code, however, we always want the x offsets - // to start from zero so we call this before each script run. - controller.setXOffsetToZero(); - - if (controller.rtl()) - base -= controller.width(); - if (fromX == -1 && from >= 0 && static_cast<unsigned>(from) < controller.numCodePoints()) { // |from| is within this script run. So we index the clusters log to // find which glyph this code-point contributed to and find its x // position. int glyph = controller.logClusters()[from]; - fromX = base + controller.xPositions()[glyph]; + fromX = controller.xPositions()[glyph]; if (controller.rtl()) fromX += truncateFixedPointToInteger(controller.advances()[glyph]); } else @@ -370,22 +348,18 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, if (toX == -1 && to >= 0 && static_cast<unsigned>(to) < controller.numCodePoints()) { int glyph = controller.logClusters()[to]; - toX = base + controller.xPositions()[glyph]; + toX = controller.xPositions()[glyph]; if (controller.rtl()) toX += truncateFixedPointToInteger(controller.advances()[glyph]); } else to -= controller.numCodePoints(); - - if (!controller.rtl()) - base += controller.width(); } // The position in question might be just after the text. - const int endEdge = base; - if (fromX == -1 && !from) - fromX = endEdge; - if (toX == -1 && !to) - toX = endEdge; + if (fromX == -1) + fromX = controller.offsetX(); + if (toX == -1) + toX = controller.offsetX(); ASSERT(fromX != -1 && toX != -1); diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp index d6c83ec..1022a9f 100644 --- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp @@ -36,7 +36,7 @@ #include <objidl.h> #include <mlang.h> -#include "ChromiumBridge.h" +#include "PlatformBridge.h" #include "SkiaFontWin.h" namespace WebCore { @@ -136,7 +136,7 @@ SCRIPT_FONTPROPERTIES* FontPlatformData::scriptFontProperties() const HRESULT hr = ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties); if (S_OK != hr) { - if (ChromiumBridge::ensureFontLoaded(hfont())) { + if (PlatformBridge::ensureFontLoaded(hfont())) { // FIXME: Handle gracefully the error if this call also fails. hr = ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties); diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index 42942cc..a1ea012 100644 --- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -31,9 +31,9 @@ #include "config.h" #include "FontPlatformData.h" -#include "ChromiumBridge.h" #include "HarfbuzzSkia.h" #include "NotImplemented.h" +#include "PlatformBridge.h" #include "PlatformString.h" #include "SkPaint.h" @@ -229,7 +229,7 @@ void FontPlatformData::querySystemForRenderStyle() return; } - ChromiumBridge::getRenderStyleForStrike(m_family.data(), (((int)m_textSize) << 2) | (m_typeface->style() & 3), &m_style); + PlatformBridge::getRenderStyleForStrike(m_family.data(), (((int)m_textSize) << 2) | (m_typeface->style() & 3), &m_style); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp index 697cf5e..4393f97 100644 --- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp +++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp @@ -34,12 +34,16 @@ #include "DrawingBuffer.h" #include "FloatRect.h" +#include "FloatSize.h" #include "GraphicsContext3D.h" +#include "internal_glu.h" #include "IntRect.h" +#include "Path.h" #include "PlatformString.h" #include "SharedGraphicsContext3D.h" -#include "SolidFillShader.h" -#include "TexShader.h" +#if PLATFORM(SKIA) +#include "SkPath.h" +#endif #include "Texture.h" #define _USE_MATH_DEFINES @@ -50,17 +54,99 @@ namespace WebCore { +// Number of line segments used to approximate bezier curves. +const int pathTesselation = 30; +typedef void (GLAPIENTRY *TESSCB)(); +typedef WTF::Vector<float> FloatVector; +typedef WTF::Vector<double> DoubleVector; + struct GLES2Canvas::State { State() : m_fillColor(0, 0, 0, 255) , m_alpha(1.0f) , m_compositeOp(CompositeSourceOver) + , m_clippingEnabled(false) + { + } + State(const State& other) + : m_fillColor(other.m_fillColor) + , m_alpha(other.m_alpha) + , m_compositeOp(other.m_compositeOp) + , m_ctm(other.m_ctm) + , m_clippingPaths() // Don't copy; clipping paths are tracked per-state. + , m_clippingEnabled(other.m_clippingEnabled) { } Color m_fillColor; float m_alpha; CompositeOperator m_compositeOp; AffineTransform m_ctm; + WTF::Vector<Path> m_clippingPaths; + bool m_clippingEnabled; +}; + +static inline FloatPoint operator*(const FloatPoint& f, float scale) +{ + return FloatPoint(f.x() * scale, f.y() * scale); +} + +static inline FloatPoint operator*(float scale, const FloatPoint& f) +{ + return FloatPoint(f.x() * scale, f.y() * scale); +} + +static inline FloatSize operator*(const FloatSize& f, float scale) +{ + return FloatSize(f.width() * scale, f.height() * scale); +} + +static inline FloatSize operator*(float scale, const FloatSize& f) +{ + return FloatSize(f.width() * scale, f.height() * scale); +} + +class Quadratic { + public: + Quadratic(FloatPoint a, FloatPoint b, FloatPoint c) : + m_a(a), m_b(b), m_c(c) + { + } + static Quadratic fromBezier(FloatPoint p0, FloatPoint p1, FloatPoint p2) + { + FloatSize p1s(p1.x(), p1.y()); + FloatSize p2s(p2.x(), p2.y()); + FloatPoint b = -2.0f * p0 + 2.0f * p1s; + FloatPoint c = p0 - 2.0f * p1s + p2s; + return Quadratic(p0, b, c); + } + inline FloatPoint evaluate(float t) + { + return m_a + t * (m_b + t * m_c); + } + FloatPoint m_a, m_b, m_c, m_d; +}; + +class Cubic { + public: + Cubic(FloatPoint a, FloatPoint b, FloatPoint c, FloatPoint d) : + m_a(a), m_b(b), m_c(c), m_d(d) + { + } + static Cubic fromBezier(FloatPoint p0, FloatPoint p1, FloatPoint p2, FloatPoint p3) + { + FloatSize p1s(p1.x(), p1.y()); + FloatSize p2s(p2.x(), p2.y()); + FloatSize p3s(p3.x(), p3.y()); + FloatPoint b = -3.0f * p0 + 3.0f * p1s; + FloatPoint c = 3.0f * p0 - 6.0f * p1s + 3.0f * p2s; + FloatPoint d = -1.0f * p0 + 3.0f * p1s - 3.0f * p2s + p3s; + return Cubic(p0, b, c, d); + } + FloatPoint evaluate(float t) + { + return m_a + t * (m_b + t * (m_c + t * m_d)); + } + FloatPoint m_a, m_b, m_c, m_d; }; GLES2Canvas::GLES2Canvas(SharedGraphicsContext3D* context, DrawingBuffer* drawingBuffer, const IntSize& size) @@ -88,7 +174,7 @@ void GLES2Canvas::bindFramebuffer() void GLES2Canvas::clearRect(const FloatRect& rect) { bindFramebuffer(); - if (m_state->m_ctm.isIdentity()) { + if (m_state->m_ctm.isIdentity() && !m_state->m_clippingEnabled) { m_context->scissor(rect); m_context->enable(GraphicsContext3D::SCISSOR_TEST); m_context->clearColor(Color(RGBA32(0))); @@ -102,13 +188,21 @@ void GLES2Canvas::clearRect(const FloatRect& rect) } } +void GLES2Canvas::fillPath(const Path& path) +{ + m_context->applyCompositeOperator(m_state->m_compositeOp); + applyClipping(m_state->m_clippingEnabled); + fillPath(path, m_state->m_fillColor); +} + void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { m_context->applyCompositeOperator(m_state->m_compositeOp); + applyClipping(m_state->m_clippingEnabled); m_context->useQuadVertices(); AffineTransform matrix(m_flipMatrix); - matrix.multLeft(m_state->m_ctm); + matrix *= m_state->m_ctm; matrix.translate(rect.x(), rect.y()); matrix.scale(rect.width(), rect.height()); @@ -150,7 +244,24 @@ void GLES2Canvas::scale(const FloatSize& size) void GLES2Canvas::concatCTM(const AffineTransform& affine) { - m_state->m_ctm.multLeft(affine); + m_state->m_ctm *= affine; +} + +void GLES2Canvas::clipPath(const Path& path) +{ + bindFramebuffer(); + checkGLError("bindFramebuffer"); + beginStencilDraw(); + // Red is used so we can see it if it ends up in the color buffer. + Color red(255, 0, 0, 255); + fillPath(path, red); + m_state->m_clippingPaths.append(path); + m_state->m_clippingEnabled = true; +} + +void GLES2Canvas::clipOut(const Path& path) +{ + ASSERT(!"clipOut is unsupported in GLES2Canvas.\n"); } void GLES2Canvas::save() @@ -162,13 +273,30 @@ void GLES2Canvas::save() void GLES2Canvas::restore() { ASSERT(!m_stateStack.isEmpty()); + bool hadClippingPaths = !m_state->m_clippingPaths.isEmpty(); m_stateStack.removeLast(); m_state = &m_stateStack.last(); + if (hadClippingPaths) { + m_context->clear(GraphicsContext3D::STENCIL_BUFFER_BIT); + beginStencilDraw(); + StateVector::const_iterator iter; + for (iter = m_stateStack.begin(); iter < m_stateStack.end(); ++iter) { + const State& state = *iter; + const Vector<Path>& clippingPaths = state.m_clippingPaths; + Vector<Path>::const_iterator pathIter; + for (pathIter = clippingPaths.begin(); pathIter < clippingPaths.end(); ++pathIter) { + // Red is used so we can see it if it ends up in the color buffer. + Color red(255, 0, 0, 255); + fillPath(*pathIter, red); + } + } + } } void GLES2Canvas::drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) { m_context->applyCompositeOperator(compositeOp); + applyClipping(false); m_context->useQuadVertices(); m_context->setActiveTexture(GraphicsContext3D::TEXTURE0); @@ -180,13 +308,14 @@ void GLES2Canvas::drawTexturedRect(unsigned texture, const IntSize& textureSize, 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); + drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp, m_state->m_clippingEnabled); } -void GLES2Canvas::drawTexturedRect(Texture* 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, bool clip) { m_context->applyCompositeOperator(compositeOp); + applyClipping(clip); const TilingData& tiles = texture->tiles(); IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect); @@ -220,7 +349,7 @@ void GLES2Canvas::drawTexturedRectTile(Texture* texture, int tile, const FloatRe void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) { AffineTransform matrix(m_flipMatrix); - matrix.multLeft(transform); + matrix *= transform; matrix.translate(dstRect.x(), dstRect.y()); matrix.scale(dstRect.width(), dstRect.height()); @@ -251,6 +380,214 @@ Texture* GLES2Canvas::getTexture(NativeImagePtr ptr) return m_context->getTexture(ptr); } +#if PLATFORM(SKIA) +// This is actually cross-platform code, but since its only caller is inside a +// PLATFORM(SKIA), it will cause a warning-as-error on Chrome/Mac. +static void interpolateQuadratic(DoubleVector* vertices, const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2) +{ + float tIncrement = 1.0f / pathTesselation, t = tIncrement; + Quadratic c = Quadratic::fromBezier(p0, p1, p2); + for (int i = 0; i < pathTesselation; ++i, t += tIncrement) { + FloatPoint p = c.evaluate(t); + vertices->append(p.x()); + vertices->append(p.y()); + vertices->append(1.0); + } +} + +static void interpolateCubic(DoubleVector* vertices, const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3) +{ + float tIncrement = 1.0f / pathTesselation, t = tIncrement; + Cubic c = Cubic::fromBezier(p0, p1, p2, p3); + for (int i = 0; i < pathTesselation; ++i, t += tIncrement) { + FloatPoint p = c.evaluate(t); + vertices->append(p.x()); + vertices->append(p.y()); + vertices->append(1.0); + } +} +#endif + +struct PolygonData { + PolygonData(FloatVector* vertices, WTF::Vector<short>* indices) + : m_vertices(vertices) + , m_indices(indices) + { + } + FloatVector* m_vertices; + WTF::Vector<short>* m_indices; +}; + +static void beginData(GLenum type, void* data) +{ + ASSERT(type == GL_TRIANGLES); +} + +static void edgeFlagData(GLboolean flag, void* data) +{ +} + +static void vertexData(void* vertexData, void* data) +{ + static_cast<PolygonData*>(data)->m_indices->append(reinterpret_cast<long>(vertexData)); +} + +static void endData(void* data) +{ +} + +static void combineData(GLdouble coords[3], void* vertexData[4], + GLfloat weight[4], void **outData, void* data) +{ + PolygonData* polygonData = static_cast<PolygonData*>(data); + int index = polygonData->m_vertices->size() / 3; + polygonData->m_vertices->append(static_cast<float>(coords[0])); + polygonData->m_vertices->append(static_cast<float>(coords[1])); + polygonData->m_vertices->append(1.0f); + *outData = reinterpret_cast<void*>(index); +} + +typedef void (*TESSCB)(); + +void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsigned* vertexBuffer, unsigned* indexBuffer) +{ + *vertexBuffer = m_context->graphicsContext3D()->createBuffer(); + checkGLError("createVertexBufferFromPath, createBuffer"); + *indexBuffer = m_context->graphicsContext3D()->createBuffer(); + checkGLError("createVertexBufferFromPath, createBuffer"); + DoubleVector inVertices; + WTF::Vector<size_t> contours; +#if PLATFORM(SKIA) + const SkPath* skPath = path.platformPath(); + SkPoint pts[4]; + SkPath::Iter iter(*skPath, true); + SkPath::Verb verb; + while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { + switch (verb) { + case SkPath::kMove_Verb: + inVertices.append(pts[0].fX); + inVertices.append(pts[0].fY); + inVertices.append(1.0); + break; + case SkPath::kLine_Verb: + inVertices.append(pts[1].fX); + inVertices.append(pts[1].fY); + inVertices.append(1.0); + break; + case SkPath::kQuad_Verb: + interpolateQuadratic(&inVertices, pts[0], pts[1], pts[2]); + break; + case SkPath::kCubic_Verb: + interpolateCubic(&inVertices, pts[0], pts[1], pts[2], pts[3]); + break; + case SkPath::kClose_Verb: + contours.append(inVertices.size() / 3); + break; + case SkPath::kDone_Verb: + break; + } + } +#else + ASSERT(!"Path extraction not implemented on this platform."); +#endif + + GLUtesselator* tess = internal_gluNewTess(); + internal_gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); + internal_gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (TESSCB) &beginData); + internal_gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (TESSCB) &vertexData); + internal_gluTessCallback(tess, GLU_TESS_END_DATA, (TESSCB) &endData); + internal_gluTessCallback(tess, GLU_TESS_EDGE_FLAG_DATA, (TESSCB) &edgeFlagData); + internal_gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (TESSCB) &combineData); + WTF::Vector<short> indices; + FloatVector vertices; + vertices.reserveInitialCapacity(inVertices.size()); + PolygonData data(&vertices, &indices); + internal_gluTessBeginPolygon(tess, &data); + WTF::Vector<size_t>::const_iterator contour; + size_t i = 0; + for (contour = contours.begin(); contour != contours.end(); ++contour) { + internal_gluTessBeginContour(tess); + for (; i < *contour; ++i) { + vertices.append(inVertices[i * 3]); + vertices.append(inVertices[i * 3 + 1]); + vertices.append(1.0f); + internal_gluTessVertex(tess, &inVertices[i * 3], reinterpret_cast<void*>(i)); + } + internal_gluTessEndContour(tess); + } + internal_gluTessEndPolygon(tess); + internal_gluDeleteTess(tess); + + m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, *vertexBuffer); + checkGLError("createVertexBufferFromPath, bindBuffer ARRAY_BUFFER"); + m_context->graphicsContext3D()->bufferData(GraphicsContext3D::ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GraphicsContext3D::STREAM_DRAW); + checkGLError("createVertexBufferFromPath, bufferData ARRAY_BUFFER"); + + m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, *indexBuffer); + checkGLError("createVertexBufferFromPath, bindBuffer ELEMENT_ARRAY_BUFFER"); + m_context->graphicsContext3D()->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(short), indices.data(), GraphicsContext3D::STREAM_DRAW); + checkGLError("createVertexBufferFromPath, bufferData ELEMENT_ARRAY_BUFFER"); + *count = indices.size(); +} + +void GLES2Canvas::fillPath(const Path& path, const Color& color) +{ + int count; + unsigned vertexBuffer, indexBuffer; + createVertexBufferFromPath(path, &count, &vertexBuffer, &indexBuffer); + m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vertexBuffer); + checkGLError("bindBuffer"); + m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indexBuffer); + checkGLError("bindBuffer"); + + AffineTransform matrix(m_flipMatrix); + matrix *= m_state->m_ctm; + + m_context->useFillSolidProgram(matrix, color); + checkGLError("useFillSolidProgram"); + + m_context->graphicsContext3D()->drawElements(GraphicsContext3D::TRIANGLES, count, GraphicsContext3D::UNSIGNED_SHORT, 0); + checkGLError("drawArrays"); + + m_context->graphicsContext3D()->deleteBuffer(vertexBuffer); + checkGLError("deleteBuffer"); + + m_context->graphicsContext3D()->deleteBuffer(indexBuffer); + checkGLError("deleteBuffer"); +} + +void GLES2Canvas::beginStencilDraw() +{ + // Turn on stencil test. + m_context->enableStencil(true); + checkGLError("enable STENCIL_TEST"); + + // Stencil test never passes, so colorbuffer is not drawn. + m_context->graphicsContext3D()->stencilFunc(GraphicsContext3D::NEVER, 1, 1); + checkGLError("stencilFunc"); + + // All writes incremement the stencil buffer. + m_context->graphicsContext3D()->stencilOp(GraphicsContext3D::INCR, + GraphicsContext3D::INCR, + GraphicsContext3D::INCR); + checkGLError("stencilOp"); +} + +void GLES2Canvas::applyClipping(bool enable) +{ + m_context->enableStencil(enable); + if (enable) { + // Enable drawing only where stencil is non-zero. + m_context->graphicsContext3D()->stencilFunc(GraphicsContext3D::EQUAL, m_state->m_clippingPaths.size() % 256, 1); + checkGLError("stencilFunc"); + // Keep all stencil values the same. + m_context->graphicsContext3D()->stencilOp(GraphicsContext3D::KEEP, + GraphicsContext3D::KEEP, + GraphicsContext3D::KEEP); + checkGLError("stencilOp"); + } +} + void GLES2Canvas::checkGLError(const char* header) { #ifndef NDEBUG @@ -283,4 +620,3 @@ void GLES2Canvas::checkGLError(const char* header) } } - diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h index 6fc1a0e..605f86f 100644 --- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h +++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h @@ -48,13 +48,16 @@ class Color; class DrawingBuffer; class FloatRect; class GraphicsContext3D; +class Path; class SharedGraphicsContext3D; -class GLES2Canvas : public Noncopyable { +class GLES2Canvas { + WTF_MAKE_NONCOPYABLE(GLES2Canvas); public: GLES2Canvas(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&); ~GLES2Canvas(); + void fillPath(const Path&); void fillRect(const FloatRect&, const Color&, ColorSpace); void fillRect(const FloatRect&); void clearRect(const FloatRect&); @@ -65,6 +68,8 @@ public: void rotate(float angleInRadians); void scale(const FloatSize&); void concatCTM(const AffineTransform&); + void clipPath(const Path&); + void clipOut(const Path&); void save(); void restore(); @@ -72,9 +77,13 @@ public: // non-standard functions // These are not standard GraphicsContext functions, and should be pushed // down into a PlatformContextGLES2 at some point. + + // This version is called by the canvas->canvas draws. void drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator); - void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator); + // This version is called by BitmapImage::draw(). void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator); + // This version is called by the above, and by the software->hardware uploads. + void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator, bool clip); Texture* createTexture(NativeImagePtr, Texture::Format, int width, int height); Texture* getTexture(NativeImagePtr); @@ -88,6 +97,10 @@ private: void drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); void drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); void applyCompositeOperator(CompositeOperator); + void createVertexBufferFromPath(const Path&, int* count, unsigned* vertexBuffer, unsigned* indexBuffer); + void fillPath(const Path&, const Color&); + void beginStencilDraw(); + void applyClipping(bool enable); void checkGLError(const char* header); IntSize m_size; @@ -96,7 +109,8 @@ private: DrawingBuffer* m_drawingBuffer; struct State; - WTF::Vector<State> m_stateStack; + typedef WTF::Vector<State> StateVector; + StateVector m_stateStack; State* m_state; AffineTransform m_flipMatrix; }; diff --git a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp index e71f66a..ee2b5ab 100644 --- a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp @@ -32,9 +32,9 @@ #include <windows.h> #include <vector> -#include "ChromiumBridge.h" #include "Font.h" #include "GlyphPageTreeNode.h" +#include "PlatformBridge.h" #include "SimpleFontData.h" #include "UniscribeHelperTextRun.h" #include "WindowsVersion.h" @@ -80,12 +80,11 @@ static bool fillBMPGlyphs(unsigned offset, ReleaseDC(0, dc); if (recurse) { - if (ChromiumBridge::ensureFontLoaded(fontData->platformData().hfont())) + if (PlatformBridge::ensureFontLoaded(fontData->platformData().hfont())) return fillBMPGlyphs(offset, length, buffer, page, fontData, false); - else { - fillEmptyGlyphs(page); - return false; - } + + fillEmptyGlyphs(page); + return false; } else { // FIXME: Handle gracefully the error if this call also fails. // See http://crbug.com/6401 diff --git a/Source/WebCore/platform/graphics/chromium/ImageChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageChromium.cpp index e90d566..e2b6f7a 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ImageChromium.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "Image.h" -#include "ChromiumBridge.h" +#include "PlatformBridge.h" namespace WebCore { @@ -39,7 +39,7 @@ namespace WebCore { PassRefPtr<Image> Image::loadPlatformResource(const char *name) { - return ChromiumBridge::loadPlatformImageResource(name); + return PlatformBridge::loadPlatformImageResource(name); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/ImageChromiumMac.mm b/Source/WebCore/platform/graphics/chromium/ImageChromiumMac.mm index 073a409..f003894 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageChromiumMac.mm +++ b/Source/WebCore/platform/graphics/chromium/ImageChromiumMac.mm @@ -33,14 +33,14 @@ #include "config.h" #include "BitmapImage.h" -#include "ChromiumBridge.h" #include "Image.h" +#include "PlatformBridge.h" namespace WebCore { PassRefPtr<Image> Image::loadPlatformResource(const char* name) { - return ChromiumBridge::loadPlatformImageResource(name); + return PlatformBridge::loadPlatformImageResource(name); } // FIXME: These are temporary stubs, we need real implementations which diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index 8d77bea..90eac74 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -119,12 +119,6 @@ LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> conte LayerRendererChromium::~LayerRendererChromium() { cleanupSharedObjects(); - - // Because the tilers need to clean up textures, clean them up explicitly - // before the GraphicsContext3D is destroyed. - m_rootLayerTiler.clear(); - m_horizontalScrollbarTiler.clear(); - m_verticalScrollbarTiler.clear(); } GraphicsContext3D* LayerRendererChromium::context() @@ -269,6 +263,9 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect updateAndDrawRootLayer(tilePaint, scrollbarPaint, visibleRect, contentRect); + // Re-enable color writes to layers, which may be partially transparent. + m_context->colorMask(true, true, true, true); + // Set the root visible/content rects --- used by subsequent drawLayers calls. m_rootVisibleRect = visibleRect; m_rootContentRect = contentRect; @@ -795,6 +792,11 @@ void LayerRendererChromium::cleanupSharedObjects() if (m_offscreenFramebufferId) GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId)); + // Clear tilers before the texture manager, as they have references to textures. + m_rootLayerTiler.clear(); + m_horizontalScrollbarTiler.clear(); + m_verticalScrollbarTiler.clear(); + m_textureManager.clear(); } diff --git a/Source/WebCore/platform/graphics/chromium/LayerTexture.h b/Source/WebCore/platform/graphics/chromium/LayerTexture.h index 711e687..b60dff2 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTexture.h +++ b/Source/WebCore/platform/graphics/chromium/LayerTexture.h @@ -28,6 +28,7 @@ #include "IntSize.h" #include "TextureManager.h" +#include <wtf/FastAllocBase.h> #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> #include <wtf/RefPtr.h> @@ -37,7 +38,8 @@ namespace WebCore { class GraphicsContext3D; class TextureManager; -class LayerTexture : public Noncopyable { +class LayerTexture { + WTF_MAKE_NONCOPYABLE(LayerTexture); WTF_MAKE_FAST_ALLOCATED; public: static PassOwnPtr<LayerTexture> create(GraphicsContext3D* context, TextureManager* manager) { diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp index b4b4a72..6b65e66 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp @@ -33,6 +33,7 @@ #include "GraphicsContext.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" +#include "LayerTexture.h" #if PLATFORM(SKIA) #include "NativeImageSkia.h" @@ -54,7 +55,8 @@ PassOwnPtr<LayerTilerChromium> LayerTilerChromium::create(LayerRendererChromium* } LayerTilerChromium::LayerTilerChromium(LayerRendererChromium* layerRenderer, const IntSize& tileSize) - : m_layerRenderer(layerRenderer) + : m_skipsDraw(false) + , m_layerRenderer(layerRenderer) { setTileSize(tileSize); } @@ -83,17 +85,7 @@ void LayerTilerChromium::setTileSize(const IntSize& size) void LayerTilerChromium::reset() { - for (size_t i = 0; i < m_tiles.size(); ++i) { - if (!m_tiles[i]) - continue; - layerRenderer()->deleteLayerTexture(m_tiles[i]->releaseTextureId()); - } m_tiles.clear(); - for (size_t i = 0; i < m_unusedTiles.size(); ++i) { - if (!m_unusedTiles[i]) - continue; - layerRenderer()->deleteLayerTexture(m_unusedTiles[i]->releaseTextureId()); - } m_unusedTiles.clear(); m_layerSize = IntSize(); @@ -110,12 +102,9 @@ LayerTilerChromium::Tile* LayerTilerChromium::createTile(int i, int j) m_tiles[index] = m_unusedTiles.last().release(); m_unusedTiles.removeLast(); } else { - const unsigned int textureId = layerRenderer()->createLayerTexture(); - OwnPtr<Tile> tile = adoptPtr(new Tile(textureId)); - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_tileSize.width(), m_tileSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE)); - + TextureManager* manager = layerRenderer()->textureManager(); + OwnPtr<Tile> tile = adoptPtr(new Tile(LayerTexture::create(context, manager))); m_tiles[index] = tile.release(); } @@ -238,6 +227,9 @@ void LayerTilerChromium::invalidateEntireLayer() void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& contentRect) { + if (m_skipsDraw) + return; + // Invalidate old tiles that were previously used but aren't in use this // frame so that they can get reused for new tiles. IntRect layerRect = contentRectToLayerRect(contentRect); @@ -256,6 +248,8 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont Tile* tile = m_tiles[tileIndex(i, j)].get(); if (!tile) tile = createTile(i, j); + if (!tile->texture()->isValid(m_tileSize, GraphicsContext3D::RGBA)) + tile->m_dirtyLayerRect = tileLayerRect(i, j); dirtyLayerRect.unite(tile->m_dirtyLayerRect); } } @@ -318,6 +312,12 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont if (sourceRect.isEmpty()) continue; + if (!tile->texture()->reserve(m_tileSize, GraphicsContext3D::RGBA)) { + m_skipsDraw = true; + reset(); + return; + } + // Calculate tile-space rectangle to upload into. IntRect destRect(IntPoint(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()), sourceRect.size()); ASSERT(destRect.x() >= 0); @@ -342,7 +342,7 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont pixelSource = &m_tilePixels[0]; } - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, tile->textureId())); + tile->texture()->bindTexture(); GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, destRect.x(), destRect.y(), destRect.width(), destRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixelSource)); tile->clearDirty(); @@ -357,6 +357,9 @@ void LayerTilerChromium::setLayerPosition(const IntPoint& layerPosition) void LayerTilerChromium::draw(const IntRect& contentRect) { + if (m_skipsDraw) + return; + // We reuse the shader program used by ContentLayerChromium. GraphicsContext3D* context = layerRendererContext(); const ContentLayerChromium::SharedValues* contentLayerValues = layerRenderer()->contentLayerSharedValues(); @@ -370,13 +373,15 @@ void LayerTilerChromium::draw(const IntRect& contentRect) Tile* tile = m_tiles[tileIndex(i, j)].get(); ASSERT(tile); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, tile->textureId())); + tile->texture()->bindTexture(); TransformationMatrix tileMatrix; IntRect tileRect = tileContentRect(i, j); tileMatrix.translate3d(tileRect.x() - contentRect.x() + tileRect.width() / 2.0, tileRect.y() - contentRect.y() + tileRect.height() / 2.0, 0); LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), tileMatrix, m_tileSize.width(), m_tileSize.height(), 1, contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation()); + + tile->texture()->unreserve(); } } } @@ -410,21 +415,6 @@ void LayerTilerChromium::growLayerToContain(const IntRect& contentRect) resizeLayer(newSize); } -LayerTilerChromium::Tile::~Tile() -{ - // Each tile doesn't have a reference to the context, so can't clean up - // its own texture. If this assert is hit, then the LayerTilerChromium - // destructor didn't clean this up. - ASSERT(!m_textureId); -} - -unsigned int LayerTilerChromium::Tile::releaseTextureId() -{ - unsigned int id = m_textureId; - m_textureId = 0; - return id; -} - } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h index c066fdf..e09693d 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h @@ -30,6 +30,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "LayerChromium.h" +#include "LayerTexture.h" #include <wtf/OwnArrayPtr.h> namespace WebCore { @@ -42,7 +43,8 @@ public: virtual void paint(GraphicsContext& context, const IntRect& contentRect) = 0; }; -class LayerTilerChromium : public Noncopyable { +class LayerTilerChromium { + WTF_MAKE_NONCOPYABLE(LayerTilerChromium); public: static PassOwnPtr<LayerTilerChromium> create(LayerRendererChromium* layerRenderer, const IntSize& tileSize); @@ -62,12 +64,11 @@ private: LayerTilerChromium(LayerRendererChromium* layerRenderer, const IntSize& tileSize); class Tile { + WTF_MAKE_NONCOPYABLE(Tile); public: - explicit Tile(unsigned int textureId) : m_textureId(textureId) { } - ~Tile(); + explicit Tile(PassOwnPtr<LayerTexture> tex) : m_tex(tex) {} - unsigned int textureId() const { return m_textureId; } - unsigned int releaseTextureId(); + LayerTexture* texture() { return m_tex.get(); } bool dirty() const { return !m_dirtyLayerRect.isEmpty(); } void clearDirty() { m_dirtyLayerRect = IntRect(); } @@ -75,7 +76,7 @@ private: // Layer-space dirty rectangle that needs to be repainted. IntRect m_dirtyLayerRect; private: - unsigned int m_textureId; + OwnPtr<LayerTexture> m_tex; }; void resizeLayer(const IntSize& size); @@ -105,6 +106,8 @@ private: IntRect m_lastUpdateLayerRect; IntPoint m_layerPosition; + bool m_skipsDraw; + // Logical 2D array of tiles (dimensions of m_layerTileSize) Vector<OwnPtr<Tile> > m_tiles; // Linear array of unused tiles. diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h index a93218f..689a6eb 100644 --- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h +++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h @@ -41,7 +41,8 @@ class LayerChromium; class LayerRendererChromium; class LayerTexture; -class RenderSurfaceChromium : public Noncopyable { +class RenderSurfaceChromium { + WTF_MAKE_NONCOPYABLE(RenderSurfaceChromium); friend class LayerRendererChromium; public: explicit RenderSurfaceChromium(LayerChromium*); diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp index 204c565..c23c586 100644 --- a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp @@ -32,11 +32,11 @@ #include "config.h" #include "SimpleFontData.h" -#include "ChromiumBridge.h" +#include "FloatRect.h" #include "Font.h" #include "FontCache.h" -#include "FloatRect.h" #include "FontDescription.h" +#include "PlatformBridge.h" #include <wtf/MathExtras.h> #include <unicode/uchar.h> @@ -70,7 +70,7 @@ void SimpleFontData::platformInit() TEXTMETRIC textMetric = {0}; if (!GetTextMetrics(dc, &textMetric)) { - if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) { + if (PlatformBridge::ensureFontLoaded(m_platformData.hfont())) { // Retry GetTextMetrics. // FIXME: Handle gracefully the error if this call also fails. // See http://crbug.com/6401. @@ -159,7 +159,7 @@ void SimpleFontData::determinePitch() // is *not* fixed pitch. Unbelievable but true. TEXTMETRIC textMetric = {0}; if (!GetTextMetrics(dc, &textMetric)) { - if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) { + if (PlatformBridge::ensureFontLoaded(m_platformData.hfont())) { // Retry GetTextMetrics. // FIXME: Handle gracefully the error if this call also fails. // See http://crbug.com/6401. @@ -190,7 +190,7 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const int width = 0; if (!GetCharWidthI(dc, glyph, 1, 0, &width)) { // Ask the browser to preload the font and retry. - if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) { + if (PlatformBridge::ensureFontLoaded(m_platformData.hfont())) { // FIXME: Handle gracefully the error if this call also fails. // See http://crbug.com/6401. if (!GetCharWidthI(dc, glyph, 1, 0, &width)) diff --git a/Source/WebCore/platform/graphics/chromium/TextureManager.h b/Source/WebCore/platform/graphics/chromium/TextureManager.h index 4891cc7..83104a9 100644 --- a/Source/WebCore/platform/graphics/chromium/TextureManager.h +++ b/Source/WebCore/platform/graphics/chromium/TextureManager.h @@ -29,6 +29,7 @@ #include "IntRect.h" #include "IntSize.h" +#include <wtf/FastAllocBase.h> #include <wtf/HashMap.h> #include <wtf/ListHashSet.h> @@ -36,7 +37,8 @@ namespace WebCore { typedef int TextureToken; -class TextureManager : public Noncopyable { +class TextureManager { + WTF_MAKE_NONCOPYABLE(TextureManager); public: static PassOwnPtr<TextureManager> create(GraphicsContext3D* context, size_t memoryLimitBytes, int maxTextureSize) { diff --git a/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp index 4dc2157..ba66eae 100644 --- a/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp @@ -252,7 +252,7 @@ void TransparencyWin::setupLayerForOpaqueCompositeLayer() if (m_transformMode == Untransform){ // Compute the inverse mapping from the canvas space to the // coordinate space of our bitmap. - mapping = m_orgTransform.inverse() * mapping; + mapping *= m_orgTransform.inverse(); } compositeToCopy(*m_destContext, *m_drawContext, mapping); @@ -313,7 +313,7 @@ void TransparencyWin::setupTransformForKeepTransform(const IntRect& region) // We're making a layer, so apply the old transform to the new one // so it's maintained. We know the new layer has the identity // transform now, we we can just multiply it. - xform = m_orgTransform * xform; + xform *= m_orgTransform; m_drawContext->concatCTM(xform); } m_drawRect = m_sourceRect; diff --git a/Source/WebCore/platform/graphics/chromium/TransparencyWin.h b/Source/WebCore/platform/graphics/chromium/TransparencyWin.h index b6bef91..535cbaa 100644 --- a/Source/WebCore/platform/graphics/chromium/TransparencyWin.h +++ b/Source/WebCore/platform/graphics/chromium/TransparencyWin.h @@ -54,7 +54,8 @@ class TransparencyWin_OpaqueCompositeLayer_Test; // that is composited later manually. This is to get around Windows' inability // to handle the alpha channel, semitransparent text, and transformed form // controls. -class TransparencyWin : public Noncopyable { +class TransparencyWin { + WTF_MAKE_NONCOPYABLE(TransparencyWin); public: enum LayerMode { // No extra layer is created. Drawing will happen to the source. diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp b/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp index f801c13..aa18b4a 100644 --- a/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp +++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp @@ -31,9 +31,10 @@ #include "config.h" #include "UniscribeHelperTextRun.h" -#include "ChromiumBridge.h" #include "Font.h" +#include "PlatformBridge.h" #include "SimpleFontData.h" +#include "TextRun.h" namespace WebCore { @@ -79,7 +80,7 @@ void UniscribeHelperTextRun::tryToPreloadFont(HFONT font) // Ask the browser to get the font metrics for this font. // That will preload the font and it should now be accessible // from the renderer. - ChromiumBridge::ensureFontLoaded(font); + PlatformBridge::ensureFontLoaded(font); } bool UniscribeHelperTextRun::nextWinFontData( diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp index 81264b3..776b83f 100644 --- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp @@ -264,6 +264,7 @@ unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame) { switch (frame->format()) { case VideoFrameChromium::YV12: + case VideoFrameChromium::YV16: return GraphicsContext3D::LUMINANCE; case VideoFrameChromium::RGBA: return GraphicsContext3D::RGBA; @@ -330,6 +331,7 @@ void VideoLayerChromium::draw() switch (m_frameFormat) { case VideoFrameChromium::YV12: + case VideoFrameChromium::YV16: drawYUV(sv); break; case VideoFrameChromium::RGBA: |