diff options
Diffstat (limited to 'WebCore/platform/graphics')
110 files changed, 3565 insertions, 2743 deletions
diff --git a/WebCore/platform/graphics/Gradient.cpp b/WebCore/platform/graphics/Gradient.cpp index 3d8dfc9..f9427fb 100644 --- a/WebCore/platform/graphics/Gradient.cpp +++ b/WebCore/platform/graphics/Gradient.cpp @@ -117,9 +117,16 @@ void Gradient::sortStopsIfNecessary() if (m_stopsSorted) return; - if (m_stops.size()) - std::stable_sort(m_stops.begin(), m_stops.end(), compareStops); m_stopsSorted = true; + + if (!m_stops.size()) + return; + + // Shortcut for the ideal case (ordered 2-stop gradient) + if (m_stops.size() == 2 && compareStops(*m_stops.begin(), *m_stops.end())) + return; + + std::stable_sort(m_stops.begin(), m_stops.end(), compareStops); } void Gradient::getColor(float value, float* r, float* g, float* b, float* a) const diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h index c4ac01b..0a69fa2 100644 --- a/WebCore/platform/graphics/Gradient.h +++ b/WebCore/platform/graphics/Gradient.h @@ -101,7 +101,7 @@ namespace WebCore { const FloatPoint& p1() const { return m_p1; } float r0() const { return m_r0; } float r1() const { return m_r1; } - const Vector<ColorStop>& getStops() const; + const Vector<ColorStop, 2>& getStops() const; #else #if PLATFORM(ANDROID) SkShader* getShader(SkShader::TileMode); @@ -150,7 +150,7 @@ namespace WebCore { FloatPoint m_p1; float m_r0; float m_r1; - mutable Vector<ColorStop> m_stops; + mutable Vector<ColorStop, 2> m_stops; mutable bool m_stopsSorted; mutable int m_lastStop; GradientSpreadMethod m_spreadMethod; diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp index 170bb84..2da5862 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -830,6 +830,40 @@ bool GraphicsContext3D::supportsBGRA() // Returning false for now to be safe. return false; } + +bool GraphicsContext3D::supportsMapSubCHROMIUM() +{ + // We don't claim support for this extension at this time. + return false; +} + +void* GraphicsContext3D::mapBufferSubDataCHROMIUM(unsigned, int, int, unsigned) +{ + return 0; +} + +void GraphicsContext3D::unmapBufferSubDataCHROMIUM(const void*) +{ +} + +void* GraphicsContext3D::mapTexSubImage2DCHROMIUM(unsigned, int, int, int, int, int, unsigned, unsigned, unsigned) +{ + return 0; +} + +void GraphicsContext3D::unmapTexSubImage2DCHROMIUM(const void*) +{ +} + +bool GraphicsContext3D::supportsCopyTextureToParentTextureCHROMIUM() +{ + // We don't claim support for this extension at this time. + return false; +} + +void GraphicsContext3D::copyTextureToParentTextureCHROMIUM(unsigned, unsigned) +{ +} #endif } // namespace WebCore diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index b583813..bcb7997 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -404,7 +404,12 @@ public: UNPACK_FLIP_Y_WEBGL = 0x9240, UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241, - BGRA_EXT = 0x80E1 + // GL_EXT_texture_format_BGRA8888 + BGRA_EXT = 0x80E1, + + // GL_CHROMIUM_map_sub (enums inherited from GL_ARB_vertex_buffer_object) + READ_ONLY = 0x88B8, + WRITE_ONLY = 0x88B9 }; // Context creation attributes. @@ -425,7 +430,12 @@ public: bool premultipliedAlpha; }; - static PassOwnPtr<GraphicsContext3D> create(Attributes attrs, HostWindow* hostWindow); + enum RenderStyle { + RenderOffscreen, + RenderDirectlyToHostWindow + }; + + static PassOwnPtr<GraphicsContext3D> create(Attributes attrs, HostWindow* hostWindow, RenderStyle renderStyle = RenderOffscreen); virtual ~GraphicsContext3D(); #if PLATFORM(MAC) @@ -751,10 +761,22 @@ public: // getError in the order they were added. void synthesizeGLError(unsigned long error); + // EXT_texture_format_BGRA8888 bool supportsBGRA(); + // GL_CHROMIUM_map_sub + bool supportsMapSubCHROMIUM(); + void* mapBufferSubDataCHROMIUM(unsigned target, int offset, int size, unsigned access); + void unmapBufferSubDataCHROMIUM(const void*); + void* mapTexSubImage2DCHROMIUM(unsigned target, int level, int xoffset, int yoffset, int width, int height, unsigned format, unsigned type, unsigned access); + void unmapTexSubImage2DCHROMIUM(const void*); + + // GL_CHROMIUM_copy_texture_to_parent_texture + bool supportsCopyTextureToParentTextureCHROMIUM(); + void copyTextureToParentTextureCHROMIUM(unsigned texture, unsigned parentTexture); + private: - GraphicsContext3D(Attributes attrs, HostWindow* hostWindow); + GraphicsContext3D(Attributes attrs, HostWindow* hostWindow, bool renderDirectlyToHostWindow); // Each platform must provide an implementation of this method. // diff --git a/WebCore/platform/graphics/GraphicsLayer.cpp b/WebCore/platform/graphics/GraphicsLayer.cpp index 5003907..b0f529b 100644 --- a/WebCore/platform/graphics/GraphicsLayer.cpp +++ b/WebCore/platform/graphics/GraphicsLayer.cpp @@ -73,7 +73,6 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client) , m_masksToBounds(false) , m_drawsContent(false) , m_paintingPhase(GraphicsLayerPaintAll) - , m_geometryOrientation(CompositingCoordinatesTopDown) , m_contentsOrientation(CompositingCoordinatesTopDown) , m_parent(0) , m_maskLayer(0) @@ -411,29 +410,45 @@ void GraphicsLayer::dumpLayer(TextStream& ts, int indent, LayerTreeAsTextBehavio void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeAsTextBehavior behavior) const { - writeIndent(ts, indent + 1); - ts << "(position " << m_position.x() << " " << m_position.y() << ")\n"; + if (m_position != FloatPoint()) { + writeIndent(ts, indent + 1); + ts << "(position " << m_position.x() << " " << m_position.y() << ")\n"; + } - writeIndent(ts, indent + 1); - ts << "(anchor " << m_anchorPoint.x() << " " << m_anchorPoint.y() << ")\n"; + if (m_anchorPoint != FloatPoint3D(0.5f, 0.5f, 0)) { + writeIndent(ts, indent + 1); + ts << "(anchor " << m_anchorPoint.x() << " " << m_anchorPoint.y() << ")\n"; + } - writeIndent(ts, indent + 1); - ts << "(bounds " << m_size.width() << " " << m_size.height() << ")\n"; + if (m_size != IntSize()) { + writeIndent(ts, indent + 1); + ts << "(bounds " << m_size.width() << " " << m_size.height() << ")\n"; + } - writeIndent(ts, indent + 1); - ts << "(opacity " << m_opacity << ")\n"; + if (m_opacity != 1) { + writeIndent(ts, indent + 1); + ts << "(opacity " << m_opacity << ")\n"; + } - writeIndent(ts, indent + 1); - ts << "(usingTiledLayer " << m_usingTiledLayer << ")\n"; + if (m_usingTiledLayer) { + writeIndent(ts, indent + 1); + ts << "(usingTiledLayer " << m_usingTiledLayer << ")\n"; + } - writeIndent(ts, indent + 1); - ts << "(preserves3D " << m_preserves3D << ")\n"; + if (m_preserves3D) { + writeIndent(ts, indent + 1); + ts << "(preserves3D " << m_preserves3D << ")\n"; + } - writeIndent(ts, indent + 1); - ts << "(drawsContent " << m_drawsContent << ")\n"; + if (m_drawsContent) { + writeIndent(ts, indent + 1); + ts << "(drawsContent " << m_drawsContent << ")\n"; + } - writeIndent(ts, indent + 1); - ts << "(backfaceVisibility " << (m_backfaceVisibility ? "visible" : "hidden") << ")\n"; + if (!m_backfaceVisibility) { + writeIndent(ts, indent + 1); + ts << "(backfaceVisibility " << (m_backfaceVisibility ? "visible" : "hidden") << ")\n"; + } if (behavior & LayerTreeAsTextDebug) { writeIndent(ts, indent + 1); @@ -445,40 +460,29 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeAsTextBe ts << ")\n"; } - writeIndent(ts, indent + 1); - ts << "(backgroundColor "; - if (!m_backgroundColorSet) - ts << "none"; - else - ts << m_backgroundColor.name(); - ts << ")\n"; + if (m_backgroundColorSet) { + writeIndent(ts, indent + 1); + ts << "(backgroundColor " << m_backgroundColor.name() << ")\n"; + } - writeIndent(ts, indent + 1); - ts << "(transform "; - if (m_transform.isIdentity()) - ts << "identity"; - else { + if (!m_transform.isIdentity()) { + writeIndent(ts, indent + 1); + ts << "(transform "; ts << "[" << m_transform.m11() << " " << m_transform.m12() << " " << m_transform.m13() << " " << m_transform.m14() << "] "; ts << "[" << m_transform.m21() << " " << m_transform.m22() << " " << m_transform.m23() << " " << m_transform.m24() << "] "; ts << "[" << m_transform.m31() << " " << m_transform.m32() << " " << m_transform.m33() << " " << m_transform.m34() << "] "; - ts << "[" << m_transform.m41() << " " << m_transform.m42() << " " << m_transform.m43() << " " << m_transform.m44() << "]"; + ts << "[" << m_transform.m41() << " " << m_transform.m42() << " " << m_transform.m43() << " " << m_transform.m44() << "])\n"; } - ts << ")\n"; // Avoid dumping the sublayer transform on the root layer, because it's used for geometry flipping, whose behavior // differs between platforms. - if (parent()) { + if (parent() && !m_childrenTransform.isIdentity()) { writeIndent(ts, indent + 1); ts << "(childrenTransform "; - if (m_childrenTransform.isIdentity()) - ts << "identity"; - else { - ts << "[" << m_childrenTransform.m11() << " " << m_childrenTransform.m12() << " " << m_childrenTransform.m13() << " " << m_childrenTransform.m14() << "] "; - ts << "[" << m_childrenTransform.m21() << " " << m_childrenTransform.m22() << " " << m_childrenTransform.m23() << " " << m_childrenTransform.m24() << "] "; - ts << "[" << m_childrenTransform.m31() << " " << m_childrenTransform.m32() << " " << m_childrenTransform.m33() << " " << m_childrenTransform.m34() << "] "; - ts << "[" << m_childrenTransform.m41() << " " << m_childrenTransform.m42() << " " << m_childrenTransform.m43() << " " << m_childrenTransform.m44() << "]"; - } - ts << ")\n"; + ts << "[" << m_childrenTransform.m11() << " " << m_childrenTransform.m12() << " " << m_childrenTransform.m13() << " " << m_childrenTransform.m14() << "] "; + ts << "[" << m_childrenTransform.m21() << " " << m_childrenTransform.m22() << " " << m_childrenTransform.m23() << " " << m_childrenTransform.m24() << "] "; + ts << "[" << m_childrenTransform.m31() << " " << m_childrenTransform.m32() << " " << m_childrenTransform.m33() << " " << m_childrenTransform.m34() << "] "; + ts << "[" << m_childrenTransform.m41() << " " << m_childrenTransform.m42() << " " << m_childrenTransform.m43() << " " << m_childrenTransform.m44() << "])\n"; } if (m_replicaLayer) { diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h index 68a580e..04899f2 100644 --- a/WebCore/platform/graphics/GraphicsLayer.h +++ b/WebCore/platform/graphics/GraphicsLayer.h @@ -313,14 +313,7 @@ public: int repaintCount() const { return m_repaintCount; } int incrementRepaintCount() { return ++m_repaintCount; } - // Report whether the underlying compositing system uses a top-down - // or a bottom-up coordinate system. enum CompositingCoordinatesOrientation { CompositingCoordinatesTopDown, CompositingCoordinatesBottomUp }; - static CompositingCoordinatesOrientation compositingCoordinatesOrientation(); - - // Set the geometry orientation (top-down, or bottom-up) for this layer, which also controls sublayer geometry. - virtual void setGeometryOrientation(CompositingCoordinatesOrientation orientation) { m_geometryOrientation = orientation; } - CompositingCoordinatesOrientation geometryOrientation() const { return m_geometryOrientation; } // Flippedness of the contents of this layer. Does not affect sublayer geometry. virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation) { m_contentsOrientation = orientation; } @@ -395,8 +388,7 @@ protected: bool m_drawsContent : 1; GraphicsLayerPaintingPhase m_paintingPhase; - CompositingCoordinatesOrientation m_geometryOrientation; // affects geometry of layer positions - CompositingCoordinatesOrientation m_contentsOrientation; // affects orientation of layer contents + CompositingCoordinatesOrientation m_contentsOrientation; // affects orientation of layer contents Vector<GraphicsLayer*> m_children; GraphicsLayer* m_parent; diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index 2588d8d..b4a669c 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -48,7 +48,7 @@ #if PLATFORM(MAC) #include "MediaPlayerPrivateQTKit.h" #elif OS(WINCE) && !PLATFORM(QT) -#include "MediaPlayerPrivateWince.h" +#include "MediaPlayerPrivateWinCE.h" #elif PLATFORM(WIN) #include "MediaPlayerPrivateQuickTimeVisualContext.h" #include "MediaPlayerPrivateQuicktimeWin.h" diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h index 9896713..43ba889 100644 --- a/WebCore/platform/graphics/Path.h +++ b/WebCore/platform/graphics/Path.h @@ -133,11 +133,6 @@ namespace WebCore { void addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint); void addArcTo(const FloatPoint&, const FloatPoint&, float radius); void closeSubpath(); -#if PLATFORM(QT) - void closeCanvasSubpath(); -#else - void closeCanvasSubpath() { closeSubpath(); } -#endif void addArc(const FloatPoint&, float radius, float startAngle, float endAngle, bool anticlockwise); void addRect(const FloatRect&); @@ -161,10 +156,6 @@ namespace WebCore { private: PlatformPathPtr m_path; - -#if PLATFORM(QT) - int m_lastMoveToIndex; -#endif }; } diff --git a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp b/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp index 5d3263e..c09dd49 100644 --- a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp @@ -24,6 +24,7 @@ #include "CString.h" #include "Font.h" #include "OwnPtrCairo.h" +#include "PlatformRefPtrCairo.h" #include "SimpleFontData.h" #include <wtf/Assertions.h> @@ -37,7 +38,6 @@ void FontCache::platformInit() const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { -#if defined(USE_FREETYPE) FcResult fresult; FontPlatformData* prim = const_cast<FontPlatformData*>(&font.primaryFont()->platformData()); @@ -47,13 +47,13 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return 0; if (!prim->m_fallbacks) - prim->m_fallbacks = FcFontSort(NULL, prim->m_pattern, FcTrue, NULL, &fresult); + prim->m_fallbacks = FcFontSort(0, prim->m_pattern.get(), FcTrue, 0, &fresult); FcFontSet* fs = prim->m_fallbacks; for (int i = 0; i < fs->nfont; i++) { - FcPattern* fin = FcFontRenderPrepare(NULL, prim->m_pattern, fs->fonts[i]); - cairo_font_face_t* fontFace = cairo_ft_font_face_create_for_pattern(fin); + PlatformRefPtr<FcPattern> fin = adoptPlatformRef(FcFontRenderPrepare(0, prim->m_pattern.get(), fs->fonts[i])); + cairo_font_face_t* fontFace = cairo_ft_font_face_create_for_pattern(fin.get()); FontPlatformData alternateFont(fontFace, font.fontDescription().computedPixelSize(), false, false); cairo_font_face_destroy(fontFace); alternateFont.m_pattern = fin; @@ -61,7 +61,6 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons if (sfd->containsCharacters(characters, length)) return sfd; } -#endif return 0; } @@ -103,7 +102,6 @@ static bool isWellKnownFontName(const AtomicString family) FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) { -#if defined(USE_FREETYPE) // Handle generic family types specially, because fontconfig does not know them, but we have // code to fallback correctly in our platform data implementation. if (!family.length() || family.startsWith("-webkit-") @@ -115,7 +113,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD CString familyNameString = family.string().utf8(); const char* fcfamily = familyNameString.data(); - OwnPtr<FcPattern> pattern(FcPatternCreate()); + PlatformRefPtr<FcPattern> pattern = adoptPlatformRef(FcPatternCreate()); if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) return 0; @@ -130,7 +128,6 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD if (!fontSet->fonts) return 0; -#endif return new FontPlatformData(fontDescription, family); } diff --git a/WebCore/platform/graphics/cairo/FontPlatformData.h b/WebCore/platform/graphics/cairo/FontPlatformData.h index fc6b9f1..e5ffef2 100644 --- a/WebCore/platform/graphics/cairo/FontPlatformData.h +++ b/WebCore/platform/graphics/cairo/FontPlatformData.h @@ -1,11 +1,5 @@ /* - * This file is part of the internal font implementation. It should not be included by anyone other than - * FontMac.cpp, FontWin.cpp and Font.cpp. - * - * Copyright (C) 2006, 2007, 2008 Apple Inc. - * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com - * Copyright (C) 2007 Holger Hans Peter Freyther - * Copyright (C) 2007 Pioneer Research Center USA, Inc. + * Copyright (C) 2010 Igalia S.L. * All rights reserved. * * This library is free software; you can redistribute it and/or @@ -28,160 +22,12 @@ #ifndef FontPlatformData_h #define FontPlatformData_h -#include <wtf/Forward.h> -#include <cairo.h> -#include "FontDescription.h" -#include "GlyphBuffer.h" - -#if defined(USE_FREETYPE) -#include <cairo-ft.h> -#include <fontconfig/fcfreetype.h> -#elif defined(USE_PANGO) -#include <pango/pangocairo.h> -#elif PLATFORM(WIN) -#include <cairo-win32.h> -#include "RefCountedGDIHandle.h" -#include "StringImpl.h" -#else -#error "Must defined a font backend" -#endif - -#if PLATFORM(WIN) -typedef struct HFONT__* HFONT; -#endif -namespace WebCore { - -class FontPlatformData { -public: - FontPlatformData(WTF::HashTableDeletedValueType) #if defined(USE_FREETYPE) - : m_pattern(hashTableDeletedFontValue()) - , m_fallbacks(0) +#include "FontPlatformDataFreeType.h" #elif defined(USE_PANGO) - : m_context(0) - , m_font(hashTableDeletedFontValue()) +#include "FontPlatformDataPango.h" #elif PLATFORM(WIN) - : m_fontFace(0) - , m_useGDI(false) - , m_font(WTF::HashTableDeletedValue) -#else -#error "Must defined a font backend" +#include "FontPlatformDataCairoWin.h" #endif - , m_size(0) - , m_syntheticBold(false) - , m_syntheticOblique(false) - , m_scaledFont(0) - { } - FontPlatformData() -#if defined(USE_FREETYPE) - : m_pattern(0) - , m_fallbacks(0) -#elif defined(USE_PANGO) - : m_context(0) - , m_font(0) -#elif PLATFORM(WIN) - : m_fontFace(0) - , m_useGDI(false) -#else -#error "Must defined a font backend" -#endif - , m_size(0) - , m_syntheticBold(false) - , m_syntheticOblique(false) - , m_scaledFont(0) - { } - -#if PLATFORM(WIN) - FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI); -#else - FontPlatformData(const FontDescription&, const AtomicString& family); -#endif - - FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic); - FontPlatformData(float size, bool bold, bool italic); - FontPlatformData(const FontPlatformData&); - - ~FontPlatformData(); - -#if !PLATFORM(WIN) - static bool init(); -#else - HFONT hfont() const { return m_font->handle(); } - bool useGDI() const { return m_useGDI; } - cairo_font_face_t* fontFace() const { return m_fontFace; } -#endif - - bool isFixedPitch(); - float size() const { return m_size; } - void setSize(float size) { m_size = size; } - bool syntheticBold() const { return m_syntheticBold; } - bool syntheticOblique() const { return m_syntheticOblique; } - - cairo_scaled_font_t* scaledFont() const { return m_scaledFont; } - - unsigned hash() const - { -#if PLATFORM(WIN) - return m_font->hash(); -#else -#if defined(USE_FREETYPE) - if (m_pattern) - return FcPatternHash(m_pattern); -#endif - uintptr_t hashCodes[1] = { reinterpret_cast<uintptr_t>(m_scaledFont) }; - return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar)); -#endif - } - - bool operator==(const FontPlatformData&) const; - FontPlatformData& operator=(const FontPlatformData&); - bool isHashTableDeletedValue() const - { -#if defined(USE_FREETYPE) - return m_pattern == hashTableDeletedFontValue(); -#elif defined(USE_PANGO) - return m_font == hashTableDeletedFontValue(); -#elif PLATFORM(WIN) - return m_font.isHashTableDeletedValue(); -#endif - } - -#ifndef NDEBUG - String description() const; -#endif - -#if defined(USE_FREETYPE) - FcPattern* m_pattern; - FcFontSet* m_fallbacks; -#elif defined(USE_PANGO) - static PangoFontMap* m_fontMap; - static GHashTable* m_hashTable; - - PangoContext* m_context; - PangoFont* m_font; -#elif PLATFORM(WIN) -private: - void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); - - RefPtr<RefCountedGDIHandle<HFONT> > m_font; - cairo_font_face_t* m_fontFace; - bool m_useGDI; -#else -#error "Must defined a font backend" -#endif - float m_size; - bool m_syntheticBold; - bool m_syntheticOblique; - cairo_scaled_font_t* m_scaledFont; -private: -#if defined(USE_FREETYPE) - static FcPattern *hashTableDeletedFontValue() { return reinterpret_cast<FcPattern*>(-1); } -#elif defined(USE_PANGO) - static PangoFont *hashTableDeletedFontValue() { return reinterpret_cast<PangoFont*>(-1); } -#endif -}; - -} - -#endif +#endif // FontPlatformData_h diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp index 1f94f5a..7968966 100644 --- a/WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp @@ -39,12 +39,10 @@ namespace WebCore { FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName) - : m_pattern(0) - , m_fallbacks(0) + : m_fallbacks(0) , m_size(fontDescription.computedPixelSize()) , m_syntheticBold(false) , m_syntheticOblique(false) - , m_scaledFont(0) { FontPlatformData::init(); @@ -61,14 +59,14 @@ FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const int type = fontDescription.genericFamily(); - FcPattern* pattern = FcPatternCreate(); + PlatformRefPtr<FcPattern> pattern = adoptPlatformRef(FcPatternCreate()); cairo_font_face_t* fontFace; static const cairo_font_options_t* defaultOptions = cairo_font_options_create(); const cairo_font_options_t* options = NULL; cairo_matrix_t fontMatrix; - if (!FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) - goto freePattern; + if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) + return; switch (type) { case FontDescription::SerifFamily: @@ -89,31 +87,31 @@ FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const break; } - if (fcfamily && !FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) - goto freePattern; - if (!FcPatternAddInteger(pattern, FC_WEIGHT, fcweight)) - goto freePattern; - if (!FcPatternAddInteger(pattern, FC_SLANT, fcslant)) - goto freePattern; - if (!FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fcsize)) - goto freePattern; + if (fcfamily && !FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) + return; + if (!FcPatternAddInteger(pattern.get(), FC_WEIGHT, fcweight)) + return; + if (!FcPatternAddInteger(pattern.get(), FC_SLANT, fcslant)) + return; + if (!FcPatternAddDouble(pattern.get(), FC_PIXEL_SIZE, fcsize)) + return; - FcConfigSubstitute(NULL, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); + FcConfigSubstitute(0, pattern.get(), FcMatchPattern); + FcDefaultSubstitute(pattern.get()); FcResult fcresult; - m_pattern = FcFontMatch(NULL, pattern, &fcresult); + m_pattern = adoptPlatformRef(FcFontMatch(0, pattern.get(), &fcresult)); // FIXME: should we set some default font? if (!m_pattern) - goto freePattern; - fontFace = cairo_ft_font_face_create_for_pattern(m_pattern); + return; + fontFace = cairo_ft_font_face_create_for_pattern(m_pattern.get()); cairo_matrix_t ctm; cairo_matrix_init_scale(&fontMatrix, fontDescription.computedPixelSize(), fontDescription.computedPixelSize()); cairo_matrix_init_identity(&ctm); #if !PLATFORM(EFL) || ENABLE(GLIB_SUPPORT) if (GdkScreen* screen = gdk_screen_get_default()) - options = gdk_screen_get_font_options(screen); +gdk_screen_get_font_options(screen); #endif // gdk_screen_get_font_options() returns NULL if no default options are @@ -121,30 +119,23 @@ FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const if (!options) options = defaultOptions; - m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options); + m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options)); cairo_font_face_destroy(fontFace); - -freePattern: - FcPatternDestroy(pattern); } FontPlatformData::FontPlatformData(float size, bool bold, bool italic) - : m_pattern(0) - , m_fallbacks(0) + : m_fallbacks(0) , m_size(size) , m_syntheticBold(bold) , m_syntheticOblique(italic) - , m_scaledFont(0) { } FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic) - : m_pattern(0) - , m_fallbacks(0) + : m_fallbacks(0) , m_size(size) , m_syntheticBold(bold) , m_syntheticOblique(italic) - , m_scaledFont(0) { cairo_matrix_t fontMatrix; cairo_matrix_init_scale(&fontMatrix, size, size); @@ -163,7 +154,7 @@ FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool if (!options) options = defaultOptions; - m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options); + m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options)); } FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other) @@ -175,17 +166,7 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other) m_size = other.m_size; m_syntheticBold = other.m_syntheticBold; m_syntheticOblique = other.m_syntheticOblique; - - if (other.m_scaledFont) - cairo_scaled_font_reference(other.m_scaledFont); - if (m_scaledFont) - cairo_scaled_font_destroy(m_scaledFont); m_scaledFont = other.m_scaledFont; - - if (other.m_pattern) - FcPatternReference(other.m_pattern); - if (m_pattern) - FcPatternDestroy(m_pattern); m_pattern = other.m_pattern; if (m_fallbacks) { @@ -198,9 +179,7 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other) } FontPlatformData::FontPlatformData(const FontPlatformData& other) - : m_pattern(0) - , m_fallbacks(0) - , m_scaledFont(0) + : m_fallbacks(0) { *this = other; } @@ -220,18 +199,10 @@ bool FontPlatformData::init() FontPlatformData::~FontPlatformData() { - if (m_pattern && ((FcPattern*)-1 != m_pattern)) { - FcPatternDestroy(m_pattern); - m_pattern = 0; - } - if (m_fallbacks) { FcFontSetDestroy(m_fallbacks); m_fallbacks = 0; } - - if (m_scaledFont) - cairo_scaled_font_destroy(m_scaledFont); } bool FontPlatformData::isFixedPitch() @@ -241,7 +212,7 @@ bool FontPlatformData::isFixedPitch() return false; int spacing; - if (FcPatternGetInteger(m_pattern, FC_SPACING, 0, &spacing) == FcResultMatch) + if (FcPatternGetInteger(m_pattern.get(), FC_SPACING, 0, &spacing) == FcResultMatch) return spacing == FC_MONO; return false; } @@ -250,10 +221,9 @@ bool FontPlatformData::operator==(const FontPlatformData& other) const { if (m_pattern == other.m_pattern) return true; - if (m_pattern == 0 || m_pattern == reinterpret_cast<FcPattern*>(-1) - || other.m_pattern == 0 || other.m_pattern == reinterpret_cast<FcPattern*>(-1)) + if (!m_pattern || m_pattern.isHashTableDeletedValue() || !other.m_pattern || other.m_pattern.isHashTableDeletedValue()) return false; - return FcPatternEqual(m_pattern, other.m_pattern); + return FcPatternEqual(m_pattern.get(), other.m_pattern.get()); } #ifndef NDEBUG diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h new file mode 100644 index 0000000..987a684 --- /dev/null +++ b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2007 Pioneer Research Center USA, 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. + * + */ + +#ifndef FontPlatformDataFreeType_h +#define FontPlatformDataFreeType_h + +#include "FontDescription.h" +#include "GlyphBuffer.h" +#include "HashFunctions.h" +#include "PlatformRefPtrCairo.h" +#include <cairo-ft.h> +#include <cairo.h> +#include <fontconfig/fcfreetype.h> +#include <wtf/Forward.h> + +namespace WebCore { + +class FontPlatformData { +public: + FontPlatformData(WTF::HashTableDeletedValueType) + : m_fallbacks(0) + , m_size(0) + , m_syntheticBold(false) + , m_syntheticOblique(false) + , m_scaledFont(WTF::HashTableDeletedValue) + { } + + FontPlatformData() + : m_fallbacks(0) + , m_size(0) + , m_syntheticBold(false) + , m_syntheticOblique(false) + { } + + FontPlatformData(const FontDescription&, const AtomicString& family); + FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic); + FontPlatformData(float size, bool bold, bool italic); + FontPlatformData(const FontPlatformData&); + + ~FontPlatformData(); + + static bool init(); + bool isFixedPitch(); + float size() const { return m_size; } + void setSize(float size) { m_size = size; } + bool syntheticBold() const { return m_syntheticBold; } + bool syntheticOblique() const { return m_syntheticOblique; } + + cairo_scaled_font_t* scaledFont() const { return m_scaledFont.get(); } + + unsigned hash() const + { + return PtrHash<cairo_scaled_font_t*>::hash(m_scaledFont.get()); + } + + bool operator==(const FontPlatformData&) const; + FontPlatformData& operator=(const FontPlatformData&); + bool isHashTableDeletedValue() const + { + return m_scaledFont.isHashTableDeletedValue(); + } + +#ifndef NDEBUG + String description() const; +#endif + + PlatformRefPtr<FcPattern> m_pattern; + FcFontSet* m_fallbacks; + float m_size; + bool m_syntheticBold; + bool m_syntheticOblique; + PlatformRefPtr<cairo_scaled_font_t> m_scaledFont; +}; + +} + +#endif // FontPlatformDataFreeType_h diff --git a/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp index 7c9ffe6..26da68d 100644 --- a/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp +++ b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp @@ -42,7 +42,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b if (bufferLength > GlyphPage::size) return false; - FT_Face face = cairo_ft_scaled_font_lock_face(fontData->platformData().m_scaledFont); + FT_Face face = cairo_ft_scaled_font_lock_face(fontData->platformData().m_scaledFont.get()); if (!face) return false; @@ -57,7 +57,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b } } - cairo_ft_scaled_font_unlock_face(fontData->platformData().m_scaledFont); + cairo_ft_scaled_font_unlock_face(fontData->platformData().m_scaledFont.get()); return haveGlyphs; } diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 283e75a..5de7e1f 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -38,6 +38,7 @@ #include "FEGaussianBlur.h" #include "FloatRect.h" #include "Font.h" +#include "OwnPtrCairo.h" #include "ImageBuffer.h" #include "ImageBufferFilter.h" #include "IntRect.h" @@ -201,7 +202,6 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva // Calculate filter values to create appropriate shadow. cairo_t* cr = context->platformContext(); - cairo_path_t* path = cairo_copy_path(cr); double x0, x1, y0, y1; if (strokeShadow) cairo_stroke_extents(cr, &x0, &y0, &x1, &y1); @@ -214,15 +214,32 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva float radius = 0; GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur); + cairo_clip_extents(cr, &x0, &y0, &x1, &y1); + FloatRect clipRect(x0, y0, x1 - x0, y1 - y0); + + FloatPoint rectLocation = shadowRect.location(); + + // Reduce the shadow rect using the clip area. + if (!clipRect.contains(shadowRect)) { + shadowRect.intersect(clipRect); + if (shadowRect.isEmpty()) + return; + shadowRect.inflate(radius); + shadowBufferSize = IntSize(shadowRect.width(), shadowRect.height()); + } + + shadowOffset = rectLocation - shadowRect.location(); + // Create suitably-sized ImageBuffer to hold the shadow. OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); // Draw shadow into a new ImageBuffer. cairo_t* shadowContext = shadowBuffer->context()->platformContext(); copyContextProperties(cr, shadowContext); - cairo_translate(shadowContext, -rect.x() + radius, -rect.y() + radius); + cairo_translate(shadowContext, -rect.x() + radius + shadowOffset.width(), -rect.y() + radius + shadowOffset.height()); cairo_new_path(shadowContext); - cairo_append_path(shadowContext, path); + OwnPtr<cairo_path_t> path(cairo_copy_path(cr)); + cairo_append_path(shadowContext, path.get()); if (fillShadow) setPlatformFill(context, shadowContext, gcp); @@ -624,6 +641,12 @@ void GraphicsContext::fillRect(const FloatRect& rect) static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& rect, const Color& rectColor) { #if ENABLE(FILTERS) + FloatSize shadowOffset; + float shadowBlur; + Color shadowColor; + if (!context->getShadow(shadowOffset, shadowBlur, shadowColor)) + return; + AffineTransform transform = context->getCTM(); // drawTiledShadow still does not work with rotations. if ((transform.isIdentityOrTranslationOrFlipped())) { @@ -638,13 +661,6 @@ static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& return; } - FloatSize shadowOffset; - float shadowBlur; - Color shadowColor; - - if (!context->getShadow(shadowOffset, shadowBlur, shadowColor)) - return; - IntSize shadowBufferSize; FloatRect shadowRect; float radius = 0; @@ -957,18 +973,20 @@ PlatformRefPtr<cairo_surface_t> GraphicsContext::createShadowMask(PassOwnPtr<Ima return buffer->m_data.m_surface; FloatPoint blurRadius = FloatPoint(radius, radius); - float sd = FEGaussianBlur::calculateStdDeviation(radius); - if (!sd) + float stdDeviation = FEGaussianBlur::calculateStdDeviation(radius); + if (!stdDeviation) return buffer->m_data.m_surface; // create filter RefPtr<Filter> filter = ImageBufferFilter::create(); filter->setSourceImage(buffer); RefPtr<FilterEffect> source = SourceGraphic::create(); - source->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size())); + source->setRepaintRectInLocalCoordinates(FloatRect(FloatPoint(), shadowRect.size())); source->setIsAlphaImage(true); - RefPtr<FilterEffect> blur = FEGaussianBlur::create(source.get(), sd, sd); - blur->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size())); + RefPtr<FilterEffect> blur = FEGaussianBlur::create(stdDeviation, stdDeviation); + FilterEffectVector& inputEffects = blur->inputEffects(); + inputEffects.append(source.get()); + blur->setRepaintRectInLocalCoordinates(FloatRect(FloatPoint(), shadowRect.size())); blur->apply(filter.get()); return blur->resultImage()->m_data.m_surface; #endif diff --git a/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp b/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp index 9be8670..94f6809 100644 --- a/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp +++ b/WebCore/platform/graphics/cairo/OwnPtrCairo.cpp @@ -25,15 +25,11 @@ #include <fontconfig/fcfreetype.h> #endif +#include <cairo.h> + namespace WTF { #if defined(USE_FREETYPE) -template <> void deleteOwnedPtr<FcPattern>(FcPattern* ptr) -{ - if (ptr) - FcPatternDestroy(ptr); -} - template <> void deleteOwnedPtr<FcObjectSet>(FcObjectSet* ptr) { if (ptr) @@ -47,4 +43,10 @@ template <> void deleteOwnedPtr<FcFontSet>(FcFontSet* ptr) } #endif +template <> void deleteOwnedPtr<cairo_path_t>(cairo_path_t* ptr) +{ + if (ptr) + cairo_path_destroy(ptr); +} + } // namespace WTF diff --git a/WebCore/platform/graphics/cairo/OwnPtrCairo.h b/WebCore/platform/graphics/cairo/OwnPtrCairo.h index 29f4562..035d80e 100644 --- a/WebCore/platform/graphics/cairo/OwnPtrCairo.h +++ b/WebCore/platform/graphics/cairo/OwnPtrCairo.h @@ -23,19 +23,21 @@ #include "OwnPtr.h" #if defined(USE_FREETYPE) -typedef struct _FcPattern FcPattern; typedef struct _FcObjectSet FcObjectSet; typedef struct _FcFontSet FcFontSet; #endif +typedef struct cairo_path cairo_path_t; + namespace WTF { #if defined(USE_FREETYPE) -template <> void deleteOwnedPtr<FcPattern>(FcPattern*); template <> void deleteOwnedPtr<FcObjectSet>(FcObjectSet*); template <> void deleteOwnedPtr<FcFontSet>(FcFontSet*); #endif +template <> void deleteOwnedPtr<cairo_path_t>(cairo_path_t*); + } // namespace WTF #endif diff --git a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp index 6870560..aa466f9 100644 --- a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp +++ b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp @@ -21,6 +21,11 @@ #include <cairo.h> +#if defined(USE_FREETYPE) +#include <cairo-ft.h> +#include <fontconfig/fcfreetype.h> +#endif + namespace WTF { template <> cairo_t* refPlatformPtr(cairo_t* ptr) @@ -49,4 +54,32 @@ template <> void derefPlatformPtr(cairo_surface_t* ptr) cairo_surface_destroy(ptr); } +template <> cairo_scaled_font_t* refPlatformPtr(cairo_scaled_font_t* ptr) +{ + if (ptr) + cairo_scaled_font_reference(ptr); + return ptr; +} + +template <> void derefPlatformPtr(cairo_scaled_font_t* ptr) +{ + if (ptr) + cairo_scaled_font_destroy(ptr); +} + +#if defined(USE_FREETYPE) +template <> FcPattern* refPlatformPtr(FcPattern* ptr) +{ + if (ptr) + FcPatternReference(ptr); + return ptr; +} + +template <> void derefPlatformPtr(FcPattern* ptr) +{ + if (ptr) + FcPatternDestroy(ptr); +} +#endif + } diff --git a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h index 51d8fa9..4b45c1b 100644 --- a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h +++ b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h @@ -24,6 +24,11 @@ typedef struct _cairo cairo_t; typedef struct _cairo_surface cairo_surface_t; +typedef struct _cairo_scaled_font cairo_scaled_font_t; + +#if defined(USE_FREETYPE) +typedef struct _FcPattern FcPattern; +#endif namespace WTF { @@ -33,6 +38,14 @@ template <> void derefPlatformPtr(cairo_t* ptr); template <> cairo_surface_t* refPlatformPtr(cairo_surface_t* ptr); template <> void derefPlatformPtr(cairo_surface_t* ptr); +template <> cairo_scaled_font_t* refPlatformPtr(cairo_scaled_font_t*); +template <> void derefPlatformPtr(cairo_scaled_font_t*); + +#if defined(USE_FREETYPE) +template <> FcPattern* refPlatformPtr(FcPattern*); +template <> void derefPlatformPtr(FcPattern*); +#endif + } #endif diff --git a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp index 0055078..fd85d6f 100644 --- a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp +++ b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp @@ -47,7 +47,7 @@ void SimpleFontData::platformInit() { cairo_font_extents_t font_extents; cairo_text_extents_t text_extents; - cairo_scaled_font_extents(m_platformData.m_scaledFont, &font_extents); + cairo_scaled_font_extents(m_platformData.m_scaledFont.get(), &font_extents); m_ascent = static_cast<int>(lroundf(font_extents.ascent)); m_descent = static_cast<int>(lroundf(font_extents.descent)); m_lineSpacing = static_cast<int>(lroundf(font_extents.height)); @@ -58,9 +58,9 @@ void SimpleFontData::platformInit() // while we figure out what's going on. if (m_lineSpacing < m_ascent + m_descent) m_lineSpacing = m_ascent + m_descent; - cairo_scaled_font_text_extents(m_platformData.m_scaledFont, "x", &text_extents); + cairo_scaled_font_text_extents(m_platformData.m_scaledFont.get(), "x", &text_extents); m_xHeight = text_extents.height; - cairo_scaled_font_text_extents(m_platformData.m_scaledFont, " ", &text_extents); + cairo_scaled_font_text_extents(m_platformData.m_scaledFont.get(), " ", &text_extents); m_spaceWidth = static_cast<float>(text_extents.x_advance); m_lineGap = m_lineSpacing - m_ascent - m_descent; m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f; @@ -92,19 +92,19 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { - FT_Face face = cairo_ft_scaled_font_lock_face(m_platformData.m_scaledFont); + FT_Face face = cairo_ft_scaled_font_lock_face(m_platformData.m_scaledFont.get()); if (!face) return false; for (int i = 0; i < length; i++) { if (FcFreeTypeCharIndex(face, characters[i]) == 0) { - cairo_ft_scaled_font_unlock_face(m_platformData.m_scaledFont); + cairo_ft_scaled_font_unlock_face(m_platformData.m_scaledFont.get()); return false; } } - cairo_ft_scaled_font_unlock_face(m_platformData.m_scaledFont); + cairo_ft_scaled_font_unlock_face(m_platformData.m_scaledFont.get()); return true; } @@ -125,10 +125,10 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const cairo_glyph_t cglyph = { glyph, 0, 0 }; cairo_text_extents_t extents; - cairo_scaled_font_glyph_extents(m_platformData.m_scaledFont, &cglyph, 1, &extents); + cairo_scaled_font_glyph_extents(m_platformData.m_scaledFont.get(), &cglyph, 1, &extents); float w = (float)m_spaceWidth; - if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0) + if (cairo_scaled_font_status(m_platformData.m_scaledFont.get()) == CAIRO_STATUS_SUCCESS && extents.x_advance) w = (float)extents.x_advance; return w; diff --git a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp index 9826c3e..c2cde19 100644 --- a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp @@ -35,8 +35,7 @@ #include "Canvas2DLayerChromium.h" #include "DrawingBuffer.h" - -#include <GLES2/gl2.h> +#include "GraphicsContext3D.h" namespace WebCore { @@ -54,7 +53,7 @@ Canvas2DLayerChromium::Canvas2DLayerChromium(DrawingBuffer* drawingBuffer, Graph Canvas2DLayerChromium::~Canvas2DLayerChromium() { if (m_textureId) - glDeleteTextures(1, &m_textureId); + layerRendererContext()->deleteTexture(m_textureId); } void Canvas2DLayerChromium::updateContents() @@ -62,26 +61,27 @@ void Canvas2DLayerChromium::updateContents() if (!m_drawingBuffer) return; if (m_textureChanged) { // We have to generate a new backing texture. + GraphicsContext3D* context = layerRendererContext(); if (m_textureId) - glDeleteTextures(1, &m_textureId); - glGenTextures(1, &m_textureId); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_textureId); + context->deleteTexture(m_textureId); + m_textureId = context->createTexture(); + context->activeTexture(GraphicsContext3D::TEXTURE0); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId); IntSize size = m_drawingBuffer->size(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - // Set the min-mag filters to linear and wrap modes to GL_CLAMP_TO_EDGE + context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0); + // Set the min-mag filters to linear and wrap modes to GraphicsContext3D::CLAMP_TO_EDGE // to get around NPOT texture limitations of GLES. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); m_textureChanged = false; - // FIXME: The glFinish() here is required because we have to make sure that the texture created in this + // FIXME: The finish() here is required because we have to make sure that the texture created in this // context (the compositor context) is actually created by the service side before the child context - // attempts to use it (in publishToPlatformLayer). glFinish() is currently the only call with strong + // attempts to use it (in publishToPlatformLayer). finish() is currently the only call with strong // enough semantics to promise this, but is actually much stronger. Ideally we'd do something like // inserting a fence here and waiting for it before trying to publish. - glFinish(); + context->finish(); } // Update the contents of the texture used by the compositor. if (m_contentsDirty) { diff --git a/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp b/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp index 56a7262..4aef25b 100644 --- a/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp @@ -34,16 +34,16 @@ #include "CanvasLayerChromium.h" +#include "GraphicsContext3D.h" #include "LayerRendererChromium.h" -#include <GLES2/gl2.h> - namespace WebCore { unsigned CanvasLayerChromium::m_shaderProgramId = 0; -CanvasLayerChromium::SharedValues::SharedValues() - : m_canvasShaderProgram(0) +CanvasLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) + : m_context(context) + , m_canvasShaderProgram(0) , m_shaderSamplerLocation(-1) , m_shaderMatrixLocation(-1) , m_shaderAlphaLocation(-1) @@ -73,15 +73,15 @@ CanvasLayerChromium::SharedValues::SharedValues() " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" "} \n"; - m_canvasShaderProgram = createShaderProgram(vertexShaderString, fragmentShaderString); + m_canvasShaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString); if (!m_canvasShaderProgram) { LOG_ERROR("CanvasLayerChromium: Failed to create shader program"); return; } - m_shaderSamplerLocation = glGetUniformLocation(m_canvasShaderProgram, "s_texture"); - m_shaderMatrixLocation = glGetUniformLocation(m_canvasShaderProgram, "matrix"); - m_shaderAlphaLocation = glGetUniformLocation(m_canvasShaderProgram, "alpha"); + m_shaderSamplerLocation = m_context->getUniformLocation(m_canvasShaderProgram, "s_texture"); + m_shaderMatrixLocation = m_context->getUniformLocation(m_canvasShaderProgram, "matrix"); + m_shaderAlphaLocation = m_context->getUniformLocation(m_canvasShaderProgram, "alpha"); ASSERT(m_shaderSamplerLocation != -1); ASSERT(m_shaderMatrixLocation != -1); ASSERT(m_shaderAlphaLocation != -1); @@ -92,7 +92,7 @@ CanvasLayerChromium::SharedValues::SharedValues() CanvasLayerChromium::SharedValues::~SharedValues() { if (m_canvasShaderProgram) - GLC(glDeleteProgram(m_canvasShaderProgram)); + GLC(m_context, m_context->deleteProgram(m_canvasShaderProgram)); } CanvasLayerChromium::CanvasLayerChromium(GraphicsLayerChromium* owner) @@ -111,11 +111,12 @@ void CanvasLayerChromium::draw() ASSERT(layerRenderer()); const CanvasLayerChromium::SharedValues* sv = layerRenderer()->canvasLayerSharedValues(); ASSERT(sv && sv->initialized()); - GLC(glActiveTexture(GL_TEXTURE0)); - GLC(glBindTexture(GL_TEXTURE_2D, m_textureId)); + GraphicsContext3D* context = layerRendererContext(); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); layerRenderer()->useShader(sv->canvasShaderProgram()); - GLC(glUniform1i(sv->shaderSamplerLocation(), 0)); - drawTexturedQuad(layerRenderer()->projectionMatrix(), drawTransform(), + GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0)); + drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), bounds().width(), bounds().height(), drawOpacity(), sv->shaderMatrixLocation(), sv->shaderAlphaLocation()); diff --git a/WebCore/platform/graphics/chromium/CanvasLayerChromium.h b/WebCore/platform/graphics/chromium/CanvasLayerChromium.h index d591c73..6520b55 100644 --- a/WebCore/platform/graphics/chromium/CanvasLayerChromium.h +++ b/WebCore/platform/graphics/chromium/CanvasLayerChromium.h @@ -47,7 +47,7 @@ public: class SharedValues { public: - SharedValues(); + explicit SharedValues(GraphicsContext3D*); ~SharedValues(); unsigned canvasShaderProgram() const { return m_canvasShaderProgram; } @@ -57,6 +57,7 @@ public: bool initialized() const { return m_initialized; } private: + GraphicsContext3D* m_context; unsigned m_canvasShaderProgram; int m_shaderSamplerLocation; int m_shaderMatrixLocation; diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp index 48119bb..86be8da 100644 --- a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp @@ -34,6 +34,7 @@ #include "ContentLayerChromium.h" +#include "GraphicsContext3D.h" #include "LayerRendererChromium.h" #include "RenderLayerBacking.h" @@ -47,12 +48,11 @@ #include <CoreGraphics/CGBitmapContext.h> #endif -#include <GLES2/gl2.h> - namespace WebCore { -ContentLayerChromium::SharedValues::SharedValues() - : m_contentShaderProgram(0) +ContentLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) + : m_context(context) + , m_contentShaderProgram(0) , m_shaderSamplerLocation(-1) , m_shaderMatrixLocation(-1) , m_shaderAlphaLocation(-1) @@ -71,8 +71,8 @@ ContentLayerChromium::SharedValues::SharedValues() "} \n"; // Note differences between Skia and Core Graphics versions: - // - Skia uses BGRA and origin is upper left - // - Core Graphics uses RGBA and origin is lower left + // - Skia uses BGRA + // - Core Graphics uses RGBA char fragmentShaderString[] = "precision mediump float; \n" "varying vec2 v_texCoord; \n" @@ -80,26 +80,25 @@ ContentLayerChromium::SharedValues::SharedValues() "uniform float alpha; \n" "void main() \n" "{ \n" -#if PLATFORM(SKIA) " vec4 texColor = texture2D(s_texture, v_texCoord); \n" +#if PLATFORM(SKIA) " gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; \n" #elif PLATFORM(CG) - " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n" " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" #else #error "Need to implement for your platform." #endif "} \n"; - m_contentShaderProgram = createShaderProgram(vertexShaderString, fragmentShaderString); + m_contentShaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString); if (!m_contentShaderProgram) { LOG_ERROR("ContentLayerChromium: Failed to create shader program"); return; } - m_shaderSamplerLocation = glGetUniformLocation(m_contentShaderProgram, "s_texture"); - m_shaderMatrixLocation = glGetUniformLocation(m_contentShaderProgram, "matrix"); - m_shaderAlphaLocation = glGetUniformLocation(m_contentShaderProgram, "alpha"); + m_shaderSamplerLocation = m_context->getUniformLocation(m_contentShaderProgram, "s_texture"); + m_shaderMatrixLocation = m_context->getUniformLocation(m_contentShaderProgram, "matrix"); + m_shaderAlphaLocation = m_context->getUniformLocation(m_contentShaderProgram, "alpha"); ASSERT(m_shaderSamplerLocation != -1); ASSERT(m_shaderMatrixLocation != -1); ASSERT(m_shaderAlphaLocation != -1); @@ -110,7 +109,7 @@ ContentLayerChromium::SharedValues::SharedValues() ContentLayerChromium::SharedValues::~SharedValues() { if (m_contentShaderProgram) - GLC(glDeleteProgram(m_contentShaderProgram)); + GLC(m_context, m_context->deleteProgram(m_contentShaderProgram)); } @@ -128,7 +127,7 @@ ContentLayerChromium::ContentLayerChromium(GraphicsLayerChromium* owner) ContentLayerChromium::~ContentLayerChromium() { if (m_contentsTexture) - GLC(glDeleteTextures(1, &m_contentsTexture)); + GLC(layerRendererContext(), layerRendererContext()->deleteTexture(m_contentsTexture)); } @@ -207,11 +206,13 @@ void ContentLayerChromium::updateContents() dirtyRect.width(), dirtyRect.height(), 8, rowBytes, colorSpace.get(), kCGImageAlphaPremultipliedLast)); + CGContextTranslateCTM(contextCG.get(), 0, dirtyRect.height()); + CGContextScaleCTM(contextCG.get(), 1, -1); GraphicsContext graphicsContext(contextCG.get()); LocalCurrentGraphicsContext scopedNSGraphicsContext(&graphicsContext); - // Translate the graphics contxt into the coordinate system of the dirty rect. + // Translate the graphics context into the coordinate system of the dirty rect. graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y()); m_owner->paintGraphicsLayerContents(graphicsContext, dirtyRect); @@ -235,30 +236,21 @@ void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& bitmap if (!pixels) return; - glBindTexture(GL_TEXTURE_2D, textureId); + GraphicsContext3D* context = layerRendererContext(); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); // If the texture id or size changed since last time then we need to tell GL // to re-allocate a texture. if (m_contentsTexture != textureId || requiredTextureSize != m_allocatedTextureSize) { ASSERT(bitmapSize == requiredTextureSize); - GLC(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); + GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels)); m_contentsTexture = textureId; m_allocatedTextureSize = requiredTextureSize; } else { ASSERT(updateRect.width() <= m_allocatedTextureSize.width() && updateRect.height() <= m_allocatedTextureSize.height()); ASSERT(updateRect.width() == bitmapSize.width() && updateRect.height() == bitmapSize.height()); -#if PLATFORM(CG) - // The origin is at the lower left in Core Graphics' coordinate system. We need to correct for this here. - GLC(glTexSubImage2D(GL_TEXTURE_2D, 0, - updateRect.x(), m_allocatedTextureSize.height() - updateRect.height() - updateRect.y(), - updateRect.width(), updateRect.height(), - GL_RGBA, GL_UNSIGNED_BYTE, pixels)); -#elif PLATFORM(SKIA) - GLC(glTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels)); -#else -#error "Need to implement for your platform." -#endif + GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels)); } m_dirtyRect.setSize(FloatSize()); @@ -273,11 +265,12 @@ void ContentLayerChromium::draw() ASSERT(layerRenderer()); const ContentLayerChromium::SharedValues* sv = layerRenderer()->contentLayerSharedValues(); ASSERT(sv && sv->initialized()); - GLC(glActiveTexture(GL_TEXTURE0)); - GLC(glBindTexture(GL_TEXTURE_2D, m_contentsTexture)); + GraphicsContext3D* context = layerRendererContext(); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTexture)); layerRenderer()->useShader(sv->contentShaderProgram()); - GLC(glUniform1i(sv->shaderSamplerLocation(), 0)); - drawTexturedQuad(layerRenderer()->projectionMatrix(), drawTransform(), + GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0)); + drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), bounds().width(), bounds().height(), drawOpacity(), sv->shaderMatrixLocation(), sv->shaderAlphaLocation()); } diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/WebCore/platform/graphics/chromium/ContentLayerChromium.h index 3e15372..42a77c7 100644 --- a/WebCore/platform/graphics/chromium/ContentLayerChromium.h +++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.h @@ -44,7 +44,7 @@ class ContentLayerChromium : public LayerChromium { public: static PassRefPtr<ContentLayerChromium> create(GraphicsLayerChromium* owner = 0); - ~ContentLayerChromium(); + virtual ~ContentLayerChromium(); virtual void updateContents(); virtual void draw(); @@ -55,7 +55,7 @@ public: // context). class SharedValues { public: - SharedValues(); + explicit SharedValues(GraphicsContext3D*); ~SharedValues(); unsigned contentShaderProgram() const { return m_contentShaderProgram; } @@ -65,6 +65,7 @@ public: int initialized() const { return m_initialized; } private: + GraphicsContext3D* m_context; unsigned m_contentShaderProgram; int m_shaderSamplerLocation; int m_shaderMatrixLocation; diff --git a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp index 64981ee..9ce0efe 100644 --- a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp +++ b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp @@ -39,12 +39,6 @@ #include "Canvas2DLayerChromium.h" #endif -#include <GLES2/gl2.h> -#ifndef GL_GLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES 1 -#endif -#include <GLES2/gl2ext.h> - namespace WebCore { struct DrawingBufferInternal { @@ -105,8 +99,8 @@ void DrawingBuffer::publishToPlatformLayer() // happens before the compositor draws. This means we might draw stale frames sometimes. Ideally this // would insert a fence into the child command stream that the compositor could wait for. m_context->makeContextCurrent(); - glCopyTextureToParentTexture(m_internal->offscreenColorTexture, parentTexture); - glFlush(); + m_context->copyTextureToParentTextureCHROMIUM(m_internal->offscreenColorTexture, parentTexture); + m_context->flush(); } #endif diff --git a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp index 2fda22d..4399d35 100644 --- a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp @@ -43,7 +43,6 @@ #include "SkTypeface.h" #include "SkUtils.h" -#include <unicode/utf16.h> #include <wtf/Assertions.h> #include <wtf/text/AtomicString.h> #include <wtf/text/CString.h> diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index bbae72a..21dcd8e 100644 --- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -84,11 +84,6 @@ static void clearLayerBackgroundColor(LayerChromium& layer) layer.setBackgroundColor(static_cast<RGBA32>(0)); } -GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation() -{ - return CompositingCoordinatesBottomUp; -} - PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return new GraphicsLayerChromium(client); @@ -324,7 +319,6 @@ void GraphicsLayerChromium::setContentsToImage(Image* image) { bool childrenChanged = false; if (image) { - NativeImagePtr nativeImage = image->nativeImageForCurrentFrame(); if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForImage) { RefPtr<ImageLayerChromium> imageLayer = ImageLayerChromium::create(this); setupContentsLayer(imageLayer.get()); @@ -333,7 +327,7 @@ void GraphicsLayerChromium::setContentsToImage(Image* image) childrenChanged = true; } ImageLayerChromium* imageLayer = static_cast<ImageLayerChromium*>(m_contentsLayer.get()); - imageLayer->setContents(nativeImage); + imageLayer->setContents(image); updateContentsRect(); } else { if (m_contentsLayer) { @@ -400,15 +394,6 @@ void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer) updateSublayerList(); } -void GraphicsLayerChromium::setGeometryOrientation(CompositingCoordinatesOrientation orientation) -{ - if (orientation == m_geometryOrientation) - return; - - GraphicsLayer::setGeometryOrientation(orientation); - updateGeometryOrientation(); -} - PlatformLayer* GraphicsLayerChromium::hostLayerForSublayers() const { return m_transformLayer ? m_transformLayer.get() : m_layer.get(); @@ -625,21 +610,6 @@ void GraphicsLayerChromium::updateContentsRect() m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height())); } -void GraphicsLayerChromium::updateGeometryOrientation() -{ - switch (geometryOrientation()) { - case CompositingCoordinatesTopDown: - m_layer->setGeometryFlipped(false); - break; - - case CompositingCoordinatesBottomUp: - m_layer->setGeometryFlipped(true); - break; - } - // Geometry orientation is mapped onto children transform in older QuartzCores, - // so is handled via setGeometryOrientation(). -} - void GraphicsLayerChromium::setupContentsLayer(LayerChromium* contentsLayer) { if (contentsLayer == m_contentsLayer) diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h index dde443d..214058d 100644 --- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h @@ -94,8 +94,6 @@ public: virtual void setDebugBackgroundColor(const Color&); virtual void setDebugBorder(const Color&, float borderWidth); - virtual void setGeometryOrientation(CompositingCoordinatesOrientation); - void notifySyncRequired() { if (m_client) @@ -125,7 +123,6 @@ private: void updateContentsImage(); void updateContentsVideo(); void updateContentsRect(); - void updateGeometryOrientation(); void setupContentsLayer(LayerChromium*); LayerChromium* contentsLayer() const { return m_contentsLayer.get(); } diff --git a/WebCore/platform/graphics/chromium/ImageChromium.cpp b/WebCore/platform/graphics/chromium/ImageChromium.cpp new file mode 100644 index 0000000..e90d566 --- /dev/null +++ b/WebCore/platform/graphics/chromium/ImageChromium.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008-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 "Image.h" + +#include "ChromiumBridge.h" + +namespace WebCore { + +// Other Image methods are implemented in ImageSkia.cpp + +PassRefPtr<Image> Image::loadPlatformResource(const char *name) +{ + return ChromiumBridge::loadPlatformImageResource(name); +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp index 060bb46..c97be82 100644 --- a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp @@ -34,6 +34,7 @@ #include "ImageLayerChromium.h" +#include "Image.h" #include "LayerRendererChromium.h" #if PLATFORM(SKIA) @@ -61,7 +62,7 @@ ImageLayerChromium::ImageLayerChromium(GraphicsLayerChromium* owner) { } -void ImageLayerChromium::setContents(NativeImagePtr contents) +void ImageLayerChromium::setContents(Image* contents) { // Check if the image has changed. if (m_contents == contents) @@ -75,13 +76,14 @@ void ImageLayerChromium::updateContents() ASSERT(layerRenderer()); void* pixels = 0; - IntRect dirtyRect(m_dirtyRect); IntSize requiredTextureSize; IntSize bitmapSize; + NativeImagePtr nativeImage = m_contents->nativeImageForCurrentFrame(); + #if PLATFORM(SKIA) // The layer contains an Image. - NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(m_contents); + NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(nativeImage); const SkBitmap* skiaBitmap = skiaImage; requiredTextureSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); ASSERT(skiaBitmap); @@ -95,9 +97,8 @@ void ImageLayerChromium::updateContents() } #elif PLATFORM(CG) // NativeImagePtr is a CGImageRef on Mac OS X. - CGImageRef cgImage = m_contents; - int width = CGImageGetWidth(cgImage); - int height = CGImageGetHeight(cgImage); + int width = CGImageGetWidth(nativeImage); + int height = CGImageGetHeight(nativeImage); requiredTextureSize = IntSize(width, height); bitmapSize = requiredTextureSize; // FIXME: we should get rid of this temporary copy where possible. @@ -109,7 +110,7 @@ void ImageLayerChromium::updateContents() // Try to reuse the color space from the image to preserve its colors. // Some images use a color space (such as indexed) unsupported by the bitmap context. RetainPtr<CGColorSpaceRef> colorSpaceReleaser; - CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage); + CGColorSpaceRef colorSpace = CGImageGetColorSpace(nativeImage); CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace); switch (colorSpaceModel) { case kCGColorSpaceModelMonochrome: @@ -130,7 +131,7 @@ void ImageLayerChromium::updateContents() CGContextSetBlendMode(tempContext.get(), kCGBlendModeCopy); CGContextDrawImage(tempContext.get(), CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)), - cgImage); + nativeImage); pixels = tempVector.data(); #else #error "Need to implement for your platform." @@ -146,6 +147,10 @@ void ImageLayerChromium::updateContents() if (!textureId) textureId = layerRenderer()->createLayerTexture(); + // Clip the dirty rect to the bitmap dimensions. + IntRect dirtyRect(m_dirtyRect); + dirtyRect.intersect(IntRect(IntPoint(0, 0), bitmapSize)); + if (pixels) updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId); } diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/WebCore/platform/graphics/chromium/ImageLayerChromium.h index e95284c..b91f04a 100644 --- a/WebCore/platform/graphics/chromium/ImageLayerChromium.h +++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.h @@ -36,8 +36,14 @@ #include "ContentLayerChromium.h" +#if PLATFORM(CG) +#include <wtf/RetainPtr.h> +#endif + namespace WebCore { +class Image; + // A Layer that contains only an Image element. class ImageLayerChromium : public ContentLayerChromium { public: @@ -46,11 +52,12 @@ public: virtual void updateContents(); virtual bool drawsContent() { return m_contents; } - void setContents(NativeImagePtr); + void setContents(Image* image); private: ImageLayerChromium(GraphicsLayerChromium* owner); - NativeImagePtr m_contents; + + RefPtr<Image> m_contents; }; } diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index 6519f1f..e36c69d 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -34,6 +34,7 @@ #include "LayerChromium.h" +#include "GraphicsContext3D.h" #include "LayerRendererChromium.h" #if PLATFORM(SKIA) #include "NativeImageSkia.h" @@ -41,8 +42,7 @@ #endif #include "RenderLayerBacking.h" #include "skia/ext/platform_canvas.h" - -#include <GLES2/gl2.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -51,24 +51,26 @@ using namespace std; const unsigned LayerChromium::s_positionAttribLocation = 0; const unsigned LayerChromium::s_texCoordAttribLocation = 1; -static GLuint loadShader(GLenum type, const char* shaderSource) +static unsigned loadShader(GraphicsContext3D* context, unsigned type, const char* shaderSource) { - GLuint shader = glCreateShader(type); + unsigned shader = context->createShader(type); if (!shader) return 0; - GLC(glShaderSource(shader, 1, &shaderSource, 0)); - GLC(glCompileShader(shader)); - GLint compiled; - GLC(glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled)); + String sourceString(shaderSource); + GLC(context, context->shaderSource(shader, sourceString)); + GLC(context, context->compileShader(shader)); + int compiled; + GLC(context, context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled)); if (!compiled) { - GLC(glDeleteShader(shader)); + GLC(context, context->deleteShader(shader)); return 0; } return shader; } -LayerChromium::SharedValues::SharedValues() - : m_quadVerticesVbo(0) +LayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) + : m_context(context) + , m_quadVerticesVbo(0) , m_quadElementsVbo(0) , m_maxTextureSize(0) , m_borderShaderProgram(0) @@ -77,24 +79,22 @@ LayerChromium::SharedValues::SharedValues() , m_initialized(false) { // Vertex positions and texture coordinates for the 4 corners of a 1x1 quad. - GLfloat vertices[] = { -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.0f, 1.0f, 1.0f }; - GLushort indices[] = { 0, 1, 2, 0, 2, 3, // The two triangles that make up the layer quad. + float vertices[] = { -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.0f, 1.0f, 1.0f }; + uint16_t indices[] = { 0, 1, 2, 0, 2, 3, // The two triangles that make up the layer quad. 0, 1, 2, 3}; // A line path for drawing the layer border. - GLuint vboIds[2]; - GLC(glGenBuffers(2, vboIds)); - m_quadVerticesVbo = vboIds[0]; - m_quadElementsVbo = vboIds[1]; - GLC(glBindBuffer(GL_ARRAY_BUFFER, m_quadVerticesVbo)); - GLC(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW)); - GLC(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_quadElementsVbo)); - GLC(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW)); + GLC(m_context, m_quadVerticesVbo = m_context->createBuffer()); + GLC(m_context, m_quadElementsVbo = m_context->createBuffer()); + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVerticesVbo)); + GLC(m_context, m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(vertices), vertices, GraphicsContext3D::STATIC_DRAW)); + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_quadElementsVbo)); + GLC(m_context, m_context->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GraphicsContext3D::STATIC_DRAW)); // Get the max texture size supported by the system. - GLC(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize)); + GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize)); // Shaders for drawing the debug borders around the layers. char borderVertexShaderString[] = @@ -112,14 +112,14 @@ LayerChromium::SharedValues::SharedValues() " gl_FragColor = vec4(color.xyz * color.w, color.w);\n" "} \n"; - m_borderShaderProgram = createShaderProgram(borderVertexShaderString, borderFragmentShaderString); + m_borderShaderProgram = createShaderProgram(m_context, borderVertexShaderString, borderFragmentShaderString); if (!m_borderShaderProgram) { LOG_ERROR("ContentLayerChromium: Failed to create shader program"); return; } - m_borderShaderMatrixLocation = glGetUniformLocation(m_borderShaderProgram, "matrix"); - m_borderShaderColorLocation = glGetUniformLocation(m_borderShaderProgram, "color"); + m_borderShaderMatrixLocation = m_context->getUniformLocation(m_borderShaderProgram, "matrix"); + m_borderShaderColorLocation = m_context->getUniformLocation(m_borderShaderProgram, "color"); ASSERT(m_borderShaderMatrixLocation != -1); ASSERT(m_borderShaderColorLocation != -1); @@ -128,11 +128,10 @@ LayerChromium::SharedValues::SharedValues() LayerChromium::SharedValues::~SharedValues() { - GLuint vboIds[2] = { m_quadVerticesVbo, m_quadElementsVbo }; - GLC(glDeleteBuffers(2, vboIds)); - + GLC(m_context, m_context->deleteBuffer(m_quadVerticesVbo)); + GLC(m_context, m_context->deleteBuffer(m_quadElementsVbo)); if (m_borderShaderProgram) - GLC(glDeleteProgram(m_borderShaderProgram)); + GLC(m_context, m_context->deleteProgram(m_borderShaderProgram)); } @@ -181,45 +180,45 @@ void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) m_layerRenderer = renderer; } -unsigned LayerChromium::createShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource) +unsigned LayerChromium::createShaderProgram(GraphicsContext3D* context, const char* vertexShaderSource, const char* fragmentShaderSource) { - GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderSource); + unsigned vertexShader = loadShader(context, GraphicsContext3D::VERTEX_SHADER, vertexShaderSource); if (!vertexShader) { LOG_ERROR("Failed to create vertex shader"); return 0; } - GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderSource); + unsigned fragmentShader = loadShader(context, GraphicsContext3D::FRAGMENT_SHADER, fragmentShaderSource); if (!fragmentShader) { - GLC(glDeleteShader(vertexShader)); + GLC(context, context->deleteShader(vertexShader)); LOG_ERROR("Failed to create fragment shader"); return 0; } - GLuint programObject = glCreateProgram(); + unsigned programObject = context->createProgram(); if (!programObject) { LOG_ERROR("Failed to create shader program"); return 0; } - GLC(glAttachShader(programObject, vertexShader)); - GLC(glAttachShader(programObject, fragmentShader)); + GLC(context, context->attachShader(programObject, vertexShader)); + GLC(context, context->attachShader(programObject, fragmentShader)); // Bind the common attrib locations. - GLC(glBindAttribLocation(programObject, s_positionAttribLocation, "a_position")); - GLC(glBindAttribLocation(programObject, s_texCoordAttribLocation, "a_texCoord")); + GLC(context, context->bindAttribLocation(programObject, s_positionAttribLocation, "a_position")); + GLC(context, context->bindAttribLocation(programObject, s_texCoordAttribLocation, "a_texCoord")); - GLC(glLinkProgram(programObject)); - GLint linked; - GLC(glGetProgramiv(programObject, GL_LINK_STATUS, &linked)); + GLC(context, context->linkProgram(programObject)); + int linked; + GLC(context, context->getProgramiv(programObject, GraphicsContext3D::LINK_STATUS, &linked)); if (!linked) { LOG_ERROR("Failed to link shader program"); - GLC(glDeleteProgram(programObject)); + GLC(context, context->deleteProgram(programObject)); return 0; } - GLC(glDeleteShader(vertexShader)); - GLC(glDeleteShader(fragmentShader)); + GLC(context, context->deleteShader(vertexShader)); + GLC(context, context->deleteShader(fragmentShader)); return programObject; } @@ -299,10 +298,15 @@ void LayerChromium::setBounds(const IntSize& size) if (m_bounds == size) return; + bool firstResize = !m_bounds.width() && !m_bounds.height() && size.width() && size.height(); + m_bounds = size; m_backingStoreSize = size; - setNeedsCommit(); + if (firstResize) + setNeedsDisplay(FloatRect(0, 0, m_bounds.width(), m_bounds.height())); + else + setNeedsCommit(); } void LayerChromium::setFrame(const FloatRect& rect) @@ -311,7 +315,7 @@ void LayerChromium::setFrame(const FloatRect& rect) return; m_frame = rect; - setNeedsCommit(); + setNeedsDisplay(FloatRect(0, 0, m_bounds.width(), m_bounds.height())); } const LayerChromium* LayerChromium::rootLayer() const @@ -353,7 +357,6 @@ void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect) m_contentsDirty = true; m_dirtyRect.unite(dirtyRect); - setNeedsCommit(); } @@ -363,6 +366,12 @@ void LayerChromium::setNeedsDisplay() m_contentsDirty = true; } +void LayerChromium::resetNeedsDisplay() +{ + m_dirtyRect = FloatRect(); + m_contentsDirty = false; +} + void LayerChromium::toGLMatrix(float* flattened, const TransformationMatrix& m) { flattened[0] = m.m11(); @@ -383,11 +392,17 @@ void LayerChromium::toGLMatrix(float* flattened, const TransformationMatrix& m) flattened[15] = m.m44(); } -void LayerChromium::drawTexturedQuad(const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix, +GraphicsContext3D* LayerChromium::layerRendererContext() const +{ + ASSERT(layerRenderer()); + return layerRenderer()->context(); +} + +void LayerChromium::drawTexturedQuad(GraphicsContext3D* context, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix, float width, float height, float opacity, int matrixLocation, int alphaLocation) { - static GLfloat glMatrix[16]; + static float glMatrix[16]; TransformationMatrix renderMatrix = drawMatrix; @@ -399,17 +414,17 @@ void LayerChromium::drawTexturedQuad(const TransformationMatrix& projectionMatri toGLMatrix(&glMatrix[0], renderMatrix); - GLC(glUniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0])); + GLC(context, context->uniformMatrix4fv(matrixLocation, false, &glMatrix[0], 1)); if (alphaLocation != -1) - GLC(glUniform1f(alphaLocation, opacity)); + GLC(context, context->uniform1f(alphaLocation, opacity)); - GLC(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0)); + GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0)); } void LayerChromium::drawDebugBorder() { - static GLfloat glMatrix[16]; + static float glMatrix[16]; if (!borderColor().alpha()) return; @@ -421,14 +436,15 @@ void LayerChromium::drawDebugBorder() renderMatrix.scale3d(bounds().width(), bounds().height(), 1); renderMatrix.multiply(layerRenderer()->projectionMatrix()); toGLMatrix(&glMatrix[0], renderMatrix); - GLC(glUniformMatrix4fv(sv->borderShaderMatrixLocation(), 1, false, &glMatrix[0])); + GraphicsContext3D* context = layerRendererContext(); + GLC(context, context->uniformMatrix4fv(sv->borderShaderMatrixLocation(), false, &glMatrix[0], 1)); - GLC(glUniform4f(sv->borderShaderColorLocation(), borderColor().red() / 255.0, borderColor().green() / 255.0, borderColor().blue() / 255.0, 1)); + GLC(context, context->uniform4f(sv->borderShaderColorLocation(), borderColor().red() / 255.0, borderColor().green() / 255.0, borderColor().blue() / 255.0, 1)); - GLC(glLineWidth(borderWidth())); + GLC(context, context->lineWidth(borderWidth())); // The indices for the line are stored in the same array as the triangle indices. - GLC(glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, (void*)(6 * sizeof(unsigned short)))); + GLC(context, context->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short))); } const FloatRect LayerChromium::getDrawRect() const @@ -455,24 +471,26 @@ void LayerChromium::drawAsMask() // 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)); + GraphicsContext3D* context = layerRendererContext(); + GLC(context, context->uniform4f(sv->borderShaderColorLocation(), 0, 1 , 0, 0.7)); - drawTexturedQuad(layerRenderer()->projectionMatrix(), drawTransform(), - bounds().width(), bounds().height(), drawOpacity(), - sv->borderShaderMatrixLocation(), -1); + drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + sv->borderShaderMatrixLocation(), -1); } // static void LayerChromium::prepareForDraw(const SharedValues* sv) { - GLC(glBindBuffer(GL_ARRAY_BUFFER, sv->quadVerticesVbo())); - GLC(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sv->quadElementsVbo())); - GLuint offset = 0; - GLC(glVertexAttribPointer(s_positionAttribLocation, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)offset)); - offset += 3 * sizeof(GLfloat); - GLC(glVertexAttribPointer(s_texCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)offset)); - GLC(glEnableVertexAttribArray(s_positionAttribLocation)); - GLC(glEnableVertexAttribArray(s_texCoordAttribLocation)); + GraphicsContext3D* context = sv->context(); + GLC(context, context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, sv->quadVerticesVbo())); + GLC(context, context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, sv->quadElementsVbo())); + unsigned offset = 0; + GLC(context, context->vertexAttribPointer(s_positionAttribLocation, 3, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset)); + offset += 3 * sizeof(float); + GLC(context, context->vertexAttribPointer(s_texCoordAttribLocation, 2, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset)); + GLC(context, context->enableVertexAttribArray(s_positionAttribLocation)); + GLC(context, context->enableVertexAttribArray(s_texCoordAttribLocation)); } } diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index ba15088..30d35d1 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -62,7 +62,7 @@ class LayerChromium : public RefCounted<LayerChromium> { public: static PassRefPtr<LayerChromium> create(GraphicsLayerChromium* owner = 0); - ~LayerChromium(); + virtual ~LayerChromium(); const LayerChromium* rootLayer() const; LayerChromium* superlayer() const; @@ -112,6 +112,8 @@ public: void setNeedsDisplay(const FloatRect& dirtyRect); void setNeedsDisplay(); + const FloatRect& dirtyRect() const { return m_dirtyRect; } + void resetNeedsDisplay(); void setNeedsDisplayOnBoundsChange(bool needsDisplay) { m_needsDisplayOnBoundsChange = needsDisplay; } @@ -169,9 +171,10 @@ public: // context). class SharedValues { public: - SharedValues(); + explicit SharedValues(GraphicsContext3D*); ~SharedValues(); + GraphicsContext3D* context() const { return m_context; } unsigned quadVerticesVbo() const { return m_quadVerticesVbo; } unsigned quadElementsVbo() const { return m_quadElementsVbo; } int maxTextureSize() const { return m_maxTextureSize; } @@ -181,6 +184,7 @@ public: bool initialized() const { return m_initialized; } private: + GraphicsContext3D* m_context; unsigned m_quadVerticesVbo; unsigned m_quadElementsVbo; int m_maxTextureSize; @@ -197,14 +201,15 @@ protected: LayerChromium(GraphicsLayerChromium* owner); LayerRendererChromium* layerRenderer() const { return m_layerRenderer; } + GraphicsContext3D* layerRendererContext() const; - static void drawTexturedQuad(const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix, + static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix, float width, float height, float opacity, int matrixLocation, int alphaLocation); static void toGLMatrix(float*, const TransformationMatrix&); - static unsigned createShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource); + static unsigned createShaderProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource); IntSize m_bounds; FloatRect m_dirtyRect; diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index 4708310..116a15d 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -35,7 +35,7 @@ #include "LayerRendererChromium.h" #include "Canvas2DLayerChromium.h" -#include "GLES2Context.h" +#include "GraphicsContext3D.h" #include "LayerChromium.h" #include "NotImplemented.h" #include "WebGLLayerChromium.h" @@ -46,8 +46,6 @@ #include <CoreGraphics/CGBitmapContext.h> #endif -#include <GLES2/gl2.h> - namespace WebCore { static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top, float nearZ, float farZ) @@ -75,19 +73,19 @@ static inline bool compareLayerZ(const LayerChromium* a, const LayerChromium* b) return transformA.m43() < transformB.m43(); } -PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(PassOwnPtr<GLES2Context> gles2Context) +PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(PassOwnPtr<GraphicsContext3D> context) { - if (!gles2Context) + if (!context) return 0; - OwnPtr<LayerRendererChromium> layerRenderer(new LayerRendererChromium(gles2Context)); + OwnPtr<LayerRendererChromium> layerRenderer(new LayerRendererChromium(context)); if (!layerRenderer->hardwareCompositing()) return 0; return layerRenderer.release(); } -LayerRendererChromium::LayerRendererChromium(PassOwnPtr<GLES2Context> gles2Context) +LayerRendererChromium::LayerRendererChromium(PassOwnPtr<GraphicsContext3D> context) : m_rootLayerTextureId(0) , m_rootLayerTextureWidth(0) , m_rootLayerTextureHeight(0) @@ -96,7 +94,7 @@ LayerRendererChromium::LayerRendererChromium(PassOwnPtr<GLES2Context> gles2Conte , m_needsDisplay(false) , m_scrollPosition(IntPoint(-1, -1)) , m_currentShader(0) - , m_gles2Context(gles2Context) + , m_context(context) { m_hardwareCompositing = initializeSharedObjects(); } @@ -106,11 +104,16 @@ LayerRendererChromium::~LayerRendererChromium() cleanupSharedObjects(); } -void LayerRendererChromium::debugGLCall(const char* command, const char* file, int line) +GraphicsContext3D* LayerRendererChromium::context() +{ + return m_context.get(); +} + +void LayerRendererChromium::debugGLCall(GraphicsContext3D* context, const char* command, const char* file, int line) { - GLenum error = glGetError(); - if (error != GL_NO_ERROR) - LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, error); + unsigned long error = context->getError(); + if (error != GraphicsContext3D::NO_ERROR) + LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast<int>(error)); } // Creates a canvas and an associated graphics context that the root layer will @@ -138,6 +141,8 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size) size.width(), size.height(), 8, rowBytes, colorSpace.get(), kCGImageAlphaPremultipliedLast)); + CGContextTranslateCTM(m_rootLayerCGContext.get(), 0, size.height()); + CGContextScaleCTM(m_rootLayerCGContext.get(), 1, -1); m_rootLayerGraphicsContext = new GraphicsContext(m_rootLayerCGContext.get()); #else #error "Need to implement for your platform." @@ -149,15 +154,15 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size) void LayerRendererChromium::useShader(unsigned programId) { if (programId != m_currentShader) { - GLC(glUseProgram(programId)); + GLC(m_context, m_context->useProgram(programId)); m_currentShader = programId; } } // Updates the contents of the root layer texture that fall inside the updateRect // and re-composits all sublayers. -void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& visibleRect, - const IntRect& contentRect, const IntPoint& scrollPosition) +void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, + const IntPoint& scrollPosition) { ASSERT(m_hardwareCompositing); @@ -166,7 +171,7 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& makeContextCurrent(); - GLC(glBindTexture(GL_TEXTURE_2D, m_rootLayerTextureId)); + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId)); // If the size of the visible area has changed then allocate a new texture // to store the contents of the root layer and adjust the projection matrix @@ -178,56 +183,44 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& m_rootLayerTextureHeight = visibleRect.height(); m_projectionMatrix = orthoMatrix(0, visibleRectWidth, visibleRectHeight, 0, -1000, 1000); - GLC(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)); + GLC(m_context, m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0)); } // The GL viewport covers the entire visible area, including the scrollbars. - GLC(glViewport(0, 0, visibleRectWidth, visibleRectHeight)); + GLC(m_context, m_context->viewport(0, 0, visibleRectWidth, visibleRectHeight)); // 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)); + GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST)); + GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE)); + GLC(m_context, m_context->depthFunc(GraphicsContext3D::LEQUAL)); + GLC(m_context, m_context->clearStencil(0)); if (m_scrollPosition == IntPoint(-1, -1)) m_scrollPosition = scrollPosition; IntPoint scrollDelta = toPoint(scrollPosition - m_scrollPosition); - // Scroll only when the updateRect contains pixels for the newly uncovered region to avoid flashing. - if ((scrollDelta.x() && updateRect.width() >= abs(scrollDelta.x()) && updateRect.height() >= contentRect.height()) - || (scrollDelta.y() && updateRect.height() >= abs(scrollDelta.y()) && updateRect.width() >= contentRect.width())) { + // Scroll the backbuffer + if (scrollDelta.x() || scrollDelta.y()) { // Scrolling works as follows: We render a quad with the current root layer contents // translated by the amount the page has scrolled since the last update and then read the // pixels of the content area (visible area excluding the scroll bars) back into the - // root layer texture. The newly exposed area is subesquently filled as usual with - // the contents of the updateRect. + // root layer texture. The newly exposed area will be filled by a subsequent drawLayersIntoRect call TransformationMatrix scrolledLayerMatrix; -#if PLATFORM(SKIA) - float scaleFactor = 1.0f; -#elif PLATFORM(CG) - // Because the contents of the OpenGL texture are inverted - // vertically compared to the Skia backend, we need to move - // the backing store in the opposite direction. - float scaleFactor = -1.0f; -#else -#error "Need to implement for your platform." -#endif scrolledLayerMatrix.translate3d(0.5 * visibleRect.width() - scrollDelta.x(), - 0.5 * visibleRect.height() + scaleFactor * scrollDelta.y(), 0); + 0.5 * visibleRect.height() + scrollDelta.y(), 0); scrolledLayerMatrix.scale3d(1, -1, 1); useShader(m_scrollShaderProgram); - GLC(glUniform1i(m_scrollShaderSamplerLocation, 0)); - LayerChromium::drawTexturedQuad(m_projectionMatrix, scrolledLayerMatrix, + GLC(m_context, m_context->uniform1i(m_scrollShaderSamplerLocation, 0)); + LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, scrolledLayerMatrix, visibleRect.width(), visibleRect.height(), 1, m_scrollShaderMatrixLocation, -1); - GLC(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height())); + GLC(m_context, m_context->copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height())); m_scrollPosition = scrollPosition; } else if (abs(scrollDelta.y()) > contentRect.height() || abs(scrollDelta.x()) > contentRect.width()) { // Scrolling larger than the contentRect size does not preserve any of the pixels, so there is @@ -235,64 +228,83 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& m_scrollPosition = scrollPosition; } - // FIXME: The following check should go away when the compositor renders independently from its own thread. - // Ignore a 1x1 update rect at (0, 0) as that's used a way to kick off a redraw for the compositor. - if (!(!updateRect.x() && !updateRect.y() && updateRect.width() == 1 && updateRect.height() == 1)) { - // Update the root layer texture. - ASSERT((updateRect.x() + updateRect.width() <= m_rootLayerTextureWidth) - && (updateRect.y() + updateRect.height() <= m_rootLayerTextureHeight)); + // Translate all the composited layers by the scroll position. + TransformationMatrix matrix; + matrix.translate3d(-m_scrollPosition.x(), -m_scrollPosition.y(), 0); + + // Traverse the layer tree and update the layer transforms. + float opacity = 1; + const Vector<RefPtr<LayerChromium> >& sublayers = m_rootLayer->getSublayers(); + size_t i; + for (i = 0; i < sublayers.size(); i++) + updateLayersRecursive(sublayers[i].get(), matrix, opacity); +} + +void LayerRendererChromium::updateRootLayerTextureRect(const IntRect& updateRect) +{ + ASSERT(m_hardwareCompositing); + + if (!m_rootLayer) + return; + + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId)); + + // Update the root layer texture. + ASSERT((updateRect.right() <= m_rootLayerTextureWidth) + && (updateRect.bottom() <= m_rootLayerTextureHeight)); #if PLATFORM(SKIA) - // Get the contents of the updated rect. - const SkBitmap bitmap = m_rootLayerCanvas->getDevice()->accessBitmap(false); - int rootLayerWidth = bitmap.width(); - int rootLayerHeight = bitmap.height(); - ASSERT(rootLayerWidth == updateRect.width() && rootLayerHeight == updateRect.height()); - void* pixels = bitmap.getPixels(); - - // Copy the contents of the updated rect to the root layer texture. - GLC(glTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels)); + // Get the contents of the updated rect. + const SkBitmap bitmap = m_rootLayerCanvas->getDevice()->accessBitmap(false); + int bitmapWidth = bitmap.width(); + int bitmapHeight = bitmap.height(); + ASSERT(bitmapWidth == updateRect.width() && bitmapHeight == updateRect.height()); + void* pixels = bitmap.getPixels(); #elif PLATFORM(CG) - // Get the contents of the updated rect. - ASSERT(static_cast<int>(CGBitmapContextGetWidth(m_rootLayerCGContext.get())) == updateRect.width() && static_cast<int>(CGBitmapContextGetHeight(m_rootLayerCGContext.get())) == updateRect.height()); - void* pixels = m_rootLayerBackingStore.data(); - - // Copy the contents of the updated rect to the root layer texture. - // The origin is at the lower left in Core Graphics' coordinate system. We need to correct for this here. - GLC(glTexSubImage2D(GL_TEXTURE_2D, 0, - updateRect.x(), m_rootLayerTextureHeight - updateRect.y() - updateRect.height(), - updateRect.width(), updateRect.height(), - GL_RGBA, GL_UNSIGNED_BYTE, pixels)); + // Get the contents of the updated rect. + ASSERT(static_cast<int>(CGBitmapContextGetWidth(m_rootLayerCGContext.get())) == updateRect.width() && static_cast<int>(CGBitmapContextGetHeight(m_rootLayerCGContext.get())) == updateRect.height()); + void* pixels = m_rootLayerBackingStore.data(); #else #error "Need to implement for your platform." #endif - } + // Copy the contents of the updated rect to the root layer texture. + GLC(m_context, m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels)); +} + +void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect& contentRect) +{ + ASSERT(m_hardwareCompositing); - glClearColor(0, 0, 1, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_context->clearColor(0, 0, 1, 1); + m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT); + + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId)); // Render the root layer using a quad that takes up the entire visible area of the window. // We reuse the shader program used by ContentLayerChromium. const ContentLayerChromium::SharedValues* contentLayerValues = contentLayerSharedValues(); useShader(contentLayerValues->contentShaderProgram()); - GLC(glUniform1i(contentLayerValues->shaderSamplerLocation(), 0)); + GLC(m_context, m_context->uniform1i(contentLayerValues->shaderSamplerLocation(), 0)); TransformationMatrix layerMatrix; layerMatrix.translate3d(visibleRect.width() * 0.5f, visibleRect.height() * 0.5f, 0); - LayerChromium::drawTexturedQuad(m_projectionMatrix, layerMatrix, + LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, layerMatrix, visibleRect.width(), visibleRect.height(), 1, contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation()); // If culling is enabled then we will cull the backface. - GLC(glCullFace(GL_BACK)); + GLC(m_context, m_context->cullFace(GraphicsContext3D::BACK)); // The orthographic projection is setup such that Y starts at zero and // increases going down the page so we need to adjust the winding order of // front facing triangles. - GLC(glFrontFace(GL_CW)); + GLC(m_context, m_context->frontFace(GraphicsContext3D::CW)); // The shader used to render layers returns pre-multiplied alpha colors // so we need to send the blending mode appropriately. - GLC(glEnable(GL_BLEND)); - GLC(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); + GLC(m_context, m_context->enable(GraphicsContext3D::BLEND)); + GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); + + // Set the rootVisibleRect --- used by subsequent drawLayers calls + m_rootVisibleRect = visibleRect; // Translate all the composited layers by the scroll position. TransformationMatrix matrix; @@ -305,43 +317,67 @@ 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(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST)); 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)); + GLC(m_context, m_context->clear(GraphicsContext3D::STENCIL_BUFFER_BIT)); // Disable writes to the stencil buffer. - GLC(glStencilMask(0)); + GLC(m_context, m_context->stencilMask(0)); // Traverse the layer tree one more time to draw the layers. - for (i = 0; i < sublayers.size(); i++) + for (size_t i = 0; i < sublayers.size(); i++) drawLayersRecursive(sublayers[i].get(), scissorRect); - GLC(glDisable(GL_SCISSOR_TEST)); + GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST)); +} - m_gles2Context->swapBuffers(); +void LayerRendererChromium::finish() +{ + m_context->finish(); +} +void LayerRendererChromium::present() +{ + // We're done! Time to swapbuffers! + + // Note that currently this has the same effect as swapBuffers; we should + // consider exposing a different entry point on GraphicsContext3D. + m_context->prepareTexture(); m_needsDisplay = false; } +void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect) +{ + ASSERT(rect.right() <= rootLayerTextureSize().width() + && rect.bottom() <= rootLayerTextureSize().height()); + + if (!pixels) + return; + + makeContextCurrent(); + + GLC(m_context, m_context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(), + GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels)); +} + // FIXME: This method should eventually be replaced by a proper texture manager. unsigned LayerRendererChromium::createLayerTexture() { - GLuint textureId = 0; - GLC(glGenTextures(1, &textureId)); - GLC(glBindTexture(GL_TEXTURE_2D, textureId)); + unsigned textureId = 0; + GLC(m_context, textureId = m_context->createTexture()); + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); // Do basic linear filtering on resize. - GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - // NPOT textures in GL ES only work when the wrap mode is set to GL_CLAMP_TO_EDGE. - GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); + // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE. + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); return textureId; } @@ -440,18 +476,18 @@ void LayerRendererChromium::drawLayerIntoStencilBuffer(LayerChromium* layer, boo { // 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(m_context, m_context->stencilMask(0xff)); + GLC(m_context, m_context->stencilFunc(GraphicsContext3D::ALWAYS, 1, 0xff)); + unsigned stencilOp = (decrement ? GraphicsContext3D::DECR : GraphicsContext3D::INCR); + GLC(m_context, m_context->stencilOp(stencilOp, stencilOp, stencilOp)); - GLC(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)); + GLC(m_context, m_context->colorMask(false, false, false, false)); layer->drawAsMask(); // Disable writes to the stencil buffer. - GLC(glStencilMask(0)); - GLC(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)); + GLC(m_context, m_context->stencilMask(0)); + GLC(m_context, m_context->colorMask(true, true, true, true)); } // Recursively walk the layer tree and draw the layers. @@ -468,7 +504,7 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const Floa bool mustClearDepth = false; if (layer->preserves3D()) { if (!depthTestEnabledForSubtree) { - GLC(glEnable(GL_DEPTH_TEST)); + GLC(m_context, m_context->enable(GraphicsContext3D::DEPTH_TEST)); depthTestEnabledForSubtree = true; // Need to clear the depth buffer when we're done rendering this subtree. @@ -505,7 +541,7 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const Floa // 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)); + GLC(m_context, m_context->enable(GraphicsContext3D::STENCIL_TEST)); drawLayerIntoStencilBuffer(layer, false); @@ -517,7 +553,7 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const Floa // currentStencilValue. if (didStencilDraw) { // The sublayers will render only if the stencil test passes. - GLC(glStencilFunc(GL_EQUAL, currentStencilValue, 0xff)); + GLC(m_context, m_context->stencilFunc(GraphicsContext3D::EQUAL, currentStencilValue, 0xff)); } // If we're using depth testing then we need to sort the children in Z to @@ -548,8 +584,8 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const Floa currentStencilValue--; if (!currentStencilValue) { // Disable stencil testing. - GLC(glDisable(GL_STENCIL_TEST)); - GLC(glStencilFunc(GL_ALWAYS, 0, 0xff)); + GLC(m_context, m_context->disable(GraphicsContext3D::STENCIL_TEST)); + GLC(m_context, m_context->stencilFunc(GraphicsContext3D::ALWAYS, 0, 0xff)); } } @@ -558,8 +594,8 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const Floa } if (mustClearDepth) { - GLC(glDisable(GL_DEPTH_TEST)); - GLC(glClear(GL_DEPTH_BUFFER_BIT)); + GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST)); + GLC(m_context, m_context->clear(GraphicsContext3D::DEPTH_BUFFER_BIT)); depthTestEnabledForSubtree = false; } } @@ -573,13 +609,13 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer) if (layer->contentsDirty()) { // Update the backing texture contents for any dirty portion of the layer. layer->updateContents(); - m_gles2Context->makeCurrent(); + m_context->makeContextCurrent(); } if (layer->doubleSided()) - glDisable(GL_CULL_FACE); + m_context->disable(GraphicsContext3D::CULL_FACE); else - glEnable(GL_CULL_FACE); + m_context->enable(GraphicsContext3D::CULL_FACE); layer->draw(); } @@ -594,12 +630,13 @@ 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())); + GLC(m_context, m_context->scissor(scissorRect.x(), bottom, scissorRect.width(), scissorRect.height())); } bool LayerRendererChromium::makeContextCurrent() { - return m_gles2Context->makeCurrent(); + m_context->makeContextCurrent(); + return true; } // Checks whether a given size is within the maximum allowed texture size range. @@ -610,6 +647,12 @@ bool LayerRendererChromium::checkTextureSize(const IntSize& textureSize) return true; } +void LayerRendererChromium::resizeOnscreenContent(const IntSize& size) +{ + if (m_context) + m_context->reshape(size.width(), size.height()); +} + bool LayerRendererChromium::initializeSharedObjects() { makeContextCurrent(); @@ -637,15 +680,15 @@ bool LayerRendererChromium::initializeSharedObjects() " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w); \n" "} \n"; - m_scrollShaderProgram = LayerChromium::createShaderProgram(scrollVertexShaderString, scrollFragmentShaderString); + m_scrollShaderProgram = LayerChromium::createShaderProgram(m_context.get(), scrollVertexShaderString, scrollFragmentShaderString); if (!m_scrollShaderProgram) { LOG_ERROR("LayerRendererChromium: Failed to create scroll shader program"); cleanupSharedObjects(); return false; } - GLC(m_scrollShaderSamplerLocation = glGetUniformLocation(m_scrollShaderProgram, "s_texture")); - GLC(m_scrollShaderMatrixLocation = glGetUniformLocation(m_scrollShaderProgram, "matrix")); + GLC(m_context, m_scrollShaderSamplerLocation = m_context->getUniformLocation(m_scrollShaderProgram, "s_texture")); + GLC(m_context, m_scrollShaderMatrixLocation = m_context->getUniformLocation(m_scrollShaderProgram, "matrix")); if (m_scrollShaderSamplerLocation == -1 || m_scrollShaderMatrixLocation == -1) { LOG_ERROR("Failed to initialize scroll shader."); cleanupSharedObjects(); @@ -661,19 +704,19 @@ bool LayerRendererChromium::initializeSharedObjects() } // Turn off filtering for the root layer to avoid blurring from the repeated // writes and reads to the framebuffer that happen while scrolling. - GLC(glBindTexture(GL_TEXTURE_2D, m_rootLayerTextureId)); - GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - GLC(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST)); // Get the max texture size supported by the system. - GLC(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize)); + GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize)); // Get the number of bits available in the stencil buffer. - GLC(glGetIntegerv(GL_STENCIL_BITS, &m_numStencilBits)); + GLC(m_context, m_context->getIntegerv(GraphicsContext3D::STENCIL_BITS, &m_numStencilBits)); - m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues()); - m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues()); - m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues()); + m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues(m_context.get())); + m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues(m_context.get())); + m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues(m_context.get())); if (!m_layerSharedValues->initialized() || !m_contentLayerSharedValues->initialized() || !m_canvasLayerSharedValues->initialized()) { cleanupSharedObjects(); return false; @@ -691,12 +734,12 @@ void LayerRendererChromium::cleanupSharedObjects() m_canvasLayerSharedValues.clear(); if (m_scrollShaderProgram) { - GLC(glDeleteProgram(m_scrollShaderProgram)); + GLC(m_context, m_context->deleteProgram(m_scrollShaderProgram)); m_scrollShaderProgram = 0; } if (m_rootLayerTextureId) { - GLC(glDeleteTextures(1, &m_rootLayerTextureId)); + GLC(m_context, m_context->deleteTexture(m_rootLayerTextureId)); m_rootLayerTextureId = 0; } } diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h index 8f44afe..c733228 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -51,19 +51,32 @@ namespace WebCore { -class GLES2Context; +class GraphicsContext3D; // Class that handles drawing of composited render layers using GL. class LayerRendererChromium : public Noncopyable { public: - static PassOwnPtr<LayerRendererChromium> create(PassOwnPtr<GLES2Context> gles2Context); + static PassOwnPtr<LayerRendererChromium> create(PassOwnPtr<GraphicsContext3D> graphicsContext3D); - LayerRendererChromium(PassOwnPtr<GLES2Context> gles2Context); + LayerRendererChromium(PassOwnPtr<GraphicsContext3D> graphicsContext3D); ~LayerRendererChromium(); - // Updates the contents of the root layer that fall inside the updateRect and recomposites - // all the layers. - void drawLayers(const IntRect& updateRect, const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition); + GraphicsContext3D* context(); + + // updates size of root texture, if needed, and scrolls the backbuffer. + void prepareToDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition); + + // updates a rectangle within the root layer texture + void updateRootLayerTextureRect(const IntRect& updateRect); + + // draws the current layers onto the backbuffer + void drawLayers(const IntRect& visibleRect, const IntRect& contentRect); + + // waits for rendering to finish + void finish(); + + // puts backbuffer onscreen + void present(); void setRootLayer(PassRefPtr<LayerChromium> layer) { m_rootLayer = layer; } LayerChromium* rootLayer() { return m_rootLayer.get(); } @@ -78,7 +91,7 @@ public: unsigned createLayerTexture(); - static void debugGLCall(const char* command, const char* file, int line); + static void debugGLCall(GraphicsContext3D*, const char* command, const char* file, int line); const TransformationMatrix& projectionMatrix() const { return m_projectionMatrix; } @@ -90,6 +103,11 @@ public: const ContentLayerChromium::SharedValues* contentLayerSharedValues() const { return m_contentLayerSharedValues.get(); } const CanvasLayerChromium::SharedValues* canvasLayerSharedValues() const { return m_canvasLayerSharedValues.get(); } + void resizeOnscreenContent(const IntSize&); + + IntSize rootLayerTextureSize() const { return IntSize(m_rootLayerTextureWidth, m_rootLayerTextureHeight); } + void getFramebufferPixels(void *pixels, const IntRect& rect); + private: void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity); @@ -153,7 +171,7 @@ private: OwnPtr<ContentLayerChromium::SharedValues> m_contentLayerSharedValues; OwnPtr<CanvasLayerChromium::SharedValues> m_canvasLayerSharedValues; - OwnPtr<GLES2Context> m_gles2Context; + OwnPtr<GraphicsContext3D> m_context; }; // Setting DEBUG_GL_CALLS to 1 will call glGetError() after almost every GL @@ -162,9 +180,9 @@ private: #define DEBUG_GL_CALLS 0 #if DEBUG_GL_CALLS && !defined ( NDEBUG ) -#define GLC(x) { (x), LayerRendererChromium::debugGLCall(#x, __FILE__, __LINE__); } +#define GLC(context, x) { (x), LayerRendererChromium::debugGLCall(context, #x, __FILE__, __LINE__); } #else -#define GLC(x) (x) +#define GLC(context, x) (x) #endif diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp index c0da285..0fb1bb4 100644 --- a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp @@ -33,14 +33,11 @@ #if USE(ACCELERATED_COMPOSITING) #include "VideoLayerChromium.h" +#include "GraphicsContext3D.h" #include "LayerRendererChromium.h" #include "RenderLayerBacking.h" #include "skia/ext/platform_canvas.h" -#include <GLES2/gl2.h> -#define GL_GLEXT_PROTOTYPES -#include <GLES2/gl2ext.h> - #if PLATFORM(SKIA) #include "NativeImageSkia.h" #include "PlatformContextSkia.h" @@ -153,9 +150,10 @@ void VideoLayerChromium::createTextureRect(const IntSize& requiredTextureSize, c if (!pixels) return; - glBindTexture(GL_TEXTURE_2D, textureId); + GraphicsContext3D* context = layerRendererContext(); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); ASSERT(bitmapSize == requiredTextureSize); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels); m_contentsTexture = textureId; m_allocatedTextureSize = requiredTextureSize; @@ -174,11 +172,13 @@ void VideoLayerChromium::updateTextureRect(const IntRect& updateRect, unsigned t SkBitmap::Config skiaConfig = skiaBitmap->config(); if (skiaConfig == SkBitmap::kARGB_8888_Config) { - glBindTexture(GL_TEXTURE_2D, textureId); - void* mem = glMapTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, GL_WRITE_ONLY); + GraphicsContext3D* context = layerRendererContext(); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); + ASSERT(context->supportsMapSubCHROMIUM()); + void* mem = context->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, GraphicsContext3D::WRITE_ONLY); skiaBitmap->setPixels(mem); m_owner->paintGraphicsLayerContents(*m_graphicsContext, updateRect); - glUnmapTexSubImage2D(mem); + context->unmapTexSubImage2DCHROMIUM(mem); } updateCompleted(); diff --git a/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp index 411f416..2055ae6 100644 --- a/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp @@ -36,7 +36,6 @@ #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" -#include <GLES2/gl2.h> namespace WebCore { @@ -53,15 +52,16 @@ WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner) void WebGLLayerChromium::updateContents() { + GraphicsContext3D* rendererContext = layerRendererContext(); ASSERT(m_context); if (m_textureChanged) { - glBindTexture(GL_TEXTURE_2D, m_textureId); + rendererContext->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId); // Set the min-mag filters to linear and wrap modes to GL_CLAMP_TO_EDGE // to get around NPOT texture limitations of GLES. - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); m_textureChanged = false; } // Update the contents of the texture used by the compositor. diff --git a/WebCore/platform/graphics/filters/FEBlend.cpp b/WebCore/platform/graphics/filters/FEBlend.cpp index 99c0ae7..acd6545 100644 --- a/WebCore/platform/graphics/filters/FEBlend.cpp +++ b/WebCore/platform/graphics/filters/FEBlend.cpp @@ -35,27 +35,15 @@ typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, u namespace WebCore { -FEBlend::FEBlend(FilterEffect* in, FilterEffect* in2, BlendModeType mode) +FEBlend::FEBlend(BlendModeType mode) : FilterEffect() - , m_in(in) - , m_in2(in2) , m_mode(mode) { } -PassRefPtr<FEBlend> FEBlend::create(FilterEffect* in, FilterEffect* in2, BlendModeType mode) +PassRefPtr<FEBlend> FEBlend::create(BlendModeType mode) { - return adoptRef(new FEBlend(in, in2, mode)); -} - -FilterEffect* FEBlend::in2() const -{ - return m_in2.get(); -} - -void FEBlend::setIn2(FilterEffect* in2) -{ - m_in2 = in2; + return adoptRef(new FEBlend(mode)); } BlendModeType FEBlend::blendMode() const @@ -100,9 +88,11 @@ static unsigned char lighten(unsigned char colorA, unsigned char colorB, unsigne void FEBlend::apply(Filter* filter) { - m_in->apply(filter); - m_in2->apply(filter); - if (!m_in->resultImage() || !m_in2->resultImage()) + FilterEffect* in = inputEffect(0); + FilterEffect* in2 = inputEffect(1); + in->apply(filter); + in2->apply(filter); + if (!in->resultImage() || !in2->resultImage()) return; if (m_mode == FEBLEND_MODE_UNKNOWN) @@ -111,11 +101,11 @@ void FEBlend::apply(Filter* filter) if (!getEffectContext()) return; - IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); - RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); + IntRect effectADrawingRect = calculateDrawingIntRect(in->repaintRectInLocalCoordinates()); + RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); - IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion()); - RefPtr<CanvasPixelArray> srcPixelArrayB(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data()); + IntRect effectBDrawingRect = calculateDrawingIntRect(in2->repaintRectInLocalCoordinates()); + RefPtr<CanvasPixelArray> srcPixelArrayB(in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data()); IntRect imageRect(IntPoint(), resultImage()->size()); RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height()); @@ -176,8 +166,8 @@ TextStream& FEBlend::externalRepresentation(TextStream& ts, int indent) const ts << "[feBlend"; FilterEffect::externalRepresentation(ts); ts << " mode=\"" << m_mode << "\"]\n"; - m_in->externalRepresentation(ts, indent + 1); - m_in2->externalRepresentation(ts, indent + 1); + inputEffect(0)->externalRepresentation(ts, indent + 1); + inputEffect(1)->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/platform/graphics/filters/FEBlend.h b/WebCore/platform/graphics/filters/FEBlend.h index 52de647..2e67588 100644 --- a/WebCore/platform/graphics/filters/FEBlend.h +++ b/WebCore/platform/graphics/filters/FEBlend.h @@ -40,24 +40,18 @@ namespace WebCore { class FEBlend : public FilterEffect { public: - static PassRefPtr<FEBlend> create(FilterEffect*, FilterEffect*, BlendModeType); - - FilterEffect* in2() const; - void setIn2(FilterEffect*); + static PassRefPtr<FEBlend> create(BlendModeType); BlendModeType blendMode() const; void setBlendMode(BlendModeType); - virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get(), m_in2.get()); } void apply(Filter*); void dump(); TextStream& externalRepresentation(TextStream&, int indent) const; private: - FEBlend(FilterEffect*, FilterEffect*, BlendModeType); + FEBlend(BlendModeType); - RefPtr<FilterEffect> m_in; - RefPtr<FilterEffect> m_in2; BlendModeType m_mode; }; diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp index 7718066..1d9c66b 100644 --- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp +++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp @@ -34,17 +34,16 @@ namespace WebCore { -FEColorMatrix::FEColorMatrix(FilterEffect* in, ColorMatrixType type, const Vector<float>& values) +FEColorMatrix::FEColorMatrix(ColorMatrixType type, const Vector<float>& values) : FilterEffect() - , m_in(in) , m_type(type) , m_values(values) { } -PassRefPtr<FEColorMatrix> FEColorMatrix::create(FilterEffect* in, ColorMatrixType type, const Vector<float>& values) +PassRefPtr<FEColorMatrix> FEColorMatrix::create(ColorMatrixType type, const Vector<float>& values) { - return adoptRef(new FEColorMatrix(in, type, values)); + return adoptRef(new FEColorMatrix(type, values)); } ColorMatrixType FEColorMatrix::type() const @@ -156,15 +155,16 @@ void effectType(const PassRefPtr<CanvasPixelArray>& srcPixelArray, PassRefPtr<Im void FEColorMatrix::apply(Filter* filter) { - m_in->apply(filter); - if (!m_in->resultImage()) + FilterEffect* in = inputEffect(0); + in->apply(filter); + if (!in->resultImage()) return; GraphicsContext* filterContext = getEffectContext(); if (!filterContext) return; - filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates())); IntRect imageRect(IntPoint(), resultImage()->size()); PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect)); @@ -236,7 +236,7 @@ TextStream& FEColorMatrix::externalRepresentation(TextStream& ts, int indent) co ts << "\""; } ts << "]\n"; - m_in->externalRepresentation(ts, indent + 1); + inputEffect(0)->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.h b/WebCore/platform/graphics/filters/FEColorMatrix.h index 906d0f1..9b9084c 100644 --- a/WebCore/platform/graphics/filters/FEColorMatrix.h +++ b/WebCore/platform/graphics/filters/FEColorMatrix.h @@ -40,7 +40,7 @@ namespace WebCore { class FEColorMatrix : public FilterEffect { public: - static PassRefPtr<FEColorMatrix> create(FilterEffect*, ColorMatrixType, const Vector<float>&); + static PassRefPtr<FEColorMatrix> create(ColorMatrixType, const Vector<float>&); ColorMatrixType type() const; void setType(ColorMatrixType); @@ -48,15 +48,13 @@ namespace WebCore { const Vector<float>& values() const; void setValues(const Vector<float>&); - virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); } void apply(Filter*); void dump(); TextStream& externalRepresentation(TextStream&, int indent) const; private: - FEColorMatrix(FilterEffect*, ColorMatrixType, const Vector<float>&); + FEColorMatrix(ColorMatrixType, const Vector<float>&); - RefPtr<FilterEffect> m_in; ColorMatrixType m_type; Vector<float> m_values; }; diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp index 19df970..471fec8 100644 --- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp +++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp @@ -36,10 +36,9 @@ namespace WebCore { typedef void (*TransferType)(unsigned char*, const ComponentTransferFunction&); -FEComponentTransfer::FEComponentTransfer(FilterEffect* in, const ComponentTransferFunction& redFunc, +FEComponentTransfer::FEComponentTransfer(const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc) : FilterEffect() - , m_in(in) , m_redFunc(redFunc) , m_greenFunc(greenFunc) , m_blueFunc(blueFunc) @@ -47,10 +46,10 @@ FEComponentTransfer::FEComponentTransfer(FilterEffect* in, const ComponentTransf { } -PassRefPtr<FEComponentTransfer> FEComponentTransfer::create(FilterEffect* in, const ComponentTransferFunction& redFunc, +PassRefPtr<FEComponentTransfer> FEComponentTransfer::create(const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc) { - return adoptRef(new FEComponentTransfer(in, redFunc, greenFunc, blueFunc, alphaFunc)); + return adoptRef(new FEComponentTransfer(redFunc, greenFunc, blueFunc, alphaFunc)); } ComponentTransferFunction FEComponentTransfer::redFunction() const @@ -150,8 +149,9 @@ static void gamma(unsigned char* values, const ComponentTransferFunction& transf void FEComponentTransfer::apply(Filter* filter) { - m_in->apply(filter); - if (!m_in->resultImage()) + FilterEffect* in = inputEffect(0); + in->apply(filter); + if (!in->resultImage()) return; if (!getEffectContext()) @@ -167,8 +167,8 @@ void FEComponentTransfer::apply(Filter* filter) for (unsigned channel = 0; channel < 4; channel++) (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]); - IntRect drawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); - RefPtr<ImageData> imageData(m_in->resultImage()->getUnmultipliedImageData(drawingRect)); + IntRect drawingRect = calculateDrawingIntRect(in->repaintRectInLocalCoordinates()); + RefPtr<ImageData> imageData(in->resultImage()->getUnmultipliedImageData(drawingRect)); CanvasPixelArray* srcPixelArray(imageData->data()); for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) { @@ -235,7 +235,7 @@ TextStream& FEComponentTransfer::externalRepresentation(TextStream& ts, int inde ts << "{blue: " << m_blueFunc << "}\n"; writeIndent(ts, indent + 2); ts << "{alpha: " << m_alphaFunc << "}]\n"; - m_in->externalRepresentation(ts, indent + 1); + inputEffect(0)->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.h b/WebCore/platform/graphics/filters/FEComponentTransfer.h index 834d9ee..55724db 100644 --- a/WebCore/platform/graphics/filters/FEComponentTransfer.h +++ b/WebCore/platform/graphics/filters/FEComponentTransfer.h @@ -63,7 +63,7 @@ namespace WebCore { class FEComponentTransfer : public FilterEffect { public: - static PassRefPtr<FEComponentTransfer> create(FilterEffect*, const ComponentTransferFunction&, + static PassRefPtr<FEComponentTransfer> create(const ComponentTransferFunction&, const ComponentTransferFunction&, const ComponentTransferFunction&, const ComponentTransferFunction&); ComponentTransferFunction redFunction() const; @@ -78,16 +78,14 @@ namespace WebCore { ComponentTransferFunction alphaFunction() const; void setAlphaFunction(const ComponentTransferFunction&); - virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); } void apply(Filter*); void dump(); TextStream& externalRepresentation(TextStream&, int indent) const; private: - FEComponentTransfer(FilterEffect*,const ComponentTransferFunction&, const ComponentTransferFunction&, - const ComponentTransferFunction&, const ComponentTransferFunction&); + FEComponentTransfer(const ComponentTransferFunction&, const ComponentTransferFunction&, + const ComponentTransferFunction&, const ComponentTransferFunction&); - RefPtr<FilterEffect> m_in; ComponentTransferFunction m_redFunc; ComponentTransferFunction m_greenFunc; ComponentTransferFunction m_blueFunc; diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp index d9f00ce..c10a0f2 100644 --- a/WebCore/platform/graphics/filters/FEComposite.cpp +++ b/WebCore/platform/graphics/filters/FEComposite.cpp @@ -32,11 +32,8 @@ namespace WebCore { -FEComposite::FEComposite(FilterEffect* in, FilterEffect* in2, const CompositeOperationType& type, - const float& k1, const float& k2, const float& k3, const float& k4) +FEComposite::FEComposite(const CompositeOperationType& type, float k1, float k2, float k3, float k4) : FilterEffect() - , m_in(in) - , m_in2(in2) , m_type(type) , m_k1(k1) , m_k2(k2) @@ -45,10 +42,9 @@ FEComposite::FEComposite(FilterEffect* in, FilterEffect* in2, const CompositeOpe { } -PassRefPtr<FEComposite> FEComposite::create(FilterEffect* in, FilterEffect* in2, const CompositeOperationType& type, - const float& k1, const float& k2, const float& k3, const float& k4) +PassRefPtr<FEComposite> FEComposite::create(const CompositeOperationType& type, float k1, float k2, float k3, float k4) { - return adoptRef(new FEComposite(in, in2, type, k1, k2, k3, k4)); + return adoptRef(new FEComposite(type, k1, k2, k3, k4)); } CompositeOperationType FEComposite::operation() const @@ -119,9 +115,11 @@ inline void arithmetic(const RefPtr<CanvasPixelArray>& srcPixelArrayA, CanvasPix void FEComposite::apply(Filter* filter) { - m_in->apply(filter); - m_in2->apply(filter); - if (!m_in->resultImage() || !m_in2->resultImage()) + FilterEffect* in = inputEffect(0); + FilterEffect* in2 = inputEffect(1); + in->apply(filter); + in2->apply(filter); + if (!in->resultImage() || !in2->resultImage()) return; GraphicsContext* filterContext = getEffectContext(); @@ -131,33 +129,33 @@ void FEComposite::apply(Filter* filter) FloatRect srcRect = FloatRect(0.f, 0.f, -1.f, -1.f); switch (m_type) { case FECOMPOSITE_OPERATOR_OVER: - filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); - filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); + filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, calculateDrawingRect(in2->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates())); break; case FECOMPOSITE_OPERATOR_IN: filterContext->save(); - filterContext->clipToImageBuffer(m_in2->resultImage(), calculateDrawingRect(m_in2->scaledSubRegion())); - filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); + filterContext->clipToImageBuffer(in2->resultImage(), calculateDrawingRect(in2->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates())); filterContext->restore(); break; case FECOMPOSITE_OPERATOR_OUT: - filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); - filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, calculateDrawingRect(in2->repaintRectInLocalCoordinates()), srcRect, CompositeDestinationOut); break; case FECOMPOSITE_OPERATOR_ATOP: - filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); - filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop); + filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, calculateDrawingRect(in2->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates()), srcRect, CompositeSourceAtop); break; case FECOMPOSITE_OPERATOR_XOR: - filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); - filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR); + filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, calculateDrawingRect(in2->repaintRectInLocalCoordinates())); + filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, calculateDrawingRect(in->repaintRectInLocalCoordinates()), srcRect, CompositeXOR); break; case FECOMPOSITE_OPERATOR_ARITHMETIC: { - IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); - RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); + IntRect effectADrawingRect = calculateDrawingIntRect(in->repaintRectInLocalCoordinates()); + RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); - IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion()); - RefPtr<ImageData> imageData(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)); + IntRect effectBDrawingRect = calculateDrawingIntRect(in2->repaintRectInLocalCoordinates()); + RefPtr<ImageData> imageData(in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)); CanvasPixelArray* srcPixelArrayB(imageData->data()); arithmetic(srcPixelArrayA, srcPixelArrayB, m_k1, m_k2, m_k3, m_k4); @@ -210,8 +208,8 @@ TextStream& FEComposite::externalRepresentation(TextStream& ts, int indent) cons if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) ts << " k1=\"" << m_k1 << "\" k2=\"" << m_k2 << "\" k3=\"" << m_k3 << "\" k4=\"" << m_k4 << "\""; ts << "]\n"; - m_in->externalRepresentation(ts, indent + 1); - m_in2->externalRepresentation(ts, indent + 1); + inputEffect(0)->externalRepresentation(ts, indent + 1); + inputEffect(1)->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/platform/graphics/filters/FEComposite.h b/WebCore/platform/graphics/filters/FEComposite.h index 11268c7..448d036 100644 --- a/WebCore/platform/graphics/filters/FEComposite.h +++ b/WebCore/platform/graphics/filters/FEComposite.h @@ -42,8 +42,7 @@ enum CompositeOperationType { class FEComposite : public FilterEffect { public: - static PassRefPtr<FEComposite> create(FilterEffect*, FilterEffect*, const CompositeOperationType&, - const float&, const float&, const float&, const float&); + static PassRefPtr<FEComposite> create(const CompositeOperationType&, float, float, float, float); CompositeOperationType operation() const; void setOperation(CompositeOperationType); @@ -60,17 +59,13 @@ public: float k4() const; void setK4(float); - virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get(), m_in2.get()); } void apply(Filter*); void dump(); TextStream& externalRepresentation(TextStream&, int indent) const; private: - FEComposite(FilterEffect*, FilterEffect*, const CompositeOperationType&, - const float&, const float&, const float&, const float&); + FEComposite(const CompositeOperationType&, float, float, float, float); - RefPtr<FilterEffect> m_in; - RefPtr<FilterEffect> m_in2; CompositeOperationType m_type; float m_k1; float m_k2; diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp index 44bb65a..72a5a04 100644 --- a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp +++ b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp @@ -38,17 +38,16 @@ static const float gGaussianKernelFactor = (3 * sqrtf(2 * piFloat) / 4.f); namespace WebCore { -FEGaussianBlur::FEGaussianBlur(FilterEffect* in, const float& x, const float& y) +FEGaussianBlur::FEGaussianBlur(float x, float y) : FilterEffect() - , m_in(in) , m_stdX(x) , m_stdY(y) { } -PassRefPtr<FEGaussianBlur> FEGaussianBlur::create(FilterEffect* in, const float& x, const float& y) +PassRefPtr<FEGaussianBlur> FEGaussianBlur::create(float x, float y) { - return adoptRef(new FEGaussianBlur(in, x, y)); + return adoptRef(new FEGaussianBlur(x, y)); } float FEGaussianBlur::stdDeviationX() const @@ -128,17 +127,18 @@ void FEGaussianBlur::kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& void FEGaussianBlur::apply(Filter* filter) { - m_in->apply(filter); - if (!m_in->resultImage()) + FilterEffect* in = inputEffect(0); + in->apply(filter); + if (!in->resultImage()) return; if (!getEffectContext()) return; - setIsAlphaImage(m_in->isAlphaImage()); + setIsAlphaImage(in->isAlphaImage()); - IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); - RefPtr<ImageData> srcImageData(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect)); + IntRect effectDrawingRect = calculateDrawingIntRect(in->repaintRectInLocalCoordinates()); + RefPtr<ImageData> srcImageData(in->resultImage()->getPremultipliedImageData(effectDrawingRect)); IntRect imageRect(IntPoint(), resultImage()->size()); if (!m_stdX && !m_stdY) { @@ -196,7 +196,7 @@ TextStream& FEGaussianBlur::externalRepresentation(TextStream& ts, int indent) c ts << "[feGaussianBlur"; FilterEffect::externalRepresentation(ts); ts << " stdDeviation=\"" << m_stdX << ", " << m_stdY << "\"]\n"; - m_in->externalRepresentation(ts, indent + 1); + inputEffect(0)->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.h b/WebCore/platform/graphics/filters/FEGaussianBlur.h index ad5c5a3..63d763e 100644 --- a/WebCore/platform/graphics/filters/FEGaussianBlur.h +++ b/WebCore/platform/graphics/filters/FEGaussianBlur.h @@ -30,7 +30,7 @@ namespace WebCore { class FEGaussianBlur : public FilterEffect { public: - static PassRefPtr<FEGaussianBlur> create(FilterEffect*, const float&, const float&); + static PassRefPtr<FEGaussianBlur> create(float, float); float stdDeviationX() const; void setStdDeviationX(float); @@ -38,7 +38,6 @@ public: float stdDeviationY() const; void setStdDeviationY(float); - virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); } void apply(Filter*); void dump(); TextStream& externalRepresentation(TextStream&, int indent) const; @@ -46,10 +45,9 @@ public: static float calculateStdDeviation(float); private: - FEGaussianBlur(FilterEffect*, const float&, const float&); + FEGaussianBlur(float, float); static void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight); - RefPtr<FilterEffect> m_in; float m_stdX; float m_stdY; }; diff --git a/WebCore/platform/graphics/filters/Filter.h b/WebCore/platform/graphics/filters/Filter.h index 16d499f..7ad25aa 100644 --- a/WebCore/platform/graphics/filters/Filter.h +++ b/WebCore/platform/graphics/filters/Filter.h @@ -48,7 +48,7 @@ namespace WebCore { virtual FloatRect filterRegion() const = 0; // SVG specific - virtual void calculateEffectSubRegion(FilterEffect*) { } + virtual void determineFilterPrimitiveSubregion(FilterEffect*, const FloatRect&) { } virtual FloatSize maxImageSize() const = 0; virtual bool effectBoundingBoxMode() const = 0; diff --git a/WebCore/platform/graphics/filters/FilterEffect.cpp b/WebCore/platform/graphics/filters/FilterEffect.cpp index 4d7265c..b6278b2 100644 --- a/WebCore/platform/graphics/filters/FilterEffect.cpp +++ b/WebCore/platform/graphics/filters/FilterEffect.cpp @@ -1,21 +1,23 @@ /* - Copyright (C) Alex Mathews <possessedpenguinbob@gmail.com> - - 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 - aint 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. -*/ + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. 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. + */ #include "config.h" @@ -25,11 +27,11 @@ namespace WebCore { FilterEffect::FilterEffect() - : m_hasX(false) + : m_alphaImage(false) + , m_hasX(false) , m_hasY(false) , m_hasWidth(false) , m_hasHeight(false) - , m_alphaImage(false) { } @@ -37,43 +39,49 @@ FilterEffect::~FilterEffect() { } -FloatRect FilterEffect::calculateUnionOfChildEffectSubregions(Filter* filter, FilterEffect* in) -{ - return in->calculateEffectRect(filter); -} - -FloatRect FilterEffect::calculateUnionOfChildEffectSubregions(Filter* filter, FilterEffect* in, FilterEffect* in2) +FloatRect FilterEffect::determineFilterPrimitiveSubregion(Filter* filter) { - FloatRect uniteEffectRect = in->calculateEffectRect(filter); - uniteEffectRect.unite(in2->calculateEffectRect(filter)); - return uniteEffectRect; + FloatRect uniteRect; + unsigned size = m_inputEffects.size(); + + // FETurbulence, FEImage and FEFlood don't have input effects, take the filter region as unite rect. + if (!size) + uniteRect = filter->filterRegion(); + else { + for (unsigned i = 0; i < size; ++i) + uniteRect.unite(m_inputEffects.at(i)->determineFilterPrimitiveSubregion(filter)); + } + + filter->determineFilterPrimitiveSubregion(this, uniteRect); + return m_filterPrimitiveSubregion; } -FloatRect FilterEffect::calculateEffectRect(Filter* filter) +IntRect FilterEffect::calculateDrawingIntRect(const FloatRect& effectRect) const { - setUnionOfChildEffectSubregions(uniteChildEffectSubregions(filter)); - filter->calculateEffectSubRegion(this); - return subRegion(); + ASSERT(m_effectBuffer); + FloatPoint location = m_repaintRectInLocalCoordinates.location(); + location.move(-effectRect.x(), -effectRect.y()); + return IntRect(roundedIntPoint(location), m_effectBuffer->size()); } -IntRect FilterEffect::calculateDrawingIntRect(const FloatRect& effectRect) +FloatRect FilterEffect::calculateDrawingRect(const FloatRect& srcRect) const { - IntPoint location = roundedIntPoint(FloatPoint(scaledSubRegion().x() - effectRect.x(), - scaledSubRegion().y() - effectRect.y())); - return IntRect(location, resultImage()->size()); + return FloatRect(FloatPoint(srcRect.x() - m_repaintRectInLocalCoordinates.x(), + srcRect.y() - m_repaintRectInLocalCoordinates.y()), srcRect.size()); } -FloatRect FilterEffect::calculateDrawingRect(const FloatRect& srcRect) +FilterEffect* FilterEffect::inputEffect(unsigned number) const { - FloatPoint startPoint = FloatPoint(srcRect.x() - scaledSubRegion().x(), srcRect.y() - scaledSubRegion().y()); - FloatRect drawingRect = FloatRect(startPoint, srcRect.size()); - return drawingRect; + ASSERT(number < m_inputEffects.size()); + return m_inputEffects.at(number).get(); } GraphicsContext* FilterEffect::getEffectContext() { - IntRect bufferRect = enclosingIntRect(scaledSubRegion()); + IntRect bufferRect = enclosingIntRect(m_repaintRectInLocalCoordinates); m_effectBuffer = ImageBuffer::create(bufferRect.size(), LinearRGB); + if (!m_effectBuffer) + return 0; return m_effectBuffer->context(); } diff --git a/WebCore/platform/graphics/filters/FilterEffect.h b/WebCore/platform/graphics/filters/FilterEffect.h index 3b8b5a3..91c52f3 100644 --- a/WebCore/platform/graphics/filters/FilterEffect.h +++ b/WebCore/platform/graphics/filters/FilterEffect.h @@ -1,22 +1,23 @@ /* - Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> - 2009 Dirk Schulze <krit@webkit.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - aint 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. -*/ + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ #ifndef FilterEffect_h #define FilterEffect_h @@ -32,84 +33,97 @@ #include <wtf/PassOwnPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> +#include <wtf/Vector.h> namespace WebCore { - class FilterEffect : public RefCounted<FilterEffect> { - public: - virtual ~FilterEffect(); +typedef Vector<RefPtr<FilterEffect> > FilterEffectVector; + +class FilterEffect : public RefCounted<FilterEffect> { +public: + virtual ~FilterEffect(); + + // The result is bounded to the size of the filter primitive to save resources. + ImageBuffer* resultImage() const { return m_effectBuffer.get(); } + void setEffectBuffer(PassOwnPtr<ImageBuffer> effectBuffer) { m_effectBuffer = effectBuffer; } + + // Creates the ImageBuffer for the current filter primitive result in the size of the + // repaintRect. Gives back the GraphicsContext of the own ImageBuffer. + GraphicsContext* getEffectContext(); - void setUnionOfChildEffectSubregions(const FloatRect& uniteRect) { m_unionOfChildEffectSubregions = uniteRect; } - FloatRect unionOfChildEffectSubregions() const { return m_unionOfChildEffectSubregions; } + FilterEffectVector& inputEffects() { return m_inputEffects; } + FilterEffect* inputEffect(unsigned) const; + unsigned numberOfEffectInputs() const { return m_inputEffects.size(); } - FloatRect subRegion() const { return m_subRegion; } - void setSubRegion(const FloatRect& subRegion) { m_subRegion = subRegion; } + FloatRect calculateDrawingRect(const FloatRect&) const; + IntRect calculateDrawingIntRect(const FloatRect&) const; - FloatRect scaledSubRegion() const { return m_scaledSubRegion; } - void setScaledSubRegion(const FloatRect& scaledSubRegion) { m_scaledSubRegion = scaledSubRegion; } + // Solid black image with different alpha values. + bool isAlphaImage() const { return m_alphaImage; } + void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; } - FloatRect effectBoundaries() const { return m_effectBoundaries; } - void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; } + FloatRect repaintRectInLocalCoordinates() const { return m_repaintRectInLocalCoordinates; } + void setRepaintRectInLocalCoordinates(const FloatRect& repaintRectInLocalCoordinates) { m_repaintRectInLocalCoordinates = repaintRectInLocalCoordinates; } - bool hasX() { return m_hasX; } - void setHasX(bool value) { m_hasX = value; } + virtual void apply(Filter*) = 0; + virtual void dump() = 0; - bool hasY() { return m_hasY; } - void setHasY(bool value) { m_hasY = value; } + virtual bool isSourceInput() const { return false; } - bool hasWidth() { return m_hasWidth; } - void setHasWidth(bool value) { m_hasWidth = value; } + virtual TextStream& externalRepresentation(TextStream&, int indention = 0) const; - bool hasHeight() { return m_hasHeight; } - void setHasHeight(bool value) { m_hasHeight = value; } +public: + // The following functions are SVG specific and will move to RenderSVGResourceFilterPrimitive. + // See bug https://bugs.webkit.org/show_bug.cgi?id=45614. + bool hasX() const { return m_hasX; } + void setHasX(bool value) { m_hasX = value; } - // The result is bounded by the size of the filter primitive to save resources - ImageBuffer* resultImage() { return m_effectBuffer.get(); } - void setEffectBuffer(PassOwnPtr<ImageBuffer> effectBuffer) { m_effectBuffer = effectBuffer; } + bool hasY() const { return m_hasY; } + void setHasY(bool value) { m_hasY = value; } - FloatRect calculateUnionOfChildEffectSubregions(Filter*, FilterEffect*, FilterEffect*); - FloatRect calculateUnionOfChildEffectSubregions(Filter*, FilterEffect*); + bool hasWidth() const { return m_hasWidth; } + void setHasWidth(bool value) { m_hasWidth = value; } - GraphicsContext* getEffectContext(); - FloatRect calculateDrawingRect(const FloatRect&); - IntRect calculateDrawingIntRect(const FloatRect&); + bool hasHeight() const { return m_hasHeight; } + void setHasHeight(bool value) { m_hasHeight = value; } - // black image with different alpha values - bool isAlphaImage() { return m_alphaImage; } - void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; } + // FIXME: Pseudo primitives like SourceGraphic and SourceAlpha as well as FETile still need special handling. + virtual FloatRect determineFilterPrimitiveSubregion(Filter*); - virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return filter->filterRegion(); } - virtual FloatRect calculateEffectRect(Filter*); - virtual void apply(Filter*) = 0; - virtual void dump() = 0; + FloatRect filterPrimitiveSubregion() const { return m_filterPrimitiveSubregion; } + void setFilterPrimitiveSubregion(const FloatRect& filterPrimitiveSubregion) { m_filterPrimitiveSubregion = filterPrimitiveSubregion; } - virtual bool isSourceInput() { return false; } + FloatRect effectBoundaries() const { return m_effectBoundaries; } + void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; } - virtual TextStream& externalRepresentation(TextStream&, int indention = 0) const; - protected: - FilterEffect(); +protected: + FilterEffect(); - private: +private: + OwnPtr<ImageBuffer> m_effectBuffer; + FilterEffectVector m_inputEffects; - bool m_xBBoxMode : 1; - bool m_yBBoxMode : 1; - bool m_widthBBoxMode : 1; - bool m_heightBBoxMode : 1; + bool m_alphaImage; - bool m_hasX : 1; - bool m_hasY : 1; - bool m_hasWidth : 1; - bool m_hasHeight : 1; + // FIXME: Should be the paint region of the filter primitive, instead of the scaled subregion on use of filterRes. + FloatRect m_repaintRectInLocalCoordinates; - bool m_alphaImage; +private: + // The following member variables are SVG specific and will move to RenderSVGResourceFilterPrimitive. + // See bug https://bugs.webkit.org/show_bug.cgi?id=45614. - FloatRect m_effectBoundaries; - FloatRect m_subRegion; - FloatRect m_scaledSubRegion; - FloatRect m_unionOfChildEffectSubregions; + // The subregion of a filter primitive according to the SVG Filter specification in local coordinates. + // This is SVG specific and needs to move to RenderSVGResourceFilterPrimitive. + FloatRect m_filterPrimitiveSubregion; - mutable OwnPtr<ImageBuffer> m_effectBuffer; - }; + // x, y, width and height of the actual SVGFE*Element. Is needed to determine the subregion of the + // filter primitive on a later step. + FloatRect m_effectBoundaries; + bool m_hasX; + bool m_hasY; + bool m_hasWidth; + bool m_hasHeight; +}; } // namespace WebCore diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp index 37b0023..9c6a953 100644 --- a/WebCore/platform/graphics/filters/SourceAlpha.cpp +++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp @@ -42,16 +42,16 @@ const AtomicString& SourceAlpha::effectName() return s_effectName; } -FloatRect SourceAlpha::calculateEffectRect(Filter* filter) +FloatRect SourceAlpha::determineFilterPrimitiveSubregion(Filter* filter) { FloatRect clippedSourceRect = filter->sourceImageRect(); if (filter->sourceImageRect().x() < filter->filterRegion().x()) clippedSourceRect.setX(filter->filterRegion().x()); if (filter->sourceImageRect().y() < filter->filterRegion().y()) clippedSourceRect.setY(filter->filterRegion().y()); - setSubRegion(clippedSourceRect); + setFilterPrimitiveSubregion(clippedSourceRect); clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height()); - setScaledSubRegion(clippedSourceRect); + setRepaintRectInLocalCoordinates(clippedSourceRect); return filter->filterRegion(); } diff --git a/WebCore/platform/graphics/filters/SourceAlpha.h b/WebCore/platform/graphics/filters/SourceAlpha.h index e5c6815..25a17b2 100644 --- a/WebCore/platform/graphics/filters/SourceAlpha.h +++ b/WebCore/platform/graphics/filters/SourceAlpha.h @@ -34,11 +34,12 @@ namespace WebCore { static const AtomicString& effectName(); - virtual bool isSourceInput() { return true; } - virtual FloatRect calculateEffectRect(Filter*); void apply(Filter*); void dump(); TextStream& externalRepresentation(TextStream&, int indent) const; + + virtual bool isSourceInput() const { return true; } + virtual FloatRect determineFilterPrimitiveSubregion(Filter*); private: SourceAlpha() { } diff --git a/WebCore/platform/graphics/filters/SourceGraphic.cpp b/WebCore/platform/graphics/filters/SourceGraphic.cpp index 5730d34..6a32e36 100644 --- a/WebCore/platform/graphics/filters/SourceGraphic.cpp +++ b/WebCore/platform/graphics/filters/SourceGraphic.cpp @@ -41,16 +41,16 @@ const AtomicString& SourceGraphic::effectName() return s_effectName; } -FloatRect SourceGraphic::calculateEffectRect(Filter* filter) +FloatRect SourceGraphic::determineFilterPrimitiveSubregion(Filter* filter) { FloatRect clippedSourceRect = filter->sourceImageRect(); if (filter->sourceImageRect().x() < filter->filterRegion().x()) clippedSourceRect.setX(filter->filterRegion().x()); if (filter->sourceImageRect().y() < filter->filterRegion().y()) clippedSourceRect.setY(filter->filterRegion().y()); - setSubRegion(clippedSourceRect); + setFilterPrimitiveSubregion(clippedSourceRect); clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height()); - setScaledSubRegion(clippedSourceRect); + setRepaintRectInLocalCoordinates(clippedSourceRect); return filter->filterRegion(); } diff --git a/WebCore/platform/graphics/filters/SourceGraphic.h b/WebCore/platform/graphics/filters/SourceGraphic.h index 05238a2..911648c 100644 --- a/WebCore/platform/graphics/filters/SourceGraphic.h +++ b/WebCore/platform/graphics/filters/SourceGraphic.h @@ -35,12 +35,13 @@ namespace WebCore { static const AtomicString& effectName(); - virtual bool isSourceInput() { return true; } - virtual FloatRect calculateEffectRect(Filter*); void apply(Filter*); void dump(); TextStream& externalRepresentation(TextStream&, int indent) const; - + + virtual bool isSourceInput() const { return true; } + virtual FloatRect determineFilterPrimitiveSubregion(Filter*); + private: SourceGraphic() { } }; diff --git a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp index 6424293..7629735 100644 --- a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp +++ b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp @@ -58,11 +58,13 @@ SharedGraphicsContext3D::SharedGraphicsContext3D(PassOwnPtr<GraphicsContext3D> c , m_solidFillShader(SolidFillShader::create(m_context.get())) , m_texShader(TexShader::create(m_context.get())) { + allContexts()->add(this); } SharedGraphicsContext3D::~SharedGraphicsContext3D() { m_context->deleteBuffer(m_quadVertices); + allContexts()->remove(this); } void SharedGraphicsContext3D::makeContextCurrent() @@ -112,6 +114,11 @@ void SharedGraphicsContext3D::getIntegerv(unsigned long pname, int* value) m_context->getIntegerv(pname, value); } +void SharedGraphicsContext3D::flush() +{ + m_context->flush(); +} + unsigned SharedGraphicsContext3D::createFramebuffer() { return m_context->createFramebuffer(); @@ -162,6 +169,17 @@ bool SharedGraphicsContext3D::supportsBGRA() return m_context->supportsBGRA(); } +bool SharedGraphicsContext3D::supportsCopyTextureToParentTextureCHROMIUM() + +{ + return m_context->supportsCopyTextureToParentTextureCHROMIUM(); +} + +void SharedGraphicsContext3D::copyTextureToParentTextureCHROMIUM(unsigned texture, unsigned parentTexture) +{ + return m_context->copyTextureToParentTextureCHROMIUM(texture, parentTexture); +} + Texture* SharedGraphicsContext3D::createTexture(NativeImagePtr ptr, Texture::Format format, int width, int height) { RefPtr<Texture> texture = m_textures.get(ptr); @@ -180,6 +198,28 @@ Texture* SharedGraphicsContext3D::getTexture(NativeImagePtr ptr) return texture ? texture.get() : 0; } +void SharedGraphicsContext3D::removeTextureFor(NativeImagePtr ptr) +{ + TextureHashMap::iterator it = m_textures.find(ptr); + if (it != m_textures.end()) + m_textures.remove(it); +} + +// static +void SharedGraphicsContext3D::removeTexturesFor(NativeImagePtr ptr) +{ + for (HashSet<SharedGraphicsContext3D*>::iterator it = allContexts()->begin(); it != allContexts()->end(); ++it) + (*it)->removeTextureFor(ptr); +} + +// static +HashSet<SharedGraphicsContext3D*>* SharedGraphicsContext3D::allContexts() +{ + static OwnPtr<HashSet<SharedGraphicsContext3D*> > set(new HashSet<SharedGraphicsContext3D*>); + return set.get(); +} + + PassRefPtr<Texture> SharedGraphicsContext3D::createTexture(Texture::Format format, int width, int height) { return Texture::create(m_context.get(), format, width, height); diff --git a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h index 1baa0f6..3ba3c52 100644 --- a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h +++ b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h @@ -36,6 +36,7 @@ #include "Texture.h" #include <wtf/HashMap.h> +#include <wtf/HashSet.h> #include <wtf/OwnPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -69,6 +70,7 @@ public: void drawArrays(unsigned long mode, long first, long count); unsigned long getError(); void getIntegerv(unsigned long pname, int* value); + void flush(); unsigned createFramebuffer(); unsigned createTexture(); @@ -97,17 +99,30 @@ public: bool supportsBGRA(); + // GL_CHROMIUM_copy_texture_to_parent_texture + bool supportsCopyTextureToParentTextureCHROMIUM(); + void copyTextureToParentTextureCHROMIUM(unsigned texture, unsigned parentTexture); + // Creates a texture associated with the given image. Is owned by this context's // TextureHashMap. Texture* createTexture(NativeImagePtr, Texture::Format, int width, int height); Texture* getTexture(NativeImagePtr); + // Multiple SharedGraphicsContext3D can exist in a single process (one per compositing context) and the same + // NativeImagePtr may be uploaded as a texture into all of them. This function removes uploaded textures + // for a given NativeImagePtr in all contexts. + static void removeTexturesFor(NativeImagePtr); + // Creates a texture that is not associated with any image. The caller takes ownership of // the texture. PassRefPtr<Texture> createTexture(Texture::Format, int width, int height); private: - SharedGraphicsContext3D(PassOwnPtr<GraphicsContext3D> context); + explicit SharedGraphicsContext3D(PassOwnPtr<GraphicsContext3D> context); + + // Used to implement removeTexturesFor(), see the comment above. + static HashSet<SharedGraphicsContext3D*>* allContexts(); + void removeTextureFor(NativeImagePtr); OwnPtr<GraphicsContext3D> m_context; diff --git a/WebCore/platform/graphics/gpu/SolidFillShader.cpp b/WebCore/platform/graphics/gpu/SolidFillShader.cpp index bbc4792..ff1b1fa 100644 --- a/WebCore/platform/graphics/gpu/SolidFillShader.cpp +++ b/WebCore/platform/graphics/gpu/SolidFillShader.cpp @@ -54,7 +54,9 @@ PassOwnPtr<SolidFillShader> SolidFillShader::create(GraphicsContext3D* context) " gl_Position = vec4(matrix * position, 1.0);\n" "}\n"; static const char* fragmentShaderSource = + "#ifdef GL_ES\n" "precision mediump float;\n" + "#endif\n" "uniform mat3 matrix;\n" "uniform vec4 color;\n" "void main() {\n" diff --git a/WebCore/platform/graphics/gpu/TexShader.cpp b/WebCore/platform/graphics/gpu/TexShader.cpp index ba3ecdd..01f4306 100644 --- a/WebCore/platform/graphics/gpu/TexShader.cpp +++ b/WebCore/platform/graphics/gpu/TexShader.cpp @@ -57,7 +57,9 @@ PassOwnPtr<TexShader> TexShader::create(GraphicsContext3D* context) " gl_Position = vec4(matrix * position, 1.0);\n" "}\n"; static const char* fragmentShaderSource = + "#ifdef GL_ES\n" "precision mediump float;\n" + "#endif\n" "uniform sampler2D sampler;\n" "uniform float alpha;\n" "varying vec3 texCoord;\n" diff --git a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp index 2ff4f38..efccff0 100644 --- a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp +++ b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp @@ -195,7 +195,11 @@ void GStreamerGWorld::setWindowOverlay(GstMessage* message) g_object_set(sink, "force-aspect-ratio", TRUE, NULL); if (m_videoWindow) +#if GST_CHECK_VERSION(0, 10, 31) || GST_VERSION_NANO + gst_x_overlay_set_window_handle(GST_X_OVERLAY(sink), m_videoWindow->videoWindowId()); +#else gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(sink), m_videoWindow->videoWindowId()); +#endif } } diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index 4791b4c..0071d67 100644 --- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -23,6 +23,7 @@ #include "config.h" #include "MediaPlayerPrivateGStreamer.h" + #if ENABLE(VIDEO) #include "ColorSpace.h" @@ -40,19 +41,15 @@ #include "MIMETypeRegistry.h" #include "MediaPlayer.h" #include "NotImplemented.h" -#include "ScrollView.h" #include "SecurityOrigin.h" #include "TimeRanges.h" #include "VideoSinkGStreamer.h" #include "WebKitWebSourceGStreamer.h" -#include "Widget.h" #include <GOwnPtr.h> #include <gst/gst.h> -#include <gst/interfaces/mixer.h> #include <gst/video/video.h> #include <limits> #include <math.h> -#include <wtf/text/CString.h> // GstPlayFlags flags from playbin2. It is the policy of GStreamer to // not publicly expose element-specific enums. That's why this diff --git a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp index bcd59c6..4e57193 100644 --- a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp @@ -23,6 +23,7 @@ #include "Document.h" #include "GOwnPtr.h" #include "GRefPtr.h" +#include "NetworkingContext.h" #include "Noncopyable.h" #include "NotImplemented.h" #include "ResourceHandleClient.h" @@ -43,7 +44,7 @@ class StreamingClient : public Noncopyable, public ResourceHandleClient { virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse&); virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); virtual void didReceiveData(ResourceHandle*, const char*, int, int); - virtual void didFinishLoading(ResourceHandle*); + virtual void didFinishLoading(ResourceHandle*, double /*finishTime*/); virtual void didFail(ResourceHandle*, const ResourceError&); virtual void wasBlocked(ResourceHandle*); virtual void cannotShowURL(ResourceHandle*); @@ -391,14 +392,17 @@ static bool webKitWebSrcStart(WebKitWebSrc* src) request.setTargetType(ResourceRequestBase::TargetIsMedia); request.setAllowCookies(true); + NetworkingContext* context = 0; if (priv->frame) { Document* document = priv->frame->document(); if (document) request.setHTTPReferrer(document->documentURI()); FrameLoader* loader = priv->frame->loader(); - if (loader) + if (loader) { loader->addExtraFieldsToSubresourceRequest(request); + context = loader->networkingContext(); + } } // Let Apple web servers know we want to access their nice movie trailers. @@ -419,7 +423,7 @@ static bool webKitWebSrcStart(WebKitWebSrc* src) // Needed to use DLNA streaming servers request.setHTTPHeaderField("transferMode.dlna", "Streaming"); - priv->resourceHandle = ResourceHandle::create(request, priv->client, 0, false, false); + priv->resourceHandle = ResourceHandle::create(context, request, priv->client, false, false); if (!priv->resourceHandle) { GST_ERROR_OBJECT(src, "Failed to create ResourceHandle"); return false; @@ -762,7 +766,7 @@ void StreamingClient::didReceiveData(ResourceHandle* handle, const char* data, i GST_ELEMENT_ERROR(m_src, CORE, FAILED, (0), (0)); } -void StreamingClient::didFinishLoading(ResourceHandle*) +void StreamingClient::didFinishLoading(ResourceHandle*, double) { WebKitWebSrcPrivate* priv = m_src->priv; diff --git a/WebCore/platform/graphics/gtk/FontCachePango.cpp b/WebCore/platform/graphics/gtk/FontCachePango.cpp new file mode 100644 index 0000000..fad29e0 --- /dev/null +++ b/WebCore/platform/graphics/gtk/FontCachePango.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2008 Alp Toker <alp@atoker.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "FontCache.h" + +#include "CString.h" +#include "Font.h" +#include "OwnPtrCairo.h" +#include "SimpleFontData.h" +#include <wtf/Assertions.h> + +namespace WebCore { + +void FontCache::platformInit() +{ + if (!FontPlatformData::init()) + ASSERT_NOT_REACHED(); +} + +const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +{ + return 0; +} + +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +{ + return 0; +} + +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) +{ + // FIXME: Would be even better to somehow get the user's default font here. + // For now we'll pick the default that the user would get without changing any prefs. + static AtomicString timesStr("Times New Roman"); + return getCachedFontData(fontDescription, timesStr); +} + +void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks) +{ +} + +FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) +{ + return new FontPlatformData(fontDescription, family); +} + +} diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp index 489bad7..27f48fc 100644 --- a/WebCore/platform/graphics/gtk/FontGtk.cpp +++ b/WebCore/platform/graphics/gtk/FontGtk.cpp @@ -139,7 +139,7 @@ static void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout { #if defined(USE_FREETYPE) if (font->primaryFont()->platformData().m_pattern) { - PangoFontDescription* desc = pango_fc_font_description_from_pattern(font->primaryFont()->platformData().m_pattern, FALSE); + PangoFontDescription* desc = pango_fc_font_description_from_pattern(font->primaryFont()->platformData().m_pattern.get(), FALSE); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); } diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataPango.h b/WebCore/platform/graphics/gtk/FontPlatformDataPango.h new file mode 100644 index 0000000..7b1e51f --- /dev/null +++ b/WebCore/platform/graphics/gtk/FontPlatformDataPango.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2007 Pioneer Research Center USA, 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. + * + */ + +#ifndef FontPlatformDataPango_h +#define FontPlatformDataPango_h + +#include "FontDescription.h" +#include "GlyphBuffer.h" +#include <cairo.h> +#include <pango/pangocairo.h> +#include <wtf/Forward.h> + +namespace WebCore { + +class FontPlatformData { +public: + FontPlatformData(WTF::HashTableDeletedValueType) + : m_context(0) + , m_font(hashTableDeletedFontValue()) + , m_size(0) + , m_syntheticBold(false) + , m_syntheticOblique(false) + , m_scaledFont(0) + { } + + FontPlatformData() + : m_context(0) + , m_font(0) + , m_size(0) + , m_syntheticBold(false) + , m_syntheticOblique(false) + , m_scaledFont(0) + { } + + FontPlatformData(const FontDescription&, const AtomicString& family); + FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic); + FontPlatformData(float size, bool bold, bool italic); + FontPlatformData(const FontPlatformData&); + ~FontPlatformData(); + + static bool init(); + bool isFixedPitch(); + float size() const { return m_size; } + void setSize(float size) { m_size = size; } + bool syntheticBold() const { return m_syntheticBold; } + bool syntheticOblique() const { return m_syntheticOblique; } + + cairo_scaled_font_t* scaledFont() const { return m_scaledFont; } + + unsigned hash() const + { + uintptr_t hashCodes[1] = { reinterpret_cast<uintptr_t>(m_scaledFont) }; + return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar)); + } + + bool operator==(const FontPlatformData&) const; + FontPlatformData& operator=(const FontPlatformData&); + bool isHashTableDeletedValue() const + { + return m_font == hashTableDeletedFontValue(); + } + +#ifndef NDEBUG + String description() const; +#endif + + static PangoFontMap* m_fontMap; + static GHashTable* m_hashTable; + PangoContext* m_context; + PangoFont* m_font; + float m_size; + bool m_syntheticBold; + bool m_syntheticOblique; + cairo_scaled_font_t* m_scaledFont; +private: + static PangoFont *hashTableDeletedFontValue() { return reinterpret_cast<PangoFont*>(-1); } +}; + +} + +#endif // FontPlatformDataPango_h diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index 54b261c..a4919d8 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -31,21 +31,22 @@ #import "BlockExceptions.h" +#include "ANGLE/ShaderLang.h" #include "ArrayBuffer.h" #include "ArrayBufferView.h" -#include "WebGLObject.h" #include "CanvasRenderingContext.h" +#include <CoreGraphics/CGBitmapContext.h> #include "Float32Array.h" #include "GraphicsContext.h" #include "HTMLCanvasElement.h" #include "ImageBuffer.h" #include "Int32Array.h" #include "NotImplemented.h" -#include "Uint8Array.h" -#include "WebGLLayer.h" -#include <CoreGraphics/CGBitmapContext.h> #include <OpenGL/CGLRenderers.h> #include <OpenGL/gl.h> +#include "Uint8Array.h" +#include "WebGLLayer.h" +#include "WebGLObject.h" #include <wtf/UnusedParam.h> #include <wtf/text/CString.h> @@ -76,13 +77,16 @@ static void setPixelFormat(Vector<CGLPixelFormatAttribute>& attribs, int colorBi attribs.append(static_cast<CGLPixelFormatAttribute>(0)); } -PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) +PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) { - OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs, hostWindow)); + // This implementation doesn't currently support rendering directly to the HostWindow. + if (renderStyle == RenderDirectlyToHostWindow) + return 0; + OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs, hostWindow, false)); return context->m_contextObj ? context.release() : 0; } -GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) +GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, bool) : m_currentWidth(0) , m_currentHeight(0) , m_attrs(attrs) @@ -229,81 +233,14 @@ GraphicsContext3D::~GraphicsContext3D() } } -void GraphicsContext3D::validateAttributes() -{ - const char* extensions = reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS)); - if (m_attrs.stencil) { - if (std::strstr(extensions, "GL_EXT_packed_depth_stencil")) { - if (!m_attrs.depth) - m_attrs.depth = true; - } else - m_attrs.stencil = false; - } - if (m_attrs.antialias) { - bool isValidVendor = true; - // Currently in Mac we only turn on antialias if vendor is NVIDIA. - const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); - if (!std::strstr(vendor, "NVIDIA")) - isValidVendor = false; - if (!isValidVendor || !std::strstr(extensions, "GL_EXT_framebuffer_multisample")) - m_attrs.antialias = false; - } - // FIXME: instead of enforcing premultipliedAlpha = true, implement the - // correct behavior when premultipliedAlpha = false is requested. - m_attrs.premultipliedAlpha = true; -} - void GraphicsContext3D::makeContextCurrent() { - CGLSetCurrentContext(m_contextObj); -} - -void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context) -{ - HTMLCanvasElement* canvas = context->canvas(); - ImageBuffer* imageBuffer = canvas->buffer(); - - int rowBytes = m_currentWidth * 4; - int totalBytes = rowBytes * m_currentHeight; - - OwnArrayPtr<unsigned char> pixels(new unsigned char[totalBytes]); - if (!pixels) + if (!m_contextObj) return; - CGLSetCurrentContext(m_contextObj); - - bool mustRestoreFBO = false; - if (m_attrs.antialias) { - ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); - ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); - ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - mustRestoreFBO = true; - } else { - if (m_boundFBO != m_fbo) { - mustRestoreFBO = true; - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - } - } - - GLint packAlignment = 4; - bool mustRestorePackAlignment = false; - ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); - if (packAlignment > 4) { - ::glPixelStorei(GL_PACK_ALIGNMENT, 4); - mustRestorePackAlignment = true; - } - - ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels.get()); - - if (mustRestorePackAlignment) - ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); - - if (mustRestoreFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); - - paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, - canvas->width(), canvas->height(), imageBuffer->context()->platformContext()); + CGLContextObj currentContext = CGLGetCurrentContext(); + if (currentContext != m_contextObj) + CGLSetCurrentContext(m_contextObj); } bool GraphicsContext3D::isGLES2Compliant() const @@ -320,1343 +257,7 @@ bool GraphicsContext3D::isErrorGeneratedOnOutOfBoundsAccesses() const { return false; } - -void GraphicsContext3D::reshape(int width, int height) -{ - if (width == m_currentWidth && height == m_currentHeight || !m_contextObj) - return; - - m_currentWidth = width; - m_currentHeight = height; - - CGLSetCurrentContext(m_contextObj); - - GLuint internalColorFormat, colorFormat, internalDepthStencilFormat = 0; - if (m_attrs.alpha) { - internalColorFormat = GL_RGBA8; - colorFormat = GL_RGBA; - } else { - internalColorFormat = GL_RGB8; - colorFormat = GL_RGB; - } - if (m_attrs.stencil || m_attrs.depth) { - // We don't allow the logic where stencil is required and depth is not. - // See GraphicsContext3D constructor. - if (m_attrs.stencil && m_attrs.depth) - internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT; - else - internalDepthStencilFormat = GL_DEPTH_COMPONENT; - } - - bool mustRestoreFBO = false; - - // resize multisample FBO - if (m_attrs.antialias) { - GLint maxSampleCount; - ::glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSampleCount); - GLint sampleCount = std::min(8, maxSampleCount); - if (sampleCount > maxSampleCount) - sampleCount = maxSampleCount; - if (m_boundFBO != m_multisampleFBO) { - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); - mustRestoreFBO = true; - } - ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); - ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalColorFormat, width, height); - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); - if (m_attrs.stencil || m_attrs.depth) { - ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); - ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalDepthStencilFormat, width, height); - if (m_attrs.stencil) - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); - if (m_attrs.depth) - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); - } - ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { - // FIXME: cleanup. - notImplemented(); - } - } - - // resize regular FBO - if (m_boundFBO != m_fbo) { - mustRestoreFBO = true; - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - } - ::glBindTexture(GL_TEXTURE_2D, m_texture); - ::glTexImage2D(GL_TEXTURE_2D, 0, internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); - ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); - ::glBindTexture(GL_TEXTURE_2D, 0); - if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) { - ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer); - ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthStencilFormat, width, height); - if (m_attrs.stencil) - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); - if (m_attrs.depth) - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); - ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - } - if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { - // FIXME: cleanup - notImplemented(); - } - - if (m_attrs.antialias) { - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); - if (m_boundFBO == m_multisampleFBO) - mustRestoreFBO = false; - } - - // Initialize renderbuffers to 0. - GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMask = GL_TRUE, stencilMask = GL_TRUE; - GLboolean isScissorEnabled = GL_FALSE; - GLboolean isDitherEnabled = GL_FALSE; - GLbitfield clearMask = GL_COLOR_BUFFER_BIT; - ::glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); - ::glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - if (m_attrs.depth) { - ::glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); - ::glDepthMask(GL_TRUE); - clearMask |= GL_DEPTH_BUFFER_BIT; - } - if (m_attrs.stencil) { - ::glGetBooleanv(GL_STENCIL_WRITEMASK, &stencilMask); - ::glStencilMask(GL_TRUE); - clearMask |= GL_STENCIL_BUFFER_BIT; - } - isScissorEnabled = ::glIsEnabled(GL_SCISSOR_TEST); - ::glDisable(GL_SCISSOR_TEST); - isDitherEnabled = ::glIsEnabled(GL_DITHER); - ::glDisable(GL_DITHER); - - ::glClear(clearMask); - - ::glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); - if (m_attrs.depth) - ::glDepthMask(depthMask); - if (m_attrs.stencil) - ::glStencilMask(stencilMask); - if (isScissorEnabled) - ::glEnable(GL_SCISSOR_TEST); - else - ::glDisable(GL_SCISSOR_TEST); - if (isDitherEnabled) - ::glEnable(GL_DITHER); - else - ::glDisable(GL_DITHER); - - if (mustRestoreFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); - - ::glFlush(); -} - -static inline void ensureContext(CGLContextObj context) -{ - if (!context) - return; - - CGLContextObj currentContext = CGLGetCurrentContext(); - if (currentContext != context) - CGLSetCurrentContext(context); -} - -void GraphicsContext3D::prepareTexture() -{ - ensureContext(m_contextObj); - if (m_attrs.antialias) { - ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); - ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); - ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); - } - ::glFinish(); -} - -void GraphicsContext3D::activeTexture(unsigned long texture) -{ - ensureContext(m_contextObj); - ::glActiveTexture(texture); -} - -void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader) -{ - ASSERT(program); - ASSERT(shader); - ensureContext(m_contextObj); - ::glAttachShader((GLuint) program, (GLuint) shader); -} - -void GraphicsContext3D::bindAttribLocation(Platform3DObject program, unsigned long index, const String& name) -{ - ASSERT(program); - ensureContext(m_contextObj); - ::glBindAttribLocation((GLuint) program, index, name.utf8().data()); -} - -void GraphicsContext3D::bindBuffer(unsigned long target, Platform3DObject buffer) -{ - ensureContext(m_contextObj); - ::glBindBuffer(target, (GLuint) buffer); -} - - -void GraphicsContext3D::bindFramebuffer(unsigned long target, Platform3DObject buffer) -{ - ensureContext(m_contextObj); - GLuint fbo; - if (buffer) - fbo = (GLuint)buffer; - else - fbo = (m_attrs.antialias ? m_multisampleFBO : m_fbo); - if (fbo != m_boundFBO) { - ::glBindFramebufferEXT(target, fbo); - m_boundFBO = fbo; - } -} - -void GraphicsContext3D::bindRenderbuffer(unsigned long target, Platform3DObject renderbuffer) -{ - ensureContext(m_contextObj); - ::glBindRenderbufferEXT(target, (GLuint) renderbuffer); -} - - -void GraphicsContext3D::bindTexture(unsigned long target, Platform3DObject texture) -{ - ensureContext(m_contextObj); - ::glBindTexture(target, (GLuint) texture); -} - -void GraphicsContext3D::blendColor(double red, double green, double blue, double alpha) -{ - ensureContext(m_contextObj); - ::glBlendColor(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha)); -} - -void GraphicsContext3D::blendEquation( unsigned long mode ) -{ - ensureContext(m_contextObj); - ::glBlendEquation(mode); -} - -void GraphicsContext3D::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha) -{ - ensureContext(m_contextObj); - ::glBlendEquationSeparate(modeRGB, modeAlpha); -} - - -void GraphicsContext3D::blendFunc(unsigned long sfactor, unsigned long dfactor) -{ - ensureContext(m_contextObj); - ::glBlendFunc(sfactor, dfactor); -} - -void GraphicsContext3D::blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha) -{ - ensureContext(m_contextObj); - ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); -} - -void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long usage) -{ - ensureContext(m_contextObj); - ::glBufferData(target, size, 0, usage); -} - -void GraphicsContext3D::bufferData(unsigned long target, int size, const void* data, unsigned long usage) -{ - ensureContext(m_contextObj); - ::glBufferData(target, size, data, usage); -} - -void GraphicsContext3D::bufferSubData(unsigned long target, long offset, int size, const void* data) -{ - ensureContext(m_contextObj); - ::glBufferSubData(target, offset, size, data); -} - -unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target) -{ - ensureContext(m_contextObj); - return ::glCheckFramebufferStatusEXT(target); -} - -void GraphicsContext3D::clearColor(double r, double g, double b, double a) -{ - ensureContext(m_contextObj); - ::glClearColor(static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a)); -} - -void GraphicsContext3D::clear(unsigned long mask) -{ - ensureContext(m_contextObj); - ::glClear(mask); -} - -void GraphicsContext3D::clearDepth(double depth) -{ - ensureContext(m_contextObj); - ::glClearDepth(depth); -} - -void GraphicsContext3D::clearStencil(long s) -{ - ensureContext(m_contextObj); - ::glClearStencil(s); -} - -void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha) -{ - ensureContext(m_contextObj); - ::glColorMask(red, green, blue, alpha); -} - -void GraphicsContext3D::compileShader(Platform3DObject shader) -{ - ASSERT(shader); - ensureContext(m_contextObj); - - int GLshaderType; - ANGLEShaderType shaderType; - - glGetShaderiv(shader, SHADER_TYPE, &GLshaderType); - - if (GLshaderType == VERTEX_SHADER) - shaderType = SHADER_TYPE_VERTEX; - else if (GLshaderType == FRAGMENT_SHADER) - shaderType = SHADER_TYPE_FRAGMENT; - else - return; // Invalid shader type. - - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); - - if (result == m_shaderSourceMap.end()) - return; - - ShaderSourceEntry& entry = result->second; - - String translatedShaderSource; - String shaderInfoLog; - - bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog); - - entry.log = shaderInfoLog; - entry.isValid = isValid; - - if (!isValid) - return; // Shader didn't validate, don't move forward with compiling translated source - - int translatedShaderLength = translatedShaderSource.length(); - - const CString& translatedShaderCString = translatedShaderSource.utf8(); - const char* translatedShaderPtr = translatedShaderCString.data(); - - ::glShaderSource((GLuint) shader, 1, &translatedShaderPtr, &translatedShaderLength); - - ::glCompileShader((GLuint) shader); - - int GLCompileSuccess; - - ::glGetShaderiv((GLuint) shader, COMPILE_STATUS, &GLCompileSuccess); - - // ASSERT that ANGLE generated GLSL will be accepted by OpenGL - ASSERT(GLCompileSuccess == GL_TRUE); -} - -void GraphicsContext3D::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border) -{ - ensureContext(m_contextObj); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { - ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); - ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); - ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - } - ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); -} - -void GraphicsContext3D::copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height) -{ - ensureContext(m_contextObj); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { - ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); - ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); - ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - } - ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); -} - -void GraphicsContext3D::cullFace(unsigned long mode) -{ - ensureContext(m_contextObj); - ::glCullFace(mode); -} - -void GraphicsContext3D::depthFunc(unsigned long func) -{ - ensureContext(m_contextObj); - ::glDepthFunc(func); -} - -void GraphicsContext3D::depthMask(bool flag) -{ - ensureContext(m_contextObj); - ::glDepthMask(flag); -} - -void GraphicsContext3D::depthRange(double zNear, double zFar) -{ - ensureContext(m_contextObj); - ::glDepthRange(zNear, zFar); -} - -void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader) -{ - ASSERT(program); - ASSERT(shader); - ensureContext(m_contextObj); - ::glDetachShader((GLuint) program, (GLuint) shader); -} - -void GraphicsContext3D::disable(unsigned long cap) -{ - ensureContext(m_contextObj); - ::glDisable(cap); -} - -void GraphicsContext3D::disableVertexAttribArray(unsigned long index) -{ - ensureContext(m_contextObj); - ::glDisableVertexAttribArray(index); -} - -void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count) -{ - ensureContext(m_contextObj); - ::glDrawArrays(mode, first, count); -} - -void GraphicsContext3D::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset) -{ - ensureContext(m_contextObj); - ::glDrawElements(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset))); -} - -void GraphicsContext3D::enable(unsigned long cap) -{ - ensureContext(m_contextObj); - ::glEnable(cap); -} - -void GraphicsContext3D::enableVertexAttribArray(unsigned long index) -{ - ensureContext(m_contextObj); - ::glEnableVertexAttribArray(index); -} - -void GraphicsContext3D::finish() -{ - ensureContext(m_contextObj); - ::glFinish(); -} - -void GraphicsContext3D::flush() -{ - ensureContext(m_contextObj); - ::glFlush(); -} - -void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, Platform3DObject buffer) -{ - ensureContext(m_contextObj); - GLuint renderbuffer = (GLuint) buffer; - if (attachment == DEPTH_STENCIL_ATTACHMENT) { - ::glFramebufferRenderbufferEXT(target, DEPTH_ATTACHMENT, renderbuffertarget, renderbuffer); - ::glFramebufferRenderbufferEXT(target, STENCIL_ATTACHMENT, renderbuffertarget, renderbuffer); - } else - ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer); -} - -void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, Platform3DObject texture, long level) -{ - ensureContext(m_contextObj); - ::glFramebufferTexture2DEXT(target, attachment, textarget, (GLuint) texture, level); -} - -void GraphicsContext3D::frontFace(unsigned long mode) -{ - ensureContext(m_contextObj); - ::glFrontFace(mode); -} - -void GraphicsContext3D::generateMipmap(unsigned long target) -{ - ensureContext(m_contextObj); - ::glGenerateMipmapEXT(target); -} - -bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, unsigned long index, ActiveInfo& info) -{ - if (!program) { - synthesizeGLError(INVALID_VALUE); - return false; - } - ensureContext(m_contextObj); - GLint maxAttributeSize = 0; - ::glGetProgramiv(static_cast<GLuint>(program), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize); - GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination - GLsizei nameLength = 0; - GLint size = 0; - GLenum type = 0; - ::glGetActiveAttrib(static_cast<GLuint>(program), index, maxAttributeSize, &nameLength, &size, &type, name); - if (!nameLength) - return false; - info.name = String(name, nameLength); - info.type = type; - info.size = size; - return true; -} - -bool GraphicsContext3D::getActiveUniform(Platform3DObject program, unsigned long index, ActiveInfo& info) -{ - if (!program) { - synthesizeGLError(INVALID_VALUE); - return false; - } - ensureContext(m_contextObj); - GLint maxUniformSize = 0; - ::glGetProgramiv(static_cast<GLuint>(program), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize); - GLchar name[maxUniformSize]; // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination - GLsizei nameLength = 0; - GLint size = 0; - GLenum type = 0; - ::glGetActiveUniform(static_cast<GLuint>(program), index, maxUniformSize, &nameLength, &size, &type, name); - if (!nameLength) - return false; - info.name = String(name, nameLength); - info.type = type; - info.size = size; - return true; -} - -void GraphicsContext3D::getAttachedShaders(Platform3DObject program, int maxCount, int* count, unsigned int* shaders) -{ - if (!program) { - synthesizeGLError(INVALID_VALUE); - return; - } - ensureContext(m_contextObj); - ::glGetAttachedShaders(static_cast<GLuint>(program), maxCount, count, shaders); -} - -int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name) -{ - if (!program) - return -1; - - ensureContext(m_contextObj); - return ::glGetAttribLocation((GLuint) program, name.utf8().data()); -} - -GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() -{ - return m_attrs; -} - -unsigned long GraphicsContext3D::getError() -{ - if (m_syntheticErrors.size() > 0) { - ListHashSet<unsigned long>::iterator iter = m_syntheticErrors.begin(); - unsigned long err = *iter; - m_syntheticErrors.remove(iter); - return err; - } - - ensureContext(m_contextObj); - return ::glGetError(); -} - -String GraphicsContext3D::getString(unsigned long name) -{ - ensureContext(m_contextObj); - return String((const char*) ::glGetString(name)); -} - -void GraphicsContext3D::hint(unsigned long target, unsigned long mode) -{ - ensureContext(m_contextObj); - ::glHint(target, mode); -} - -bool GraphicsContext3D::isBuffer(Platform3DObject buffer) -{ - if (!buffer) - return false; - - ensureContext(m_contextObj); - return ::glIsBuffer((GLuint) buffer); -} - -bool GraphicsContext3D::isEnabled(unsigned long cap) -{ - ensureContext(m_contextObj); - return ::glIsEnabled(cap); -} - -bool GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer) -{ - if (!framebuffer) - return false; - - ensureContext(m_contextObj); - return ::glIsFramebufferEXT((GLuint) framebuffer); -} - -bool GraphicsContext3D::isProgram(Platform3DObject program) -{ - if (!program) - return false; - - ensureContext(m_contextObj); - return ::glIsProgram((GLuint) program); -} - -bool GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer) -{ - if (!renderbuffer) - return false; - - ensureContext(m_contextObj); - return ::glIsRenderbufferEXT((GLuint) renderbuffer); -} - -bool GraphicsContext3D::isShader(Platform3DObject shader) -{ - if (!shader) - return false; - - ensureContext(m_contextObj); - return ::glIsShader((GLuint) shader); -} - -bool GraphicsContext3D::isTexture(Platform3DObject texture) -{ - if (!texture) - return false; - - ensureContext(m_contextObj); - return ::glIsTexture((GLuint) texture); -} - -void GraphicsContext3D::lineWidth(double width) -{ - ensureContext(m_contextObj); - ::glLineWidth(static_cast<float>(width)); -} - -void GraphicsContext3D::linkProgram(Platform3DObject program) -{ - ASSERT(program); - ensureContext(m_contextObj); - ::glLinkProgram((GLuint) program); -} - -void GraphicsContext3D::pixelStorei(unsigned long pname, long param) -{ - ensureContext(m_contextObj); - ::glPixelStorei(pname, param); -} - -void GraphicsContext3D::polygonOffset(double factor, double units) -{ - ensureContext(m_contextObj); - ::glPolygonOffset(static_cast<float>(factor), static_cast<float>(units)); -} - -void GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* data) -{ - // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., - // all previous rendering calls should be done before reading pixels. - ensureContext(m_contextObj); - ::glFlush(); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { - ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); - ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); - ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - ::glFlush(); - } - ::glReadPixels(x, y, width, height, format, type, data); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); -} - -void GraphicsContext3D::releaseShaderCompiler() -{ - // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants - ensureContext(m_contextObj); - //::glReleaseShaderCompiler(); -} - -void GraphicsContext3D::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height) -{ - ensureContext(m_contextObj); - switch (internalformat) { - case DEPTH_STENCIL: - internalformat = GL_DEPTH24_STENCIL8_EXT; - break; - case DEPTH_COMPONENT16: - internalformat = GL_DEPTH_COMPONENT; - break; - case RGBA4: - case RGB5_A1: - internalformat = GL_RGBA; - break; - case RGB565: - internalformat = GL_RGB; - break; - } - ::glRenderbufferStorageEXT(target, internalformat, width, height); -} - -void GraphicsContext3D::sampleCoverage(double value, bool invert) -{ - ensureContext(m_contextObj); - ::glSampleCoverage(static_cast<float>(value), invert); -} - -void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned long height) -{ - ensureContext(m_contextObj); - ::glScissor(x, y, width, height); -} - -void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string) -{ - ASSERT(shader); - - ensureContext(m_contextObj); - - ShaderSourceEntry entry; - - entry.source = string; - - m_shaderSourceMap.set(shader, entry); -} - -void GraphicsContext3D::stencilFunc(unsigned long func, long ref, unsigned long mask) -{ - ensureContext(m_contextObj); - ::glStencilFunc(func, ref, mask); -} - -void GraphicsContext3D::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask) -{ - ensureContext(m_contextObj); - ::glStencilFuncSeparate(face, func, ref, mask); -} - -void GraphicsContext3D::stencilMask(unsigned long mask) -{ - ensureContext(m_contextObj); - ::glStencilMask(mask); -} - -void GraphicsContext3D::stencilMaskSeparate(unsigned long face, unsigned long mask) -{ - ensureContext(m_contextObj); - ::glStencilMaskSeparate(face, mask); -} - -void GraphicsContext3D::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass) -{ - ensureContext(m_contextObj); - ::glStencilOp(fail, zfail, zpass); -} - -void GraphicsContext3D::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass) -{ - ensureContext(m_contextObj); - ::glStencilOpSeparate(face, fail, zfail, zpass); -} - -void GraphicsContext3D::texParameterf(unsigned target, unsigned pname, float value) -{ - ensureContext(m_contextObj); - ::glTexParameterf(target, pname, static_cast<float>(value)); -} - -void GraphicsContext3D::texParameteri(unsigned target, unsigned pname, int value) -{ - ensureContext(m_contextObj); - ::glTexParameteri(target, pname, static_cast<float>(value)); -} - -void GraphicsContext3D::uniform1f(long location, float v0) -{ - ensureContext(m_contextObj); - ::glUniform1f(location, v0); -} - -void GraphicsContext3D::uniform1fv(long location, float* array, int size) -{ - ensureContext(m_contextObj); - ::glUniform1fv(location, size, array); -} - -void GraphicsContext3D::uniform2f(long location, float v0, float v1) -{ - ensureContext(m_contextObj); - ::glUniform2f(location, v0, v1); -} - -void GraphicsContext3D::uniform2fv(long location, float* array, int size) -{ - // FIXME: length needs to be a multiple of 2 - ensureContext(m_contextObj); - ::glUniform2fv(location, size, array); -} - -void GraphicsContext3D::uniform3f(long location, float v0, float v1, float v2) -{ - ensureContext(m_contextObj); - ::glUniform3f(location, v0, v1, v2); -} - -void GraphicsContext3D::uniform3fv(long location, float* array, int size) -{ - // FIXME: length needs to be a multiple of 3 - ensureContext(m_contextObj); - ::glUniform3fv(location, size, array); -} - -void GraphicsContext3D::uniform4f(long location, float v0, float v1, float v2, float v3) -{ - ensureContext(m_contextObj); - ::glUniform4f(location, v0, v1, v2, v3); -} - -void GraphicsContext3D::uniform4fv(long location, float* array, int size) -{ - // FIXME: length needs to be a multiple of 4 - ensureContext(m_contextObj); - ::glUniform4fv(location, size, array); -} - -void GraphicsContext3D::uniform1i(long location, int v0) -{ - ensureContext(m_contextObj); - ::glUniform1i(location, v0); -} - -void GraphicsContext3D::uniform1iv(long location, int* array, int size) -{ - ensureContext(m_contextObj); - ::glUniform1iv(location, size, array); -} - -void GraphicsContext3D::uniform2i(long location, int v0, int v1) -{ - ensureContext(m_contextObj); - ::glUniform2i(location, v0, v1); -} - -void GraphicsContext3D::uniform2iv(long location, int* array, int size) -{ - // FIXME: length needs to be a multiple of 2 - ensureContext(m_contextObj); - ::glUniform2iv(location, size, array); -} - -void GraphicsContext3D::uniform3i(long location, int v0, int v1, int v2) -{ - ensureContext(m_contextObj); - ::glUniform3i(location, v0, v1, v2); -} - -void GraphicsContext3D::uniform3iv(long location, int* array, int size) -{ - // FIXME: length needs to be a multiple of 3 - ensureContext(m_contextObj); - ::glUniform3iv(location, size, array); -} - -void GraphicsContext3D::uniform4i(long location, int v0, int v1, int v2, int v3) -{ - ensureContext(m_contextObj); - ::glUniform4i(location, v0, v1, v2, v3); -} - -void GraphicsContext3D::uniform4iv(long location, int* array, int size) -{ - // FIXME: length needs to be a multiple of 4 - ensureContext(m_contextObj); - ::glUniform4iv(location, size, array); -} - -void GraphicsContext3D::uniformMatrix2fv(long location, bool transpose, float* array, int size) -{ - // FIXME: length needs to be a multiple of 4 - ensureContext(m_contextObj); - ::glUniformMatrix2fv(location, size, transpose, array); -} - -void GraphicsContext3D::uniformMatrix3fv(long location, bool transpose, float* array, int size) -{ - // FIXME: length needs to be a multiple of 9 - ensureContext(m_contextObj); - ::glUniformMatrix3fv(location, size, transpose, array); -} - -void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* array, int size) -{ - // FIXME: length needs to be a multiple of 16 - ensureContext(m_contextObj); - ::glUniformMatrix4fv(location, size, transpose, array); -} - -void GraphicsContext3D::useProgram(Platform3DObject program) -{ - ensureContext(m_contextObj); - ::glUseProgram((GLuint) program); -} - -void GraphicsContext3D::validateProgram(Platform3DObject program) -{ - ASSERT(program); - ensureContext(m_contextObj); - ::glValidateProgram((GLuint) program); -} - -void GraphicsContext3D::vertexAttrib1f(unsigned long indx, float v0) -{ - ensureContext(m_contextObj); - ::glVertexAttrib1f(indx, v0); -} - -void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* array) -{ - ensureContext(m_contextObj); - ::glVertexAttrib1fv(indx, array); -} - -void GraphicsContext3D::vertexAttrib2f(unsigned long indx, float v0, float v1) -{ - ensureContext(m_contextObj); - ::glVertexAttrib2f(indx, v0, v1); -} - -void GraphicsContext3D::vertexAttrib2fv(unsigned long indx, float* array) -{ - ensureContext(m_contextObj); - ::glVertexAttrib2fv(indx, array); -} - -void GraphicsContext3D::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2) -{ - ensureContext(m_contextObj); - ::glVertexAttrib3f(indx, v0, v1, v2); -} - -void GraphicsContext3D::vertexAttrib3fv(unsigned long indx, float* array) -{ - ensureContext(m_contextObj); - ::glVertexAttrib3fv(indx, array); -} - -void GraphicsContext3D::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3) -{ - ensureContext(m_contextObj); - ::glVertexAttrib4f(indx, v0, v1, v2, v3); -} - -void GraphicsContext3D::vertexAttrib4fv(unsigned long indx, float* array) -{ - ensureContext(m_contextObj); - ::glVertexAttrib4fv(indx, array); -} - -void GraphicsContext3D::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, unsigned long stride, unsigned long offset) -{ - ensureContext(m_contextObj); - ::glVertexAttribPointer(indx, size, type, normalized, stride, reinterpret_cast<void*>(static_cast<intptr_t>(offset))); -} - -void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height) -{ - ensureContext(m_contextObj); - ::glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height)); -} - -void GraphicsContext3D::getBooleanv(unsigned long pname, unsigned char* value) -{ - ensureContext(m_contextObj); - ::glGetBooleanv(pname, value); -} - -void GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long pname, int* value) -{ - ensureContext(m_contextObj); - ::glGetBufferParameteriv(target, pname, value); -} - -void GraphicsContext3D::getFloatv(unsigned long pname, float* value) -{ - ensureContext(m_contextObj); - ::glGetFloatv(pname, value); -} - -void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname, int* value) -{ - ensureContext(m_contextObj); - if (attachment == DEPTH_STENCIL_ATTACHMENT) - attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works. - ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value); -} - -void GraphicsContext3D::getIntegerv(unsigned long pname, int* value) -{ - // Need to emulate IMPLEMENTATION_COLOR_READ_FORMAT/TYPE for GL. Any valid - // combination should work, but GL_RGB/GL_UNSIGNED_BYTE might be the most - // useful for desktop WebGL users. - // Need to emulate MAX_FRAGMENT/VERTEX_UNIFORM_VECTORS and MAX_VARYING_VECTORS - // because desktop GL's corresponding queries return the number of components - // whereas GLES2 return the number of vectors (each vector has 4 components). - // Therefore, the value returned by desktop GL needs to be divided by 4. - ensureContext(m_contextObj); - switch (pname) { - case IMPLEMENTATION_COLOR_READ_FORMAT: - *value = GL_RGB; - break; - case IMPLEMENTATION_COLOR_READ_TYPE: - *value = GL_UNSIGNED_BYTE; - break; - case MAX_FRAGMENT_UNIFORM_VECTORS: - ::glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, value); - *value /= 4; - break; - case MAX_VERTEX_UNIFORM_VECTORS: - ::glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, value); - *value /= 4; - break; - case MAX_VARYING_VECTORS: - ::glGetIntegerv(GL_MAX_VARYING_FLOATS, value); - *value /= 4; - break; - default: - ::glGetIntegerv(pname, value); - } -} - -void GraphicsContext3D::getProgramiv(Platform3DObject program, unsigned long pname, int* value) -{ - ensureContext(m_contextObj); - ::glGetProgramiv((GLuint) program, pname, value); -} - -String GraphicsContext3D::getProgramInfoLog(Platform3DObject program) -{ - ASSERT(program); - - ensureContext(m_contextObj); - GLint length; - ::glGetProgramiv((GLuint) program, GL_INFO_LOG_LENGTH, &length); - - GLsizei size; - GLchar* info = (GLchar*) fastMalloc(length); - if (!info) - return ""; - - ::glGetProgramInfoLog((GLuint) program, length, &size, info); - String s(info); - fastFree(info); - return s; -} - -void GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, unsigned long pname, int* value) -{ - ensureContext(m_contextObj); - ::glGetRenderbufferParameterivEXT(target, pname, value); -} - -void GraphicsContext3D::getShaderiv(Platform3DObject shader, unsigned long pname, int* value) -{ - ASSERT(shader); - - ensureContext(m_contextObj); - - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); - - switch (pname) { - case DELETE_STATUS: - case SHADER_TYPE: - // Let OpenGL handle these. - - ::glGetShaderiv((GLuint) shader, pname, value); - break; - - case COMPILE_STATUS: - if (result == m_shaderSourceMap.end()) { - (*value) = static_cast<int>(false); - return; - } - - (*value) = static_cast<int>(result->second.isValid); - break; - - case INFO_LOG_LENGTH: - if (result == m_shaderSourceMap.end()) { - (*value) = 0; - return; - } - - (*value) = getShaderInfoLog(shader).length(); - break; - - case SHADER_SOURCE_LENGTH: - (*value) = getShaderSource(shader).length(); - break; - - default: - synthesizeGLError(INVALID_ENUM); - } -} - -String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader) -{ - ASSERT(shader); - - ensureContext(m_contextObj); - GLint length; - ::glGetShaderiv((GLuint) shader, GL_INFO_LOG_LENGTH, &length); - - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); - - if (result == m_shaderSourceMap.end()) - return ""; - - ShaderSourceEntry entry = result->second; - - if (entry.isValid) { - GLint length; - ::glGetShaderiv((GLuint) shader, GL_INFO_LOG_LENGTH, &length); - - GLsizei size; - GLchar* info = (GLchar*) fastMalloc(length); - if (!info) - return ""; - - ::glGetShaderInfoLog((GLuint) shader, length, &size, info); - - String s(info); - fastFree(info); - return s; - } - else { - return entry.log; - } -} - -String GraphicsContext3D::getShaderSource(Platform3DObject shader) -{ - ASSERT(shader); - - ensureContext(m_contextObj); - - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); - - if (result == m_shaderSourceMap.end()) - return ""; - - return result->second.source; -} - - -void GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long pname, float* value) -{ - ensureContext(m_contextObj); - ::glGetTexParameterfv(target, pname, value); -} - -void GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long pname, int* value) -{ - ensureContext(m_contextObj); - ::glGetTexParameteriv(target, pname, value); -} - -void GraphicsContext3D::getUniformfv(Platform3DObject program, long location, float* value) -{ - ensureContext(m_contextObj); - ::glGetUniformfv((GLuint) program, location, value); -} - -void GraphicsContext3D::getUniformiv(Platform3DObject program, long location, int* value) -{ - ensureContext(m_contextObj); - ::glGetUniformiv((GLuint) program, location, value); -} - -long GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name) -{ - ASSERT(program); - - ensureContext(m_contextObj); - return ::glGetUniformLocation((GLuint) program, name.utf8().data()); -} - -void GraphicsContext3D::getVertexAttribfv(unsigned long index, unsigned long pname, float* value) -{ - ensureContext(m_contextObj); - ::glGetVertexAttribfv(index, pname, value); -} - -void GraphicsContext3D::getVertexAttribiv(unsigned long index, unsigned long pname, int* value) -{ - ensureContext(m_contextObj); - ::glGetVertexAttribiv(index, pname, value); -} - -long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long pname) -{ - ensureContext(m_contextObj); - - void* pointer; - ::glGetVertexAttribPointerv(index, pname, &pointer); - return reinterpret_cast<long>(pointer); -} - -int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels) -{ - ensureContext(m_contextObj); - - ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); - return 0; -} - -int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels) -{ - ensureContext(m_contextObj); - - // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size - ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); - return 0; -} - -unsigned GraphicsContext3D::createBuffer() -{ - ensureContext(m_contextObj); - GLuint o; - glGenBuffers(1, &o); - return o; -} - -unsigned GraphicsContext3D::createFramebuffer() -{ - ensureContext(m_contextObj); - GLuint o; - glGenFramebuffersEXT(1, &o); - return o; -} - -unsigned GraphicsContext3D::createProgram() -{ - ensureContext(m_contextObj); - return glCreateProgram(); -} - -unsigned GraphicsContext3D::createRenderbuffer() -{ - ensureContext(m_contextObj); - GLuint o; - glGenRenderbuffersEXT(1, &o); - return o; -} - -unsigned GraphicsContext3D::createShader(unsigned long type) -{ - ensureContext(m_contextObj); - return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER); -} - -unsigned GraphicsContext3D::createTexture() -{ - ensureContext(m_contextObj); - GLuint o; - glGenTextures(1, &o); - return o; -} - -void GraphicsContext3D::deleteBuffer(unsigned buffer) -{ - ensureContext(m_contextObj); - glDeleteBuffers(1, &buffer); -} - -void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer) -{ - ensureContext(m_contextObj); - glDeleteFramebuffersEXT(1, &framebuffer); -} - -void GraphicsContext3D::deleteProgram(unsigned program) -{ - ensureContext(m_contextObj); - glDeleteProgram(program); -} - -void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer) -{ - ensureContext(m_contextObj); - glDeleteRenderbuffersEXT(1, &renderbuffer); -} - -void GraphicsContext3D::deleteShader(unsigned shader) -{ - ensureContext(m_contextObj); - glDeleteShader(shader); -} - -void GraphicsContext3D::deleteTexture(unsigned texture) -{ - ensureContext(m_contextObj); - glDeleteTextures(1, &texture); -} - -int GraphicsContext3D::sizeInBytes(int type) -{ - switch (type) { - case GL_BYTE: - return sizeof(GLbyte); - case GL_UNSIGNED_BYTE: - return sizeof(GLubyte); - case GL_SHORT: - return sizeof(GLshort); - case GL_UNSIGNED_SHORT: - return sizeof(GLushort); - case GL_INT: - return sizeof(GLint); - case GL_UNSIGNED_INT: - return sizeof(GLuint); - case GL_FLOAT: - return sizeof(GLfloat); - default: - return 0; - } -} - -void GraphicsContext3D::synthesizeGLError(unsigned long error) -{ - m_syntheticErrors.add(error); -} } diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h index a9f747a..6ff3ff0 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h @@ -112,8 +112,6 @@ public: virtual void setDebugBackgroundColor(const Color&); virtual void setDebugBorder(const Color&, float borderWidth); - virtual void setGeometryOrientation(CompositingCoordinatesOrientation); - virtual void didDisplay(PlatformLayer*); void recursiveCommitChanges(); @@ -259,7 +257,6 @@ private: void updateContentsMediaLayer(); void updateContentsCanvasLayer(); void updateContentsRect(); - void updateGeometryOrientation(); void updateMaskLayer(); void updateReplicatedLayers(); @@ -304,10 +301,9 @@ private: ContentsMediaLayerChanged = 1 << 18, ContentsCanvasLayerChanged = 1 << 19, ContentsRectChanged = 1 << 20, - GeometryOrientationChanged = 1 << 21, - MaskLayerChanged = 1 << 22, - ReplicatedLayerChanged = 1 << 23, - ContentsNeedsDisplay = 1 << 24 + MaskLayerChanged = 1 << 21, + ReplicatedLayerChanged = 1 << 22, + ContentsNeedsDisplay = 1 << 23 }; typedef unsigned LayerChangeFlags; void noteLayerPropertyChanged(LayerChangeFlags flags); diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm index 5fedaff..395a691 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm @@ -263,15 +263,6 @@ static String animationIdentifier(AnimatedPropertyID property, const String& key return builder.toString(); } -#if !HAVE_MODERN_QUARTZCORE -static TransformationMatrix flipTransform() -{ - TransformationMatrix flipper; - flipper.flipY(); - return flipper; -} -#endif - static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction* timingFunction) { // By this point, timing functions can only be linear or cubic, not steps. @@ -332,11 +323,6 @@ static bool forceSoftwareAnimation() return forceSoftwareAnimation; } -GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation() -{ - return CompositingCoordinatesBottomUp; -} - static NSDictionary* nullActionsDictionary() { NSNull* nullValue = [NSNull null]; @@ -831,28 +817,6 @@ void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer) noteLayerPropertyChanged(ContentsMediaLayerChanged); } -void GraphicsLayerCA::setGeometryOrientation(CompositingCoordinatesOrientation orientation) -{ - if (orientation == m_geometryOrientation) - return; - - GraphicsLayer::setGeometryOrientation(orientation); - noteLayerPropertyChanged(GeometryOrientationChanged); - -#if !HAVE_MODERN_QUARTZCORE - // Geometry orientation is mapped onto children transform in older QuartzCores. - switch (m_geometryOrientation) { - case CompositingCoordinatesTopDown: - setChildrenTransform(TransformationMatrix()); - break; - - case CompositingCoordinatesBottomUp: - setChildrenTransform(flipTransform()); - break; - } -#endif -} - void GraphicsLayerCA::didDisplay(PlatformLayer* layer) { CALayer* sourceLayer; @@ -984,9 +948,6 @@ void GraphicsLayerCA::commitLayerChangesBeforeSublayers() if (m_uncommittedChanges & ContentsRectChanged) updateContentsRect(); - if (m_uncommittedChanges & GeometryOrientationChanged) - updateGeometryOrientation(); - if (m_uncommittedChanges & MaskLayerChanged) updateMaskLayer(); @@ -1461,23 +1422,6 @@ void GraphicsLayerCA::updateContentsRect() } } -void GraphicsLayerCA::updateGeometryOrientation() -{ -#if HAVE_MODERN_QUARTZCORE - switch (geometryOrientation()) { - case CompositingCoordinatesTopDown: - [m_layer.get() setGeometryFlipped:NO]; - break; - - case CompositingCoordinatesBottomUp: - [m_layer.get() setGeometryFlipped:YES]; - break; - } - // Geometry orientation is mapped onto children transform in older QuartzCores, - // so is handled via setGeometryOrientation(). -#endif -} - void GraphicsLayerCA::updateMaskLayer() { CALayer *maskCALayer = m_maskLayer ? m_maskLayer->platformLayer() : 0; @@ -2226,11 +2170,7 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer) [tiledLayer setTileSize:tileSize]; [tiledLayer setLevelsOfDetail:1]; [tiledLayer setLevelsOfDetailBias:0]; - - if (GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp) - [tiledLayer setContentsGravity:@"bottomLeft"]; - else - [tiledLayer setContentsGravity:@"topLeft"]; + [tiledLayer setContentsGravity:@"bottomLeft"]; #if !HAVE_MODERN_QUARTZCORE // Tiled layer has issues with flipped coordinates. diff --git a/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp new file mode 100644 index 0000000..53d9b86 --- /dev/null +++ b/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp @@ -0,0 +1,1454 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "GraphicsContext3D.h" + +#include "ArrayBuffer.h" +#include "ArrayBufferView.h" +#include "WebGLObject.h" +#include "CanvasRenderingContext.h" +#include "Float32Array.h" +#include "GraphicsContext.h" +#include "HTMLCanvasElement.h" +#include "ImageBuffer.h" +#include "Int32Array.h" +#include "NotImplemented.h" +#include "Uint8Array.h" + +#if PLATFORM(MAC) +#include <OpenGL/gl.h> +#endif + +#include <wtf/UnusedParam.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +void GraphicsContext3D::validateAttributes() +{ + const char* extensions = reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS)); + if (m_attrs.stencil) { + if (std::strstr(extensions, "GL_EXT_packed_depth_stencil")) { + if (!m_attrs.depth) + m_attrs.depth = true; + } else + m_attrs.stencil = false; + } + if (m_attrs.antialias) { + bool isValidVendor = true; + // Currently in Mac we only turn on antialias if vendor is NVIDIA. + const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); + if (!std::strstr(vendor, "NVIDIA")) + isValidVendor = false; + if (!isValidVendor || !std::strstr(extensions, "GL_EXT_framebuffer_multisample")) + m_attrs.antialias = false; + } + // FIXME: instead of enforcing premultipliedAlpha = true, implement the + // correct behavior when premultipliedAlpha = false is requested. + m_attrs.premultipliedAlpha = true; +} + +void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context) +{ + HTMLCanvasElement* canvas = context->canvas(); + ImageBuffer* imageBuffer = canvas->buffer(); + + int rowBytes = m_currentWidth * 4; + int totalBytes = rowBytes * m_currentHeight; + + OwnArrayPtr<unsigned char> pixels(new unsigned char[totalBytes]); + if (!pixels) + return; + + makeContextCurrent(); + + bool mustRestoreFBO = false; + if (m_attrs.antialias) { + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + mustRestoreFBO = true; + } else { + if (m_boundFBO != m_fbo) { + mustRestoreFBO = true; + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } + } + + GLint packAlignment = 4; + bool mustRestorePackAlignment = false; + ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); + if (packAlignment > 4) { + ::glPixelStorei(GL_PACK_ALIGNMENT, 4); + mustRestorePackAlignment = true; + } + + ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels.get()); + + if (mustRestorePackAlignment) + ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); + + if (mustRestoreFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); + + paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, + canvas->width(), canvas->height(), imageBuffer->context()->platformContext()); +} + +void GraphicsContext3D::reshape(int width, int height) +{ + if (width == m_currentWidth && height == m_currentHeight || !m_contextObj) + return; + + m_currentWidth = width; + m_currentHeight = height; + + makeContextCurrent(); + + GLuint internalColorFormat, colorFormat, internalDepthStencilFormat = 0; + if (m_attrs.alpha) { + internalColorFormat = GL_RGBA8; + colorFormat = GL_RGBA; + } else { + internalColorFormat = GL_RGB8; + colorFormat = GL_RGB; + } + if (m_attrs.stencil || m_attrs.depth) { + // We don't allow the logic where stencil is required and depth is not. + // See GraphicsContext3D constructor. + if (m_attrs.stencil && m_attrs.depth) + internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT; + else + internalDepthStencilFormat = GL_DEPTH_COMPONENT; + } + + bool mustRestoreFBO = false; + + // resize multisample FBO + if (m_attrs.antialias) { + GLint maxSampleCount; + ::glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSampleCount); + GLint sampleCount = std::min(8, maxSampleCount); + if (sampleCount > maxSampleCount) + sampleCount = maxSampleCount; + if (m_boundFBO != m_multisampleFBO) { + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + mustRestoreFBO = true; + } + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); + ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalColorFormat, width, height); + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); + if (m_attrs.stencil || m_attrs.depth) { + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); + ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalDepthStencilFormat, width, height); + if (m_attrs.stencil) + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); + if (m_attrs.depth) + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); + } + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { + // FIXME: cleanup. + notImplemented(); + } + } + + // resize regular FBO + if (m_boundFBO != m_fbo) { + mustRestoreFBO = true; + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } + ::glBindTexture(GL_TEXTURE_2D, m_texture); + ::glTexImage2D(GL_TEXTURE_2D, 0, internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); + ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); + ::glBindTexture(GL_TEXTURE_2D, 0); + if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) { + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer); + ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthStencilFormat, width, height); + if (m_attrs.stencil) + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); + if (m_attrs.depth) + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + } + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { + // FIXME: cleanup + notImplemented(); + } + + if (m_attrs.antialias) { + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + if (m_boundFBO == m_multisampleFBO) + mustRestoreFBO = false; + } + + // Initialize renderbuffers to 0. + GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMask = GL_TRUE, stencilMask = GL_TRUE; + GLboolean isScissorEnabled = GL_FALSE; + GLboolean isDitherEnabled = GL_FALSE; + GLbitfield clearMask = GL_COLOR_BUFFER_BIT; + ::glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); + ::glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + if (m_attrs.depth) { + ::glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); + ::glDepthMask(GL_TRUE); + clearMask |= GL_DEPTH_BUFFER_BIT; + } + if (m_attrs.stencil) { + ::glGetBooleanv(GL_STENCIL_WRITEMASK, &stencilMask); + ::glStencilMask(GL_TRUE); + clearMask |= GL_STENCIL_BUFFER_BIT; + } + isScissorEnabled = ::glIsEnabled(GL_SCISSOR_TEST); + ::glDisable(GL_SCISSOR_TEST); + isDitherEnabled = ::glIsEnabled(GL_DITHER); + ::glDisable(GL_DITHER); + + ::glClear(clearMask); + + ::glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); + if (m_attrs.depth) + ::glDepthMask(depthMask); + if (m_attrs.stencil) + ::glStencilMask(stencilMask); + if (isScissorEnabled) + ::glEnable(GL_SCISSOR_TEST); + else + ::glDisable(GL_SCISSOR_TEST); + if (isDitherEnabled) + ::glEnable(GL_DITHER); + else + ::glDisable(GL_DITHER); + + if (mustRestoreFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); + + ::glFlush(); +} + +void GraphicsContext3D::prepareTexture() +{ + makeContextCurrent(); + if (m_attrs.antialias) { + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); + } + ::glFinish(); +} + +void GraphicsContext3D::activeTexture(unsigned long texture) +{ + makeContextCurrent(); + ::glActiveTexture(texture); +} + +void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader) +{ + ASSERT(program); + ASSERT(shader); + makeContextCurrent(); + ::glAttachShader((GLuint) program, (GLuint) shader); +} + +void GraphicsContext3D::bindAttribLocation(Platform3DObject program, unsigned long index, const String& name) +{ + ASSERT(program); + makeContextCurrent(); + ::glBindAttribLocation((GLuint) program, index, name.utf8().data()); +} + +void GraphicsContext3D::bindBuffer(unsigned long target, Platform3DObject buffer) +{ + makeContextCurrent(); + ::glBindBuffer(target, (GLuint) buffer); +} + + +void GraphicsContext3D::bindFramebuffer(unsigned long target, Platform3DObject buffer) +{ + makeContextCurrent(); + GLuint fbo; + if (buffer) + fbo = (GLuint)buffer; + else + fbo = (m_attrs.antialias ? m_multisampleFBO : m_fbo); + if (fbo != m_boundFBO) { + ::glBindFramebufferEXT(target, fbo); + m_boundFBO = fbo; + } +} + +void GraphicsContext3D::bindRenderbuffer(unsigned long target, Platform3DObject renderbuffer) +{ + makeContextCurrent(); + ::glBindRenderbufferEXT(target, (GLuint) renderbuffer); +} + + +void GraphicsContext3D::bindTexture(unsigned long target, Platform3DObject texture) +{ + makeContextCurrent(); + ::glBindTexture(target, (GLuint) texture); +} + +void GraphicsContext3D::blendColor(double red, double green, double blue, double alpha) +{ + makeContextCurrent(); + ::glBlendColor(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha)); +} + +void GraphicsContext3D::blendEquation( unsigned long mode ) +{ + makeContextCurrent(); + ::glBlendEquation(mode); +} + +void GraphicsContext3D::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha) +{ + makeContextCurrent(); + ::glBlendEquationSeparate(modeRGB, modeAlpha); +} + + +void GraphicsContext3D::blendFunc(unsigned long sfactor, unsigned long dfactor) +{ + makeContextCurrent(); + ::glBlendFunc(sfactor, dfactor); +} + +void GraphicsContext3D::blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha) +{ + makeContextCurrent(); + ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +} + +void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long usage) +{ + makeContextCurrent(); + ::glBufferData(target, size, 0, usage); +} + +void GraphicsContext3D::bufferData(unsigned long target, int size, const void* data, unsigned long usage) +{ + makeContextCurrent(); + ::glBufferData(target, size, data, usage); +} + +void GraphicsContext3D::bufferSubData(unsigned long target, long offset, int size, const void* data) +{ + makeContextCurrent(); + ::glBufferSubData(target, offset, size, data); +} + +unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target) +{ + makeContextCurrent(); + return ::glCheckFramebufferStatusEXT(target); +} + +void GraphicsContext3D::clearColor(double r, double g, double b, double a) +{ + makeContextCurrent(); + ::glClearColor(static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a)); +} + +void GraphicsContext3D::clear(unsigned long mask) +{ + makeContextCurrent(); + ::glClear(mask); +} + +void GraphicsContext3D::clearDepth(double depth) +{ + makeContextCurrent(); + ::glClearDepth(depth); +} + +void GraphicsContext3D::clearStencil(long s) +{ + makeContextCurrent(); + ::glClearStencil(s); +} + +void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha) +{ + makeContextCurrent(); + ::glColorMask(red, green, blue, alpha); +} + +void GraphicsContext3D::compileShader(Platform3DObject shader) +{ + ASSERT(shader); + makeContextCurrent(); + + int GLshaderType; + ANGLEShaderType shaderType; + + glGetShaderiv(shader, SHADER_TYPE, &GLshaderType); + + if (GLshaderType == VERTEX_SHADER) + shaderType = SHADER_TYPE_VERTEX; + else if (GLshaderType == FRAGMENT_SHADER) + shaderType = SHADER_TYPE_FRAGMENT; + else + return; // Invalid shader type. + + HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + + if (result == m_shaderSourceMap.end()) + return; + + ShaderSourceEntry& entry = result->second; + + String translatedShaderSource; + String shaderInfoLog; + + bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog); + + entry.log = shaderInfoLog; + entry.isValid = isValid; + + if (!isValid) + return; // Shader didn't validate, don't move forward with compiling translated source + + int translatedShaderLength = translatedShaderSource.length(); + + const CString& translatedShaderCString = translatedShaderSource.utf8(); + const char* translatedShaderPtr = translatedShaderCString.data(); + + ::glShaderSource((GLuint) shader, 1, &translatedShaderPtr, &translatedShaderLength); + + ::glCompileShader((GLuint) shader); + + int GLCompileSuccess; + + ::glGetShaderiv((GLuint) shader, COMPILE_STATUS, &GLCompileSuccess); + + // ASSERT that ANGLE generated GLSL will be accepted by OpenGL + ASSERT(GLCompileSuccess == GL_TRUE); +} + +void GraphicsContext3D::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border) +{ + makeContextCurrent(); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } + ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); +} + +void GraphicsContext3D::copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height) +{ + makeContextCurrent(); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } + ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); +} + +void GraphicsContext3D::cullFace(unsigned long mode) +{ + makeContextCurrent(); + ::glCullFace(mode); +} + +void GraphicsContext3D::depthFunc(unsigned long func) +{ + makeContextCurrent(); + ::glDepthFunc(func); +} + +void GraphicsContext3D::depthMask(bool flag) +{ + makeContextCurrent(); + ::glDepthMask(flag); +} + +void GraphicsContext3D::depthRange(double zNear, double zFar) +{ + makeContextCurrent(); + ::glDepthRange(zNear, zFar); +} + +void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader) +{ + ASSERT(program); + ASSERT(shader); + makeContextCurrent(); + ::glDetachShader((GLuint) program, (GLuint) shader); +} + +void GraphicsContext3D::disable(unsigned long cap) +{ + makeContextCurrent(); + ::glDisable(cap); +} + +void GraphicsContext3D::disableVertexAttribArray(unsigned long index) +{ + makeContextCurrent(); + ::glDisableVertexAttribArray(index); +} + +void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count) +{ + makeContextCurrent(); + ::glDrawArrays(mode, first, count); +} + +void GraphicsContext3D::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset) +{ + makeContextCurrent(); + ::glDrawElements(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset))); +} + +void GraphicsContext3D::enable(unsigned long cap) +{ + makeContextCurrent(); + ::glEnable(cap); +} + +void GraphicsContext3D::enableVertexAttribArray(unsigned long index) +{ + makeContextCurrent(); + ::glEnableVertexAttribArray(index); +} + +void GraphicsContext3D::finish() +{ + makeContextCurrent(); + ::glFinish(); +} + +void GraphicsContext3D::flush() +{ + makeContextCurrent(); + ::glFlush(); +} + +void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, Platform3DObject buffer) +{ + makeContextCurrent(); + GLuint renderbuffer = (GLuint) buffer; + if (attachment == DEPTH_STENCIL_ATTACHMENT) { + ::glFramebufferRenderbufferEXT(target, DEPTH_ATTACHMENT, renderbuffertarget, renderbuffer); + ::glFramebufferRenderbufferEXT(target, STENCIL_ATTACHMENT, renderbuffertarget, renderbuffer); + } else + ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer); +} + +void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, Platform3DObject texture, long level) +{ + makeContextCurrent(); + ::glFramebufferTexture2DEXT(target, attachment, textarget, (GLuint) texture, level); +} + +void GraphicsContext3D::frontFace(unsigned long mode) +{ + makeContextCurrent(); + ::glFrontFace(mode); +} + +void GraphicsContext3D::generateMipmap(unsigned long target) +{ + makeContextCurrent(); + ::glGenerateMipmapEXT(target); +} + +bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, unsigned long index, ActiveInfo& info) +{ + if (!program) { + synthesizeGLError(INVALID_VALUE); + return false; + } + makeContextCurrent(); + GLint maxAttributeSize = 0; + ::glGetProgramiv(static_cast<GLuint>(program), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize); + GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination + GLsizei nameLength = 0; + GLint size = 0; + GLenum type = 0; + ::glGetActiveAttrib(static_cast<GLuint>(program), index, maxAttributeSize, &nameLength, &size, &type, name); + if (!nameLength) + return false; + info.name = String(name, nameLength); + info.type = type; + info.size = size; + return true; +} + +bool GraphicsContext3D::getActiveUniform(Platform3DObject program, unsigned long index, ActiveInfo& info) +{ + if (!program) { + synthesizeGLError(INVALID_VALUE); + return false; + } + makeContextCurrent(); + GLint maxUniformSize = 0; + ::glGetProgramiv(static_cast<GLuint>(program), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize); + GLchar name[maxUniformSize]; // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination + GLsizei nameLength = 0; + GLint size = 0; + GLenum type = 0; + ::glGetActiveUniform(static_cast<GLuint>(program), index, maxUniformSize, &nameLength, &size, &type, name); + if (!nameLength) + return false; + info.name = String(name, nameLength); + info.type = type; + info.size = size; + return true; +} + +void GraphicsContext3D::getAttachedShaders(Platform3DObject program, int maxCount, int* count, unsigned int* shaders) +{ + if (!program) { + synthesizeGLError(INVALID_VALUE); + return; + } + makeContextCurrent(); + ::glGetAttachedShaders(static_cast<GLuint>(program), maxCount, count, shaders); +} + +int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name) +{ + if (!program) + return -1; + + makeContextCurrent(); + return ::glGetAttribLocation((GLuint) program, name.utf8().data()); +} + +GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() +{ + return m_attrs; +} + +unsigned long GraphicsContext3D::getError() +{ + if (m_syntheticErrors.size() > 0) { + ListHashSet<unsigned long>::iterator iter = m_syntheticErrors.begin(); + unsigned long err = *iter; + m_syntheticErrors.remove(iter); + return err; + } + + makeContextCurrent(); + return ::glGetError(); +} + +String GraphicsContext3D::getString(unsigned long name) +{ + makeContextCurrent(); + return String((const char*) ::glGetString(name)); +} + +void GraphicsContext3D::hint(unsigned long target, unsigned long mode) +{ + makeContextCurrent(); + ::glHint(target, mode); +} + +bool GraphicsContext3D::isBuffer(Platform3DObject buffer) +{ + if (!buffer) + return false; + + makeContextCurrent(); + return ::glIsBuffer((GLuint) buffer); +} + +bool GraphicsContext3D::isEnabled(unsigned long cap) +{ + makeContextCurrent(); + return ::glIsEnabled(cap); +} + +bool GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer) +{ + if (!framebuffer) + return false; + + makeContextCurrent(); + return ::glIsFramebufferEXT((GLuint) framebuffer); +} + +bool GraphicsContext3D::isProgram(Platform3DObject program) +{ + if (!program) + return false; + + makeContextCurrent(); + return ::glIsProgram((GLuint) program); +} + +bool GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer) +{ + if (!renderbuffer) + return false; + + makeContextCurrent(); + return ::glIsRenderbufferEXT((GLuint) renderbuffer); +} + +bool GraphicsContext3D::isShader(Platform3DObject shader) +{ + if (!shader) + return false; + + makeContextCurrent(); + return ::glIsShader((GLuint) shader); +} + +bool GraphicsContext3D::isTexture(Platform3DObject texture) +{ + if (!texture) + return false; + + makeContextCurrent(); + return ::glIsTexture((GLuint) texture); +} + +void GraphicsContext3D::lineWidth(double width) +{ + makeContextCurrent(); + ::glLineWidth(static_cast<float>(width)); +} + +void GraphicsContext3D::linkProgram(Platform3DObject program) +{ + ASSERT(program); + makeContextCurrent(); + ::glLinkProgram((GLuint) program); +} + +void GraphicsContext3D::pixelStorei(unsigned long pname, long param) +{ + makeContextCurrent(); + ::glPixelStorei(pname, param); +} + +void GraphicsContext3D::polygonOffset(double factor, double units) +{ + makeContextCurrent(); + ::glPolygonOffset(static_cast<float>(factor), static_cast<float>(units)); +} + +void GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* data) +{ + // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., + // all previous rendering calls should be done before reading pixels. + makeContextCurrent(); + ::glFlush(); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + ::glFlush(); + } + ::glReadPixels(x, y, width, height, format, type, data); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); +} + +void GraphicsContext3D::releaseShaderCompiler() +{ + // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants + makeContextCurrent(); + //::glReleaseShaderCompiler(); +} + +void GraphicsContext3D::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height) +{ + makeContextCurrent(); + switch (internalformat) { + case DEPTH_STENCIL: + internalformat = GL_DEPTH24_STENCIL8_EXT; + break; + case DEPTH_COMPONENT16: + internalformat = GL_DEPTH_COMPONENT; + break; + case RGBA4: + case RGB5_A1: + internalformat = GL_RGBA; + break; + case RGB565: + internalformat = GL_RGB; + break; + } + ::glRenderbufferStorageEXT(target, internalformat, width, height); +} + +void GraphicsContext3D::sampleCoverage(double value, bool invert) +{ + makeContextCurrent(); + ::glSampleCoverage(static_cast<float>(value), invert); +} + +void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned long height) +{ + makeContextCurrent(); + ::glScissor(x, y, width, height); +} + +void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string) +{ + ASSERT(shader); + + makeContextCurrent(); + + ShaderSourceEntry entry; + + entry.source = string; + + m_shaderSourceMap.set(shader, entry); +} + +void GraphicsContext3D::stencilFunc(unsigned long func, long ref, unsigned long mask) +{ + makeContextCurrent(); + ::glStencilFunc(func, ref, mask); +} + +void GraphicsContext3D::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask) +{ + makeContextCurrent(); + ::glStencilFuncSeparate(face, func, ref, mask); +} + +void GraphicsContext3D::stencilMask(unsigned long mask) +{ + makeContextCurrent(); + ::glStencilMask(mask); +} + +void GraphicsContext3D::stencilMaskSeparate(unsigned long face, unsigned long mask) +{ + makeContextCurrent(); + ::glStencilMaskSeparate(face, mask); +} + +void GraphicsContext3D::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass) +{ + makeContextCurrent(); + ::glStencilOp(fail, zfail, zpass); +} + +void GraphicsContext3D::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass) +{ + makeContextCurrent(); + ::glStencilOpSeparate(face, fail, zfail, zpass); +} + +void GraphicsContext3D::texParameterf(unsigned target, unsigned pname, float value) +{ + makeContextCurrent(); + ::glTexParameterf(target, pname, static_cast<float>(value)); +} + +void GraphicsContext3D::texParameteri(unsigned target, unsigned pname, int value) +{ + makeContextCurrent(); + ::glTexParameteri(target, pname, static_cast<float>(value)); +} + +void GraphicsContext3D::uniform1f(long location, float v0) +{ + makeContextCurrent(); + ::glUniform1f(location, v0); +} + +void GraphicsContext3D::uniform1fv(long location, float* array, int size) +{ + makeContextCurrent(); + ::glUniform1fv(location, size, array); +} + +void GraphicsContext3D::uniform2f(long location, float v0, float v1) +{ + makeContextCurrent(); + ::glUniform2f(location, v0, v1); +} + +void GraphicsContext3D::uniform2fv(long location, float* array, int size) +{ + // FIXME: length needs to be a multiple of 2 + makeContextCurrent(); + ::glUniform2fv(location, size, array); +} + +void GraphicsContext3D::uniform3f(long location, float v0, float v1, float v2) +{ + makeContextCurrent(); + ::glUniform3f(location, v0, v1, v2); +} + +void GraphicsContext3D::uniform3fv(long location, float* array, int size) +{ + // FIXME: length needs to be a multiple of 3 + makeContextCurrent(); + ::glUniform3fv(location, size, array); +} + +void GraphicsContext3D::uniform4f(long location, float v0, float v1, float v2, float v3) +{ + makeContextCurrent(); + ::glUniform4f(location, v0, v1, v2, v3); +} + +void GraphicsContext3D::uniform4fv(long location, float* array, int size) +{ + // FIXME: length needs to be a multiple of 4 + makeContextCurrent(); + ::glUniform4fv(location, size, array); +} + +void GraphicsContext3D::uniform1i(long location, int v0) +{ + makeContextCurrent(); + ::glUniform1i(location, v0); +} + +void GraphicsContext3D::uniform1iv(long location, int* array, int size) +{ + makeContextCurrent(); + ::glUniform1iv(location, size, array); +} + +void GraphicsContext3D::uniform2i(long location, int v0, int v1) +{ + makeContextCurrent(); + ::glUniform2i(location, v0, v1); +} + +void GraphicsContext3D::uniform2iv(long location, int* array, int size) +{ + // FIXME: length needs to be a multiple of 2 + makeContextCurrent(); + ::glUniform2iv(location, size, array); +} + +void GraphicsContext3D::uniform3i(long location, int v0, int v1, int v2) +{ + makeContextCurrent(); + ::glUniform3i(location, v0, v1, v2); +} + +void GraphicsContext3D::uniform3iv(long location, int* array, int size) +{ + // FIXME: length needs to be a multiple of 3 + makeContextCurrent(); + ::glUniform3iv(location, size, array); +} + +void GraphicsContext3D::uniform4i(long location, int v0, int v1, int v2, int v3) +{ + makeContextCurrent(); + ::glUniform4i(location, v0, v1, v2, v3); +} + +void GraphicsContext3D::uniform4iv(long location, int* array, int size) +{ + // FIXME: length needs to be a multiple of 4 + makeContextCurrent(); + ::glUniform4iv(location, size, array); +} + +void GraphicsContext3D::uniformMatrix2fv(long location, bool transpose, float* array, int size) +{ + // FIXME: length needs to be a multiple of 4 + makeContextCurrent(); + ::glUniformMatrix2fv(location, size, transpose, array); +} + +void GraphicsContext3D::uniformMatrix3fv(long location, bool transpose, float* array, int size) +{ + // FIXME: length needs to be a multiple of 9 + makeContextCurrent(); + ::glUniformMatrix3fv(location, size, transpose, array); +} + +void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* array, int size) +{ + // FIXME: length needs to be a multiple of 16 + makeContextCurrent(); + ::glUniformMatrix4fv(location, size, transpose, array); +} + +void GraphicsContext3D::useProgram(Platform3DObject program) +{ + makeContextCurrent(); + ::glUseProgram((GLuint) program); +} + +void GraphicsContext3D::validateProgram(Platform3DObject program) +{ + ASSERT(program); + + makeContextCurrent(); + ::glValidateProgram((GLuint) program); +} + +void GraphicsContext3D::vertexAttrib1f(unsigned long indx, float v0) +{ + makeContextCurrent(); + ::glVertexAttrib1f(indx, v0); +} + +void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* array) +{ + makeContextCurrent(); + ::glVertexAttrib1fv(indx, array); +} + +void GraphicsContext3D::vertexAttrib2f(unsigned long indx, float v0, float v1) +{ + makeContextCurrent(); + ::glVertexAttrib2f(indx, v0, v1); +} + +void GraphicsContext3D::vertexAttrib2fv(unsigned long indx, float* array) +{ + makeContextCurrent(); + ::glVertexAttrib2fv(indx, array); +} + +void GraphicsContext3D::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2) +{ + makeContextCurrent(); + ::glVertexAttrib3f(indx, v0, v1, v2); +} + +void GraphicsContext3D::vertexAttrib3fv(unsigned long indx, float* array) +{ + makeContextCurrent(); + ::glVertexAttrib3fv(indx, array); +} + +void GraphicsContext3D::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3) +{ + makeContextCurrent(); + ::glVertexAttrib4f(indx, v0, v1, v2, v3); +} + +void GraphicsContext3D::vertexAttrib4fv(unsigned long indx, float* array) +{ + makeContextCurrent(); + ::glVertexAttrib4fv(indx, array); +} + +void GraphicsContext3D::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, unsigned long stride, unsigned long offset) +{ + makeContextCurrent(); + ::glVertexAttribPointer(indx, size, type, normalized, stride, reinterpret_cast<void*>(static_cast<intptr_t>(offset))); +} + +void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height) +{ + makeContextCurrent(); + ::glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height)); +} + +void GraphicsContext3D::getBooleanv(unsigned long pname, unsigned char* value) +{ + makeContextCurrent(); + ::glGetBooleanv(pname, value); +} + +void GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long pname, int* value) +{ + makeContextCurrent(); + ::glGetBufferParameteriv(target, pname, value); +} + +void GraphicsContext3D::getFloatv(unsigned long pname, float* value) +{ + makeContextCurrent(); + ::glGetFloatv(pname, value); +} + +void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname, int* value) +{ + makeContextCurrent(); + if (attachment == DEPTH_STENCIL_ATTACHMENT) + attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works. + ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value); +} + +void GraphicsContext3D::getIntegerv(unsigned long pname, int* value) +{ + // Need to emulate IMPLEMENTATION_COLOR_READ_FORMAT/TYPE for GL. Any valid + // combination should work, but GL_RGB/GL_UNSIGNED_BYTE might be the most + // useful for desktop WebGL users. + // Need to emulate MAX_FRAGMENT/VERTEX_UNIFORM_VECTORS and MAX_VARYING_VECTORS + // because desktop GL's corresponding queries return the number of components + // whereas GLES2 return the number of vectors (each vector has 4 components). + // Therefore, the value returned by desktop GL needs to be divided by 4. + makeContextCurrent(); + switch (pname) { + case IMPLEMENTATION_COLOR_READ_FORMAT: + *value = GL_RGB; + break; + case IMPLEMENTATION_COLOR_READ_TYPE: + *value = GL_UNSIGNED_BYTE; + break; + case MAX_FRAGMENT_UNIFORM_VECTORS: + ::glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, value); + *value /= 4; + break; + case MAX_VERTEX_UNIFORM_VECTORS: + ::glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, value); + *value /= 4; + break; + case MAX_VARYING_VECTORS: + ::glGetIntegerv(GL_MAX_VARYING_FLOATS, value); + *value /= 4; + break; + default: + ::glGetIntegerv(pname, value); + } +} + +void GraphicsContext3D::getProgramiv(Platform3DObject program, unsigned long pname, int* value) +{ + makeContextCurrent(); + ::glGetProgramiv((GLuint) program, pname, value); +} + +String GraphicsContext3D::getProgramInfoLog(Platform3DObject program) +{ + ASSERT(program); + + makeContextCurrent(); + GLint length; + ::glGetProgramiv((GLuint) program, GL_INFO_LOG_LENGTH, &length); + + GLsizei size; + GLchar* info = (GLchar*) fastMalloc(length); + if (!info) + return ""; + + ::glGetProgramInfoLog((GLuint) program, length, &size, info); + String s(info); + fastFree(info); + return s; +} + +void GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, unsigned long pname, int* value) +{ + makeContextCurrent(); + ::glGetRenderbufferParameterivEXT(target, pname, value); +} + +void GraphicsContext3D::getShaderiv(Platform3DObject shader, unsigned long pname, int* value) +{ + ASSERT(shader); + + makeContextCurrent(); + + HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + + switch (pname) { + case DELETE_STATUS: + case SHADER_TYPE: + // Let OpenGL handle these. + + ::glGetShaderiv((GLuint) shader, pname, value); + break; + + case COMPILE_STATUS: + if (result == m_shaderSourceMap.end()) { + (*value) = static_cast<int>(false); + return; + } + + (*value) = static_cast<int>(result->second.isValid); + break; + + case INFO_LOG_LENGTH: + if (result == m_shaderSourceMap.end()) { + (*value) = 0; + return; + } + + (*value) = getShaderInfoLog(shader).length(); + break; + + case SHADER_SOURCE_LENGTH: + (*value) = getShaderSource(shader).length(); + break; + + default: + synthesizeGLError(INVALID_ENUM); + } +} + +String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader) +{ + ASSERT(shader); + + makeContextCurrent(); + GLint length; + ::glGetShaderiv((GLuint) shader, GL_INFO_LOG_LENGTH, &length); + + HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + + if (result == m_shaderSourceMap.end()) + return ""; + + ShaderSourceEntry entry = result->second; + + if (entry.isValid) { + GLint length; + ::glGetShaderiv((GLuint) shader, GL_INFO_LOG_LENGTH, &length); + + GLsizei size; + GLchar* info = (GLchar*) fastMalloc(length); + if (!info) + return ""; + + ::glGetShaderInfoLog((GLuint) shader, length, &size, info); + + String s(info); + fastFree(info); + return s; + } + else { + return entry.log; + } +} + +String GraphicsContext3D::getShaderSource(Platform3DObject shader) +{ + ASSERT(shader); + + makeContextCurrent(); + + HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + + if (result == m_shaderSourceMap.end()) + return ""; + + return result->second.source; +} + + +void GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long pname, float* value) +{ + makeContextCurrent(); + ::glGetTexParameterfv(target, pname, value); +} + +void GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long pname, int* value) +{ + makeContextCurrent(); + ::glGetTexParameteriv(target, pname, value); +} + +void GraphicsContext3D::getUniformfv(Platform3DObject program, long location, float* value) +{ + makeContextCurrent(); + ::glGetUniformfv((GLuint) program, location, value); +} + +void GraphicsContext3D::getUniformiv(Platform3DObject program, long location, int* value) +{ + makeContextCurrent(); + ::glGetUniformiv((GLuint) program, location, value); +} + +long GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name) +{ + ASSERT(program); + + makeContextCurrent(); + return ::glGetUniformLocation((GLuint) program, name.utf8().data()); +} + +void GraphicsContext3D::getVertexAttribfv(unsigned long index, unsigned long pname, float* value) +{ + makeContextCurrent(); + ::glGetVertexAttribfv(index, pname, value); +} + +void GraphicsContext3D::getVertexAttribiv(unsigned long index, unsigned long pname, int* value) +{ + makeContextCurrent(); + ::glGetVertexAttribiv(index, pname, value); +} + +long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long pname) +{ + makeContextCurrent(); + + void* pointer; + ::glGetVertexAttribPointerv(index, pname, &pointer); + return reinterpret_cast<long>(pointer); +} + +int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels) +{ + makeContextCurrent(); + + ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); + return 0; +} + +int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels) +{ + makeContextCurrent(); + + // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size + ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); + return 0; +} + +unsigned GraphicsContext3D::createBuffer() +{ + makeContextCurrent(); + GLuint o; + glGenBuffers(1, &o); + return o; +} + +unsigned GraphicsContext3D::createFramebuffer() +{ + makeContextCurrent(); + GLuint o; + glGenFramebuffersEXT(1, &o); + return o; +} + +unsigned GraphicsContext3D::createProgram() +{ + makeContextCurrent(); + return glCreateProgram(); +} + +unsigned GraphicsContext3D::createRenderbuffer() +{ + makeContextCurrent(); + GLuint o; + glGenRenderbuffersEXT(1, &o); + return o; +} + +unsigned GraphicsContext3D::createShader(unsigned long type) +{ + makeContextCurrent(); + return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER); +} + +unsigned GraphicsContext3D::createTexture() +{ + makeContextCurrent(); + GLuint o; + glGenTextures(1, &o); + return o; +} + +void GraphicsContext3D::deleteBuffer(unsigned buffer) +{ + makeContextCurrent(); + glDeleteBuffers(1, &buffer); +} + +void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer) +{ + makeContextCurrent(); + glDeleteFramebuffersEXT(1, &framebuffer); +} + +void GraphicsContext3D::deleteProgram(unsigned program) +{ + makeContextCurrent(); + glDeleteProgram(program); +} + +void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer) +{ + makeContextCurrent(); + glDeleteRenderbuffersEXT(1, &renderbuffer); +} + +void GraphicsContext3D::deleteShader(unsigned shader) +{ + makeContextCurrent(); + glDeleteShader(shader); +} + +void GraphicsContext3D::deleteTexture(unsigned texture) +{ + makeContextCurrent(); + glDeleteTextures(1, &texture); +} + +int GraphicsContext3D::sizeInBytes(int type) +{ + switch (type) { + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_INT: + return sizeof(GLint); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_FLOAT: + return sizeof(GLfloat); + default: + return 0; + } +} + +void GraphicsContext3D::synthesizeGLError(unsigned long error) +{ + m_syntheticErrors.add(error); +} + +} + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/qt/ContextShadow.cpp b/WebCore/platform/graphics/qt/ContextShadow.cpp index 829ca82..4609923 100644 --- a/WebCore/platform/graphics/qt/ContextShadow.cpp +++ b/WebCore/platform/graphics/qt/ContextShadow.cpp @@ -139,134 +139,80 @@ void ContextShadow::clear() offset = QPointF(0, 0); } -// Instead of integer division, we use 18.14 for fixed-point division. -static const int BlurSumShift = 14; +// Instead of integer division, we use 17.15 for fixed-point division. +static const int BlurSumShift = 15; -// Note: image must be RGB32 format -static void blurHorizontal(QImage& image, int radius, bool swap = false) -{ - Q_ASSERT(image.format() == QImage::Format_ARGB32_Premultiplied); +// Check http://www.w3.org/TR/SVG/filters.html#feGaussianBlur. +// As noted in the SVG filter specification, running box blur 3x +// approximates a real gaussian blur nicely. +void shadowBlur(QImage& image, int radius, const QColor& shadowColor) +{ // See comments in http://webkit.org/b/40793, it seems sensible - // to follow Skia's limit of 128 pixels of blur radius - radius = qMin(128, radius); - - int imgWidth = image.width(); - int imgHeight = image.height(); + // to follow Skia's limit of 128 pixels for the blur radius. + if (radius > 128) + radius = 128; - // Check http://www.w3.org/TR/SVG/filters.html#feGaussianBlur - // for the approaches when the box-blur radius is even vs odd. + int channels[4] = { 3, 0, 1, 3 }; int dmax = radius >> 1; - int dmin = qMax(0, dmax - 1 + (radius & 1)); - - for (int y = 0; y < imgHeight; ++y) { - - unsigned char* pixels = image.scanLine(y); - - int left; - int right; - int pixelCount; - int prev; - int next; - int firstAlpha; - int lastAlpha; - int totalAlpha; - unsigned char* target; - unsigned char* prevPtr; - unsigned char* nextPtr; - - int invCount; - - static const int alphaChannel = 3; - static const int blueChannel = 0; - static const int greenChannel = 1; - - // For each step, we use sliding window algorithm. This is much more - // efficient than computing the sum of each pixels covered by the box - // kernel size for each x. - - // As noted in the SVG filter specification, running box blur 3x - // approximates a real gaussian blur nicely. - - // Step 1: blur alpha channel and store the result in the blue channel. - left = swap ? dmax : dmin; - right = swap ? dmin : dmax; - pixelCount = left + 1 + right; - invCount = (1 << BlurSumShift) / pixelCount; - prev = -left; - next = 1 + right; - firstAlpha = pixels[alphaChannel]; - lastAlpha = pixels[(imgWidth - 1) * 4 + alphaChannel]; - totalAlpha = 0; - for (int i = 0; i < pixelCount; ++i) - totalAlpha += pixels[qBound(0, i - left, imgWidth - 1) * 4 + alphaChannel]; - target = pixels + blueChannel; - prevPtr = pixels + prev * 4 + alphaChannel; - nextPtr = pixels + next * 4 + alphaChannel; - for (int x = 0; x < imgWidth; ++x, ++prev, ++next, target += 4, prevPtr += 4, nextPtr += 4) { - *target = (totalAlpha * invCount) >> BlurSumShift; - int delta = ((next < imgWidth) ? *nextPtr : lastAlpha) - - ((prev > 0) ? *prevPtr : firstAlpha); - totalAlpha += delta; - } - - // Step 2: blur blue channel and store the result in the green channel. - left = swap ? dmin : dmax; - right = swap ? dmax : dmin; - pixelCount = left + 1 + right; - invCount = (1 << BlurSumShift) / pixelCount; - prev = -left; - next = 1 + right; - firstAlpha = pixels[blueChannel]; - lastAlpha = pixels[(imgWidth - 1) * 4 + blueChannel]; - totalAlpha = 0; - for (int i = 0; i < pixelCount; ++i) - totalAlpha += pixels[qBound(0, i - left, imgWidth - 1) * 4 + blueChannel]; - target = pixels + greenChannel; - prevPtr = pixels + prev * 4 + blueChannel; - nextPtr = pixels + next * 4 + blueChannel; - for (int x = 0; x < imgWidth; ++x, ++prev, ++next, target += 4, prevPtr += 4, nextPtr += 4) { - *target = (totalAlpha * invCount) >> BlurSumShift; - int delta = ((next < imgWidth) ? *nextPtr : lastAlpha) - - ((prev > 0) ? *prevPtr : firstAlpha); - totalAlpha += delta; - } - - // Step 3: blur green channel and store the result in the alpha channel. - left = dmax; - right = dmax; - pixelCount = left + 1 + right; - invCount = (1 << BlurSumShift) / pixelCount; - prev = -left; - next = 1 + right; - firstAlpha = pixels[greenChannel]; - lastAlpha = pixels[(imgWidth - 1) * 4 + greenChannel]; - totalAlpha = 0; - for (int i = 0; i < pixelCount; ++i) - totalAlpha += pixels[qBound(0, i - left, imgWidth - 1) * 4 + greenChannel]; - target = pixels + alphaChannel; - prevPtr = pixels + prev * 4 + greenChannel; - nextPtr = pixels + next * 4 + greenChannel; - for (int x = 0; x < imgWidth; ++x, ++prev, ++next, target += 4, prevPtr += 4, nextPtr += 4) { - *target = (totalAlpha * invCount) >> BlurSumShift; - int delta = ((next < imgWidth) ? *nextPtr : lastAlpha) - - ((prev > 0) ? *prevPtr : firstAlpha); - totalAlpha += delta; + int dmin = dmax - 1 + (radius & 1); + if (dmin < 0) + dmin = 0; + + // Two stages: horizontal and vertical + for (int k = 0; k < 2; ++k) { + + unsigned char* pixels = image.bits(); + int stride = (!k) ? 4 : image.bytesPerLine(); + int delta = (!k) ? image.bytesPerLine() : 4; + int jfinal = (!k) ? image.height() : image.width(); + int dim = (!k) ? image.width() : image.height(); + + for (int j = 0; j < jfinal; ++j, pixels += delta) { + + // For each step, we blur the alpha in a channel and store the result + // in another channel for the subsequent step. + // We use sliding window algorithm to accumulate the alpha values. + // This is much more efficient than computing the sum of each pixels + // covered by the box kernel size for each x. + + for (int step = 0; step < 3; ++step) { + int side1 = (!step) ? dmin : dmax; + int side2 = (step == 1) ? dmin : dmax; + int pixelCount = side1 + 1 + side2; + int invCount = ((1 << BlurSumShift) + pixelCount - 1) / pixelCount; + int ofs = 1 + side2; + int alpha1 = pixels[channels[step]]; + int alpha2 = pixels[(dim - 1) * stride + channels[step]]; + unsigned char* ptr = pixels + channels[step + 1]; + unsigned char* prev = pixels + stride + channels[step]; + unsigned char* next = pixels + ofs * stride + channels[step]; + + int i; + int sum = side1 * alpha1 + alpha1; + int limit = (dim < side2 + 1) ? dim : side2 + 1; + for (i = 1; i < limit; ++i, prev += stride) + sum += *prev; + if (limit <= side2) + sum += (side2 - limit + 1) * alpha2; + + limit = (side1 < dim) ? side1 : dim; + for (i = 0; i < limit; ptr += stride, next += stride, ++i, ++ofs) { + *ptr = (sum * invCount) >> BlurSumShift; + sum += ((ofs < dim) ? *next : alpha2) - alpha1; + } + prev = pixels + channels[step]; + for (; ofs < dim; ptr += stride, prev += stride, next += stride, ++i, ++ofs) { + *ptr = (sum * invCount) >> BlurSumShift; + sum += (*next) - (*prev); + } + for (; i < dim; ptr += stride, prev += stride, ++i) { + *ptr = (sum * invCount) >> BlurSumShift; + sum += alpha2 - (*prev); + } + } } } -} - -static void shadowBlur(QImage& image, int radius, const QColor& shadowColor) -{ - blurHorizontal(image, radius); - - QTransform transform; - transform.rotate(90); - image = image.transformed(transform); - blurHorizontal(image, radius, true); - transform.reset(); - transform.rotate(270); - image = image.transformed(transform); // "Colorize" with the right shadow color. QPainter p(&image); diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index 7918378..0756aa7 100644 --- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -491,13 +491,16 @@ void* GraphicsContext3DInternal::getProcAddress(const String& proc) return 0; } -PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) +PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) { - OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs, hostWindow)); + // This implementation doesn't currently support rendering directly to the HostWindow. + if (renderStyle == RenderDirectlyToHostWindow) + return 0; + OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs, hostWindow, false)); return context->m_internal ? context.release() : 0; } -GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) +GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, bool) : m_internal(new GraphicsContext3DInternal(attrs, hostWindow)) { if (!m_internal->isContextValid()) diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index c9c74dd..5a29ad4 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -174,14 +174,10 @@ public: GraphicsContextPlatformPrivate(QPainter* painter); ~GraphicsContextPlatformPrivate(); - inline QPainter* p() + inline QPainter* p() const { - if (layers.isEmpty()) { - if (redirect) - return redirect; - + if (layers.isEmpty()) return painter; - } return &layers.top()->painter; } @@ -191,7 +187,6 @@ public: // Counting real layers. Required by inTransparencyLayer() calls // For example, layers with valid alphaMask are not real layers int layerCount; - QPainter* redirect; // reuse this brush for solid color (to prevent expensive QBrush construction) QBrush solidColor; @@ -212,9 +207,9 @@ public: QRectF clipBoundingRect() const { #if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0) - return painter->clipBoundingRect(); + return p()->clipBoundingRect(); #else - return painter->clipRegion().boundingRect(); + return p()->clipRegion().boundingRect(); #endif } @@ -227,7 +222,6 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p) { painter = p; layerCount = 0; - redirect = 0; solidColor = QBrush(Qt::black); diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index e164f8c..079d8ba 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -130,22 +130,21 @@ public: TransformChange = (1L << 6), ContentChange = (1L << 7), - GeometryOrientationChange = (1L << 8), - ContentsOrientationChange = (1L << 9), - OpacityChange = (1L << 10), - ContentsRectChange = (1L << 11), - - Preserves3DChange = (1L << 12), - MasksToBoundsChange = (1L << 13), - DrawsContentChange = (1L << 14), - ContentsOpaqueChange = (1L << 15), - - BackfaceVisibilityChange = (1L << 16), - ChildrenTransformChange = (1L << 17), - DisplayChange = (1L << 18), - BackgroundColorChange = (1L << 19), - - DistributesOpacityChange = (1L << 20) + ContentsOrientationChange = (1L << 8), + OpacityChange = (1L << 9), + ContentsRectChange = (1L << 10), + + Preserves3DChange = (1L << 11), + MasksToBoundsChange = (1L << 12), + DrawsContentChange = (1L << 13), + ContentsOpaqueChange = (1L << 14), + + BackfaceVisibilityChange = (1L << 15), + ChildrenTransformChange = (1L << 16), + DisplayChange = (1L << 17), + BackgroundColorChange = (1L << 18), + + DistributesOpacityChange = (1L << 19) }; // The compositor lets us special-case images and colors, so we try to do so. @@ -250,7 +249,6 @@ public: TransformationMatrix childrenTransform; Color backgroundColor; Color currentColor; - GraphicsLayer::CompositingCoordinatesOrientation geoOrientation; GraphicsLayer::CompositingCoordinatesOrientation contentsOrientation; float opacity; QRect contentsRect; @@ -777,7 +775,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform m_state.anchorPoint = m_layer->anchorPoint(); m_state.size = m_layer->size(); m_state.transform = m_layer->transform(); - m_state.geoOrientation = m_layer->geometryOrientation(); m_state.contentsOrientation =m_layer->contentsOrientation(); m_state.opacity = m_layer->opacity(); m_state.contentsRect = m_layer->contentsRect(); @@ -837,13 +834,6 @@ PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) return new GraphicsLayerQt(client); } -/* \reimp (GraphicsLayer.h): Qt is top-down -*/ -GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation() -{ - return CompositingCoordinatesTopDown; -} - /* \reimp (GraphicsLayer.h): The current size might change, thus we need to update the whole display. */ void GraphicsLayerQt::setNeedsDisplay() @@ -1149,14 +1139,6 @@ void GraphicsLayerQt::setContentsToMedia(PlatformLayer* media) /* \reimp (GraphicsLayer.h) */ -void GraphicsLayerQt::setGeometryOrientation(CompositingCoordinatesOrientation orientation) -{ - m_impl->notifyChange(GraphicsLayerQtImpl::GeometryOrientationChange); - GraphicsLayer::setGeometryOrientation(orientation); -} - -/* \reimp (GraphicsLayer.h) -*/ void GraphicsLayerQt::setContentsOrientation(CompositingCoordinatesOrientation orientation) { m_impl->notifyChange(GraphicsLayerQtImpl::ContentsOrientationChange); diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/WebCore/platform/graphics/qt/GraphicsLayerQt.h index 4282e64..75ca498 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.h +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.h @@ -81,7 +81,6 @@ public: virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*); virtual void setGraphicsContext3DNeedsDisplay(); #endif - virtual void setGeometryOrientation(CompositingCoordinatesOrientation orientation); virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation); virtual void distributeOpacity(float); virtual float accumulatedOpacity() const; diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 605dcb7..1bf1a3d 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -25,6 +25,7 @@ #include "GraphicsContext.h" #include "HTMLMediaElement.h" #include "HTMLVideoElement.h" +#include "NetworkingContext.h" #include "NotImplemented.h" #include "TimeRanges.h" #include "Widget.h" @@ -192,8 +193,8 @@ void MediaPlayerPrivate::commitLoad(const String& url) // Grab the frame and network manager Frame* frame = document ? document->frame() : 0; + QNetworkAccessManager* manager = frame ? frame->loader()->networkingContext()->networkAccessManager() : 0; FrameLoaderClientQt* frameLoader = frame ? static_cast<FrameLoaderClientQt*>(frame->loader()->client()) : 0; - QNetworkAccessManager* manager = frameLoader ? frameLoader->webFrame()->page()->networkAccessManager() : 0; if (document && manager) { // Set the cookies diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index df54684..b8b9d5e 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -51,7 +51,6 @@ namespace WebCore { Path::Path() - : m_lastMoveToIndex(0) { } @@ -61,14 +60,12 @@ Path::~Path() Path::Path(const Path& other) : m_path(other.m_path) - , m_lastMoveToIndex(other.m_lastMoveToIndex) { } Path& Path::operator=(const Path& other) { m_path = other.m_path; - m_lastMoveToIndex = other.m_lastMoveToIndex; return *this; } @@ -183,7 +180,6 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) void Path::moveTo(const FloatPoint& point) { - m_lastMoveToIndex = m_path.elementCount(); m_path.moveTo(point); } @@ -267,30 +263,6 @@ void Path::closeSubpath() m_path.closeSubpath(); } -void Path::closeCanvasSubpath() -{ - const int elementCount = m_path.elementCount(); - - if (!elementCount) - return; - - QPointF lastMoveToPoint = m_path.elementAt(m_lastMoveToIndex); - int elementsInLastSubpath = 0; - - for (int i = m_lastMoveToIndex; i < elementCount; ++i) { - QPainterPath::Element element = m_path.elementAt(i); - if (element.isLineTo() || element.isCurveTo()) { - // All we need to know is if there are 1 or more elements in the last subpath. - if (++elementsInLastSubpath == 2) { - m_path.lineTo(lastMoveToPoint); - return; - } - } - } - - moveTo(lastMoveToPoint); -} - #define DEGREES(t) ((t) * 180.0 / M_PI) void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool anticlockwise) { diff --git a/WebCore/platform/graphics/qt/TransparencyLayer.h b/WebCore/platform/graphics/qt/TransparencyLayer.h index 1a614ac..6bdfb39 100644 --- a/WebCore/platform/graphics/qt/TransparencyLayer.h +++ b/WebCore/platform/graphics/qt/TransparencyLayer.h @@ -61,9 +61,6 @@ struct TransparencyLayer : FastAllocBase { painter.setFont(p->font()); if (painter.paintEngine()->hasFeature(QPaintEngine::PorterDuff)) painter.setCompositionMode(p->compositionMode()); - // if the path is an empty region, this assignment disables all painting - if (!p->clipPath().isEmpty()) - painter.setClipPath(p->clipPath()); } TransparencyLayer() diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp index 9625b34..0b96d80 100644 --- a/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -33,7 +33,6 @@ #include "AffineTransform.h" #include "BitmapImage.h" #include "BitmapImageSingleFrameSkia.h" -#include "ChromiumBridge.h" #include "FloatConversion.h" #include "FloatRect.h" #include "GLES2Canvas.h" @@ -311,11 +310,6 @@ bool FrameData::clear(bool clearMetadata) return false; } -PassRefPtr<Image> Image::loadPlatformResource(const char *name) -{ - return ChromiumBridge::loadPlatformImageResource(name); -} - void Image::drawPattern(GraphicsContext* context, const FloatRect& floatSrcRect, const AffineTransform& patternTransform, diff --git a/WebCore/platform/graphics/skia/NativeImageSkia.cpp b/WebCore/platform/graphics/skia/NativeImageSkia.cpp index 28e0758..3cc89cc 100644 --- a/WebCore/platform/graphics/skia/NativeImageSkia.cpp +++ b/WebCore/platform/graphics/skia/NativeImageSkia.cpp @@ -35,6 +35,7 @@ #endif #include "NativeImageSkia.h" +#include "SharedGraphicsContext3D.h" #include "SkiaUtils.h" namespace WebCore { @@ -54,6 +55,12 @@ NativeImageSkia::NativeImageSkia(const SkBitmap& other) { } + +NativeImageSkia::~NativeImageSkia() +{ + SharedGraphicsContext3D::removeTexturesFor(this); +} + int NativeImageSkia::decodedSize() const { return getSize() + m_resizedImage.getSize(); diff --git a/WebCore/platform/graphics/skia/NativeImageSkia.h b/WebCore/platform/graphics/skia/NativeImageSkia.h index e26a5ea..00b0a68 100644 --- a/WebCore/platform/graphics/skia/NativeImageSkia.h +++ b/WebCore/platform/graphics/skia/NativeImageSkia.h @@ -42,6 +42,7 @@ namespace WebCore { class NativeImageSkia : public SkBitmap { public: NativeImageSkia(); + ~NativeImageSkia(); // This constructor does a shallow copy of the passed-in SkBitmap (ie., it // references the same pixel data and bumps the refcount). Use only when diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index 88fbcdd..88fbcdd 100755..100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp diff --git a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.h b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.h new file mode 100644 index 0000000..05f9eab --- /dev/null +++ b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2007 Pioneer Research Center USA, 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. + * + */ + +#ifndef FontPlatformDataCairoWin_h +#define FontPlatformDataCairoWin_h + +#include "FontDescription.h" +#include "GlyphBuffer.h" +#include "RefCountedGDIHandle.h" +#include "StringImpl.h" +#include <cairo-win32.h> +#include <cairo.h> +#include <wtf/Forward.h> + +typedef struct HFONT__* HFONT; + +namespace WebCore { + +class FontPlatformData { +public: + FontPlatformData(WTF::HashTableDeletedValueType) + : m_fontFace(0) + , m_useGDI(false) + , m_font(WTF::HashTableDeletedValue) + , m_size(0) + , m_syntheticBold(false) + , m_syntheticOblique(false) + , m_scaledFont(0) + { } + + FontPlatformData() + : m_fontFace(0) + , m_useGDI(false) + , m_size(0) + , m_syntheticBold(false) + , m_syntheticOblique(false) + , m_scaledFont(0) + { } + + FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI); + FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic); + FontPlatformData(float size, bool bold, bool italic); + FontPlatformData(const FontPlatformData&); + ~FontPlatformData(); + + HFONT hfont() const { return m_font->handle(); } + bool useGDI() const { return m_useGDI; } + cairo_font_face_t* fontFace() const { return m_fontFace; } + + bool isFixedPitch(); + float size() const { return m_size; } + void setSize(float size) { m_size = size; } + bool syntheticBold() const { return m_syntheticBold; } + bool syntheticOblique() const { return m_syntheticOblique; } + cairo_scaled_font_t* scaledFont() const { return m_scaledFont; } + + unsigned hash() const + { + return m_font->hash(); + } + + bool operator==(const FontPlatformData&) const; + FontPlatformData& operator=(const FontPlatformData&); + bool isHashTableDeletedValue() const + { + return m_font.isHashTableDeletedValue(); + } + +#ifndef NDEBUG + String description() const; +#endif + +private: + void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); + + RefPtr<RefCountedGDIHandle<HFONT> > m_font; + cairo_font_face_t* m_fontFace; + bool m_useGDI; + float m_size; + bool m_syntheticBold; + bool m_syntheticOblique; + cairo_scaled_font_t* m_scaledFont; +}; + +} + +#endif // FontPlatformDataCairoWin_h diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp index 96ac0c1..dad5da1 100644 --- a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp +++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp @@ -121,11 +121,6 @@ static void clearLayerBackgroundColor(WKCACFLayer* layer) layer->setBackgroundColor(0); } -GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation() -{ - return CompositingCoordinatesBottomUp; -} - PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return new GraphicsLayerCACF(client); @@ -395,15 +390,6 @@ void GraphicsLayerCACF::setContentsToMedia(PlatformLayer* mediaLayer) updateSublayerList(); } -void GraphicsLayerCACF::setGeometryOrientation(CompositingCoordinatesOrientation orientation) -{ - if (orientation == m_geometryOrientation) - return; - - GraphicsLayer::setGeometryOrientation(orientation); - updateGeometryOrientation(); -} - PlatformLayer* GraphicsLayerCACF::hostLayerForSublayers() const { return m_transformLayer ? m_transformLayer.get() : m_layer.get(); @@ -461,13 +447,6 @@ void GraphicsLayerCACF::swapFromOrToTiledLayer(bool useTiledLayer) m_layer = WebLayer::create(WKCACFLayer::Layer, this); m_usingTiledLayer = useTiledLayer; - - if (useTiledLayer) { - if (GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp) - m_layer->setContentsGravity(WKCACFLayer::BottomLeft); - else - m_layer->setContentsGravity(WKCACFLayer::TopLeft); - } m_layer->adoptSublayers(oldLayer.get()); if (oldLayer->superlayer()) @@ -738,21 +717,6 @@ void GraphicsLayerCACF::updateContentsRect() m_contentsLayer->setBounds(rect); } -void GraphicsLayerCACF::updateGeometryOrientation() -{ - switch (geometryOrientation()) { - case CompositingCoordinatesTopDown: - m_layer->setGeometryFlipped(false); - break; - - case CompositingCoordinatesBottomUp: - m_layer->setGeometryFlipped(true); - break; - } - // Geometry orientation is mapped onto children transform in older QuartzCores, - // so is handled via setGeometryOrientation(). -} - void GraphicsLayerCACF::setupContentsLayer(WKCACFLayer* contentsLayer) { if (contentsLayer == m_contentsLayer) diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.h b/WebCore/platform/graphics/win/GraphicsLayerCACF.h index 0b74266..c18a6e9 100644 --- a/WebCore/platform/graphics/win/GraphicsLayerCACF.h +++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.h @@ -89,8 +89,6 @@ public: virtual void setDebugBackgroundColor(const Color&); virtual void setDebugBorder(const Color&, float borderWidth); - virtual void setGeometryOrientation(CompositingCoordinatesOrientation); - private: void updateOpacityOnLayer(); @@ -118,7 +116,6 @@ private: void updateContentsImage(); void updateContentsMedia(); void updateContentsRect(); - void updateGeometryOrientation(); void setupContentsLayer(WKCACFLayer*); WKCACFLayer* contentsLayer() const { return m_contentsLayer.get(); } diff --git a/WebCore/platform/graphics/win/LocalWindowsContext.h b/WebCore/platform/graphics/win/LocalWindowsContext.h index c216140..c216140 100755..100644 --- a/WebCore/platform/graphics/win/LocalWindowsContext.h +++ b/WebCore/platform/graphics/win/LocalWindowsContext.h diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp index e664f2a..4a7e45e 100644..100755 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp @@ -107,7 +107,6 @@ void MediaPlayerPrivateFullscreenWindow::setRootChildLayer(PassRefPtr<WKCACFLaye WKCACFLayer* rootLayer = m_rootChild->rootLayer(); CGRect rootBounds = m_rootChild->rootLayer()->bounds(); m_rootChild->setFrame(rootBounds); - m_layerRenderer->setScrollFrame(IntPoint(rootBounds.origin), IntSize(rootBounds.size)); m_rootChild->setBackgroundColor(CGColorGetConstantColor(kCGColorBlack)); #ifndef NDEBUG RetainPtr<CGColorRef> redColor(AdoptCF, CGColorCreateGenericRGB(1, 0, 0, 1)); @@ -165,7 +164,6 @@ LRESULT MediaPlayerPrivateFullscreenWindow::wndProc(HWND hWnd, UINT message, WPA CGRect rootBounds = m_rootChild->rootLayer()->bounds(); m_rootChild->setFrame(rootBounds); m_rootChild->setNeedsLayout(); - m_layerRenderer->setScrollFrame(IntPoint(rootBounds.origin), IntSize(rootBounds.size)); #endif } break; diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp index 9bc68d1..354e0bf 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp @@ -97,6 +97,39 @@ public: private: MediaPlayerPrivateQuickTimeVisualContext* m_parent; }; + +class MediaPlayerPrivateQuickTimeVisualContext::LayoutClient : public WKCACFLayerLayoutClient { +public: + LayoutClient(MediaPlayerPrivateQuickTimeVisualContext* parent) : m_parent(parent) {} + virtual void layoutSublayersOfLayer(WKCACFLayer*); +private: + MediaPlayerPrivateQuickTimeVisualContext* m_parent; +}; + +void MediaPlayerPrivateQuickTimeVisualContext::LayoutClient::layoutSublayersOfLayer(WKCACFLayer* layer) +{ + ASSERT(m_parent); + ASSERT(m_parent->m_transformLayer->platformLayer() == layer); + + CGSize parentSize = layer->bounds().size; + CGSize naturalSize = m_parent->naturalSize(); + + // Calculate the ratio of these two sizes and use that ratio to scale the qtVideoLayer: + CGSize ratio = CGSizeMake(parentSize.width / naturalSize.width, parentSize.height / naturalSize.height); + + int videoWidth = 0; + int videoHeight = 0; + m_parent->m_movie->getNaturalSize(videoWidth, videoHeight); + CGRect videoBounds = CGRectMake(0, 0, videoWidth * ratio.width, videoHeight * ratio.height); + CGPoint videoAnchor = m_parent->m_qtVideoLayer->anchorPoint(); + + // Calculate the new position based on the parent's size: + CGPoint position = CGPointMake(parentSize.width * 0.5 - videoBounds.size.width * (0.5 - videoAnchor.x), + parentSize.height * 0.5 - videoBounds.size.height * (0.5 - videoAnchor.y)); + + m_parent->m_qtVideoLayer->setBounds(videoBounds); + m_parent->m_qtVideoLayer->setPosition(position); +} #endif class MediaPlayerPrivateQuickTimeVisualContext::VisualContextClient : public QTMovieVisualContextClient { @@ -137,6 +170,8 @@ MediaPlayerPrivateQuickTimeVisualContext::MediaPlayerPrivateQuickTimeVisualConte , m_movieClient(new MediaPlayerPrivateQuickTimeVisualContext::MovieClient(this)) #if USE(ACCELERATED_COMPOSITING) , m_layerClient(new MediaPlayerPrivateQuickTimeVisualContext::LayerClient(this)) + , m_layoutClient(new MediaPlayerPrivateQuickTimeVisualContext::LayoutClient(this)) + , m_movieTransform(CGAffineTransformIdentity) #endif , m_visualContextClient(new MediaPlayerPrivateQuickTimeVisualContext::VisualContextClient(this)) { @@ -169,7 +204,7 @@ PlatformMedia MediaPlayerPrivateQuickTimeVisualContext::platformMedia() const #if USE(ACCELERATED_COMPOSITING) PlatformLayer* MediaPlayerPrivateQuickTimeVisualContext::platformLayer() const { - return m_qtVideoLayer ? m_qtVideoLayer->platformLayer() : 0; + return m_transformLayer ? m_transformLayer->platformLayer() : 0; } #endif @@ -263,6 +298,24 @@ void MediaPlayerPrivateQuickTimeVisualContext::setUpCookiesForQuickTime(const St } } +static void disableComponentsOnce() +{ + static bool sComponentsDisabled = false; + if (sComponentsDisabled) + return; + sComponentsDisabled = true; + + uint32_t componentsToDisable[][5] = { + {'eat ', 'TEXT', 'text', 0, 0}, + {'eat ', 'TXT ', 'text', 0, 0}, + {'eat ', 'utxt', 'text', 0, 0}, + {'eat ', 'TEXT', 'tx3g', 0, 0}, + }; + + for (size_t i = 0; i < sizeof(componentsToDisable) / sizeof(componentsToDisable[0]); ++i) + QTMovie::disableComponent(componentsToDisable[i]); +} + void MediaPlayerPrivateQuickTimeVisualContext::load(const String& url) { if (!QTMovie::initializeQuickTime()) { @@ -272,6 +325,8 @@ void MediaPlayerPrivateQuickTimeVisualContext::load(const String& url) return; } + disableComponentsOnce(); + // Initialize the task timer. MediaPlayerPrivateTaskTimer::initialize(); @@ -404,7 +459,13 @@ IntSize MediaPlayerPrivateQuickTimeVisualContext::naturalSize() const int width; int height; m_movie->getNaturalSize(width, height); +#if USE(ACCELERATED_COMPOSITING) + CGSize originalSize = {width, height}; + CGSize transformedSize = CGSizeApplyAffineTransform(originalSize, m_movieTransform); + return IntSize(abs(transformedSize.width), abs(transformedSize.height)); +#else return IntSize(width, height); +#endif } bool MediaPlayerPrivateQuickTimeVisualContext::hasVideo() const @@ -763,7 +824,7 @@ void MediaPlayerPrivateQuickTimeVisualContext::retrieveCurrentImage() if (!buffer.pixelBufferRef()) return; - WKCACFLayer* layer = static_cast<WKCACFLayer*>(m_qtVideoLayer->platformLayer()); + WKCACFLayer* layer = m_qtVideoLayer.get(); if (!buffer.lockBaseAddress()) { if (requiredDllsAvailable()) { @@ -1017,6 +1078,40 @@ bool MediaPlayerPrivateQuickTimeVisualContext::hasSetUpVideoRendering() const #endif } +void MediaPlayerPrivateQuickTimeVisualContext::retrieveAndResetMovieTransform() +{ +#if USE(ACCELERATED_COMPOSITING) + // First things first, reset the total movie transform so that + // we can bail out early: + m_movieTransform = CGAffineTransformIdentity; + + if (!m_movie || !m_movie->hasVideo()) + return; + + // This trick will only work on movies with a single video track, + // so bail out early if the video contains more than one (or zero) + // video tracks. + QTTrackArray videoTracks = m_movie->videoTracks(); + if (videoTracks.size() != 1) + return; + + QTTrack* track = videoTracks[0].get(); + ASSERT(track); + + CGAffineTransform movieTransform = m_movie->getTransform(); + if (!CGAffineTransformEqualToTransform(movieTransform, CGAffineTransformIdentity)) + m_movie->resetTransform(); + + CGAffineTransform trackTransform = track->getTransform(); + if (!CGAffineTransformEqualToTransform(trackTransform, CGAffineTransformIdentity)) + track->resetTransform(); + + // Multiply the two transforms together, taking care to + // do so in the correct order, track * movie = final: + m_movieTransform = CGAffineTransformConcat(trackTransform, movieTransform); +#endif +} + void MediaPlayerPrivateQuickTimeVisualContext::createLayerForMovie() { #if USE(ACCELERATED_COMPOSITING) @@ -1028,17 +1123,35 @@ void MediaPlayerPrivateQuickTimeVisualContext::createLayerForMovie() // Create a GraphicsLayer that won't be inserted directly into the render tree, but will used // as a wrapper for a WKCACFLayer which gets inserted as the content layer of the video // renderer's GraphicsLayer. - m_qtVideoLayer.set(new GraphicsLayerCACF(m_layerClient.get())); - if (!m_qtVideoLayer) + m_transformLayer.set(new GraphicsLayerCACF(m_layerClient.get())); + if (!m_transformLayer) return; // Mark the layer as drawing itself, anchored in the top left, and bottom-up. - m_qtVideoLayer->setDrawsContent(true); - m_qtVideoLayer->setAnchorPoint(FloatPoint3D()); - m_qtVideoLayer->setContentsOrientation(GraphicsLayer::CompositingCoordinatesBottomUp); + m_transformLayer->setDrawsContent(false); + m_transformLayer->setAnchorPoint(FloatPoint3D()); + m_transformLayer->setContentsOrientation(GraphicsLayer::CompositingCoordinatesBottomUp); + m_transformLayer->platformLayer()->setLayoutClient(m_layoutClient.get()); + + m_qtVideoLayer = WKCACFLayer::create(WKCACFLayer::Layer); + if (!m_qtVideoLayer) + return; + + if (CGAffineTransformEqualToTransform(m_movieTransform, CGAffineTransformIdentity)) + retrieveAndResetMovieTransform(); + CGAffineTransform t = m_movieTransform; + + // Remove the translation portion of the transform, since we will always rotate about + // the layer's center point. In our limited use-case (a single video track), this is + // safe: + t.tx = t.ty = 0; + m_qtVideoLayer->setTransform(CATransform3DMakeAffineTransform(t)); + #ifndef NDEBUG m_qtVideoLayer->setName("Video layer"); #endif + m_transformLayer->platformLayer()->addSublayer(m_qtVideoLayer.get()); + m_transformLayer->platformLayer()->setNeedsLayout(); // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration(). #endif @@ -1052,8 +1165,13 @@ void MediaPlayerPrivateQuickTimeVisualContext::createLayerForMovie() void MediaPlayerPrivateQuickTimeVisualContext::destroyLayerForMovie() { #if USE(ACCELERATED_COMPOSITING) - if (m_qtVideoLayer) + if (m_qtVideoLayer) { + m_qtVideoLayer->removeFromSuperlayer(); m_qtVideoLayer = 0; + } + + if (m_transformLayer) + m_transformLayer = 0; if (m_imageQueue) m_imageQueue = 0; diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h index 9c449dd..272b90f 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h @@ -50,6 +50,7 @@ class IntSize; class IntRect; #if USE(ACCELERATED_COMPOSITING) +class WKCACFLayer; class WKCAImageQueue; #endif @@ -154,17 +155,25 @@ private: class LayerClient; friend class LayerClient; OwnPtr<LayerClient> m_layerClient; + + class LayoutClient; + friend class LayoutClient; + OwnPtr<LayoutClient> m_layoutClient; #endif class VisualContextClient; friend class VisualContextClient; OwnPtr<VisualContextClient> m_visualContextClient; + void retrieveAndResetMovieTransform(); + MediaPlayer* m_player; RefPtr<QTMovie> m_movie; #if USE(ACCELERATED_COMPOSITING) - OwnPtr<GraphicsLayer> m_qtVideoLayer; + RefPtr<WKCACFLayer> m_qtVideoLayer; + OwnPtr<GraphicsLayer> m_transformLayer; OwnPtr<WKCAImageQueue> m_imageQueue; + CGAffineTransform m_movieTransform; #endif RefPtr<QTMovieVisualContext> m_visualContext; float m_seekTo; @@ -185,6 +194,7 @@ private: double m_timeStartedPlaying; double m_timeStoppedPlaying; #endif + }; } diff --git a/WebCore/platform/graphics/win/QTMovie.cpp b/WebCore/platform/graphics/win/QTMovie.cpp index cc1349a..375d8c2 100644 --- a/WebCore/platform/graphics/win/QTMovie.cpp +++ b/WebCore/platform/graphics/win/QTMovie.cpp @@ -28,6 +28,7 @@ #include "QTMovieTask.h" #include "QTMovieWinTimer.h" +#include <FixMath.h> #include <GXMath.h> #include <Movies.h> #include <QTML.h> @@ -279,6 +280,16 @@ QTMovie::~QTMovie() delete m_private; } +void QTMovie::disableComponent(uint32_t cd[5]) +{ + ComponentDescription nullDesc = {'null', 'base', kAppleManufacturer, 0, 0}; + Component nullComp = FindNextComponent(0, &nullDesc); + Component disabledComp = 0; + + while (disabledComp = FindNextComponent(disabledComp, (ComponentDescription*)&cd[0])) + CaptureComponent(disabledComp, nullComp); +} + void QTMovie::addClient(QTMovieClient* client) { if (client) @@ -696,6 +707,16 @@ bool QTMovie::hasAudio() const return (GetMovieIndTrackType(m_private->m_movie, 1, AudioMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly)); } +QTTrackArray QTMovie::videoTracks() const +{ + QTTrackArray tracks; + long trackIndex = 1; + + while (Track theTrack = GetMovieIndTrackType(m_private->m_movie, trackIndex++, VisualMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly)) + tracks.append(QTTrack::create(theTrack)); + + return tracks; +} bool QTMovie::hasClosedCaptions() const { @@ -830,6 +851,45 @@ void QTMovie::getSupportedType(unsigned index, const UChar*& str, unsigned& len) } +CGAffineTransform QTMovie::getTransform() const +{ + ASSERT(m_private->m_movie); + MatrixRecord m = {0}; + GetMovieMatrix(m_private->m_movie, &m); + + ASSERT(!m.matrix[0][2]); + ASSERT(!m.matrix[1][2]); + CGAffineTransform transform = CGAffineTransformMake( + Fix2X(m.matrix[0][0]), + Fix2X(m.matrix[0][1]), + Fix2X(m.matrix[1][0]), + Fix2X(m.matrix[1][1]), + Fix2X(m.matrix[2][0]), + Fix2X(m.matrix[2][1])); + return transform; +} + +void QTMovie::setTransform(CGAffineTransform t) +{ + ASSERT(m_private->m_movie); + MatrixRecord m = {{ + {X2Fix(t.a), X2Fix(t.b), 0}, + {X2Fix(t.c), X2Fix(t.d), 0}, + {X2Fix(t.tx), X2Fix(t.ty), fract1}, + }}; + + SetMovieMatrix(m_private->m_movie, &m); + m_private->cacheMovieScale(); +} + +void QTMovie::resetTransform() +{ + ASSERT(m_private->m_movie); + SetMovieMatrix(m_private->m_movie, 0); + m_private->cacheMovieScale(); +} + + bool QTMovie::initializeQuickTime() { static bool initialized = false; diff --git a/WebCore/platform/graphics/win/QTMovie.h b/WebCore/platform/graphics/win/QTMovie.h index 8fa4b6e..e205b68 100644 --- a/WebCore/platform/graphics/win/QTMovie.h +++ b/WebCore/platform/graphics/win/QTMovie.h @@ -26,9 +26,8 @@ #ifndef QTMovie_h #define QTMovie_h -#include <Unicode.h> -#include <windows.h> -#include <wtf/RefCounted.h> +#include "QTTrack.h" +#include <WTF/Vector.h> #ifdef QTMOVIEWIN_EXPORTS #define QTMOVIEWIN_API __declspec(dllexport) @@ -39,6 +38,7 @@ class QTMovie; class QTMoviePrivate; typedef struct MovieType** Movie; +typedef Vector<RefPtr<QTTrack>> QTTrackArray; class QTMovieClient { public: @@ -62,6 +62,8 @@ public: static bool initializeQuickTime(); static void taskTimerFired(); + static void disableComponent(uint32_t[5]); + QTMovie(QTMovieClient*); ~QTMovie(); @@ -99,12 +101,18 @@ public: bool hasVideo() const; bool hasAudio() const; + QTTrackArray videoTracks() const; + bool hasClosedCaptions() const; void setClosedCaptionsVisible(bool); static unsigned countSupportedTypes(); static void getSupportedType(unsigned index, const UChar*& str, unsigned& len); + CGAffineTransform getTransform() const; + void setTransform(CGAffineTransform); + void resetTransform(); + Movie getMovieHandle() const; private: diff --git a/WebCore/platform/graphics/win/QTTrack.cpp b/WebCore/platform/graphics/win/QTTrack.cpp new file mode 100644 index 0000000..09142bc --- /dev/null +++ b/WebCore/platform/graphics/win/QTTrack.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2007, 2008, 2009, 2010 Apple, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "config.h" + +#include "QTTrack.h" + +#include <Movies.h> +#include <QTML.h> + +using namespace std; + +class QTTrackPrivate : public Noncopyable { +public: + QTTrackPrivate(); + ~QTTrackPrivate(); + + QTTrack* m_track; + Track m_trackHandle; +}; + +QTTrackPrivate::QTTrackPrivate() + : m_track(0) + , m_trackHandle(0) +{ +} + +QTTrackPrivate::~QTTrackPrivate() +{ + m_trackHandle = 0; +} + +PassRefPtr<QTTrack> QTTrack::create(Track trackHandle) +{ + return adoptRef(new QTTrack(trackHandle)); +} + +QTTrack::QTTrack(Track trackHandle) + : m_private(new QTTrackPrivate()) +{ + m_private->m_track = this; + m_private->m_trackHandle = trackHandle; +} + +QTTrack::~QTTrack() +{ + delete m_private; +} + +bool QTTrack::isEnabled() const +{ + ASSERT(m_private->m_track); + return GetTrackEnabled(m_private->m_trackHandle); +} + +void QTTrack::setEnabled(bool enabled) +{ + ASSERT(m_private->m_trackHandle); + SetTrackEnabled(m_private->m_trackHandle, enabled); +} + +CGAffineTransform QTTrack::getTransform() const +{ + ASSERT(m_private->m_trackHandle); + MatrixRecord m = {0}; + GetTrackMatrix(m_private->m_trackHandle, &m); + + ASSERT(!m.matrix[0][2]); + ASSERT(!m.matrix[1][2]); + CGAffineTransform transform = CGAffineTransformMake( + Fix2X(m.matrix[0][0]), + Fix2X(m.matrix[0][1]), + Fix2X(m.matrix[1][0]), + Fix2X(m.matrix[1][1]), + Fix2X(m.matrix[2][0]), + Fix2X(m.matrix[2][1])); + + return transform; +} + +void QTTrack::setTransform(CGAffineTransform t) +{ + ASSERT(m_private->m_trackHandle); + MatrixRecord m = {{ + {X2Fix(t.a), X2Fix(t.b), 0}, + {X2Fix(t.c), X2Fix(t.d), 0}, + {X2Fix(t.tx), X2Fix(t.ty), fract1}, + }}; + + SetTrackMatrix(m_private->m_trackHandle, &m); +} + +void QTTrack::resetTransform() +{ + ASSERT(m_private->m_trackHandle); + SetTrackMatrix(m_private->m_trackHandle, 0); +} + diff --git a/WebCore/platform/graphics/win/QTTrack.h b/WebCore/platform/graphics/win/QTTrack.h new file mode 100644 index 0000000..bda5644 --- /dev/null +++ b/WebCore/platform/graphics/win/QTTrack.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007, 2008, 2009, 2010 Apple, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef QTTrack_h +#define QTTrack_h + +#include <Unicode.h> +#include <windows.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +// We must include this after <Unicode.h>, or the definition of OSErr will change: +#include <CoreGraphics/CGAffineTransform.h> + +#ifdef QTMOVIEWIN_EXPORTS +#define QTMOVIEWIN_API __declspec(dllexport) +#else +#define QTMOVIEWIN_API __declspec(dllimport) +#endif + +class QTTrack; +class QTTrackPrivate; +typedef struct TrackType** Track; + +class QTMOVIEWIN_API QTTrack : public RefCounted<QTTrack> { +public: + static PassRefPtr<QTTrack> create(Track); + ~QTTrack(); + + CGAffineTransform getTransform() const; + void setTransform(CGAffineTransform); + void resetTransform(); + + bool isEnabled() const; + void setEnabled(bool); + + Track getTrackHandle() const; +private: + QTTrack(Track); + QTTrackPrivate* m_private; + friend class QTTrackPrivate; +}; + +#endif diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp index bbe5883..bf47925 100644 --- a/WebCore/platform/graphics/win/WKCACFLayer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp @@ -355,6 +355,9 @@ void WKCACFLayer::setBounds(const CGRect& rect) if (m_needsDisplayOnBoundsChange) setNeedsDisplay(); + + if (m_layoutClient) + setNeedsLayout(); } void WKCACFLayer::setFrame(const CGRect& rect) @@ -368,6 +371,9 @@ void WKCACFLayer::setFrame(const CGRect& rect) if (m_needsDisplayOnBoundsChange && !CGSizeEqualToSize(rect.size, oldFrame.size)) setNeedsDisplay(); + + if (m_layoutClient) + setNeedsLayout(); } void WKCACFLayer::setContentsGravity(ContentsGravityType type) diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp index 630a8af..4f39b13 100644..100755 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp @@ -226,15 +226,11 @@ WKCACFLayerRenderer::WKCACFLayerRenderer(WKCACFLayerRendererClient* client) : m_client(client) , m_mightBeAbleToCreateDeviceLater(true) , m_rootLayer(WKCACFRootLayer::create(this)) - , m_scrollLayer(WKCACFLayer::create(WKCACFLayer::Layer)) - , m_clipLayer(WKCACFLayer::create(WKCACFLayer::Layer)) , m_context(AdoptCF, CACFContextCreate(0)) , m_renderContext(static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get()))) , m_renderer(0) , m_hostWindow(0) , m_renderTimer(this, &WKCACFLayerRenderer::renderTimerFired) - , m_scrollPosition(0, 0) - , m_scrollSize(1, 1) , m_backingStoreDirty(false) , m_mustResetLostDeviceBeforeRendering(false) { @@ -250,15 +246,8 @@ WKCACFLayerRenderer::WKCACFLayerRenderer(WKCACFLayerRendererClient* client) // Scrolling will affect only the position of the scroll layer without affecting the bounds. m_rootLayer->setName("WKCACFLayerRenderer rootLayer"); - m_clipLayer->setName("WKCACFLayerRenderer clipLayer"); - m_scrollLayer->setName("WKCACFLayerRenderer scrollLayer"); - - m_rootLayer->addSublayer(m_clipLayer); - m_clipLayer->addSublayer(m_scrollLayer); - m_clipLayer->setMasksToBounds(true); m_rootLayer->setAnchorPoint(CGPointMake(0, 0)); - m_scrollLayer->setAnchorPoint(CGPointMake(0, 1)); - m_clipLayer->setAnchorPoint(CGPointMake(0, 1)); + m_rootLayer->setGeometryFlipped(true); #ifndef NDEBUG CGColorRef debugColor = createCGColor(Color(255, 0, 0, 204)); @@ -285,26 +274,6 @@ WKCACFLayer* WKCACFLayerRenderer::rootLayer() const return m_rootLayer.get(); } -void WKCACFLayerRenderer::setScrollFrame(const IntPoint& position, const IntSize& size) -{ - m_scrollSize = size; - m_scrollPosition = position; - - updateScrollFrame(); -} - -void WKCACFLayerRenderer::updateScrollFrame() -{ - CGRect frameBounds = bounds(); - m_clipLayer->setBounds(CGRectMake(0, 0, m_scrollSize.width(), m_scrollSize.height())); - m_clipLayer->setPosition(CGPointMake(0, frameBounds.size.height)); - if (m_rootChildLayer) { - CGRect rootBounds = m_rootChildLayer->bounds(); - m_scrollLayer->setBounds(rootBounds); - } - m_scrollLayer->setPosition(CGPointMake(-m_scrollPosition.x(), m_scrollPosition.y() + m_scrollSize.height())); -} - void WKCACFLayerRenderer::setRootContents(CGImageRef image) { ASSERT(m_rootLayer); @@ -321,16 +290,10 @@ void WKCACFLayerRenderer::setRootContentsAndDisplay(CGImageRef image) void WKCACFLayerRenderer::setRootChildLayer(WKCACFLayer* layer) { - if (!m_scrollLayer) - return; - - m_scrollLayer->removeAllSublayers(); + m_rootLayer->removeAllSublayers(); m_rootChildLayer = layer; - if (layer) { - m_scrollLayer->addSublayer(layer); - // Adjust the scroll frame accordingly - updateScrollFrame(); - } + if (m_rootChildLayer) + m_rootLayer->addSublayer(m_rootChildLayer); } void WKCACFLayerRenderer::layerTreeDidChange() @@ -435,8 +398,6 @@ void WKCACFLayerRenderer::destroyRenderer() s_d3d = 0; m_rootLayer = 0; - m_clipLayer = 0; - m_scrollLayer = 0; m_rootChildLayer = 0; m_mightBeAbleToCreateDeviceLater = true; @@ -454,7 +415,6 @@ void WKCACFLayerRenderer::resize() if (m_rootLayer) { m_rootLayer->setBounds(bounds()); WKCACFContextFlusher::shared().flushAllContexts(); - updateScrollFrame(); } } diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h index 2647c5f..1d73b99 100644..100755 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h @@ -66,7 +66,6 @@ public: static bool acceleratedCompositingAvailable(); static void didFlushContext(CACFContextRef); - void setScrollFrame(const IntPoint&, const IntSize&); void setRootContents(CGImageRef); void setRootContentsAndDisplay(CGImageRef); void setRootChildLayer(WKCACFLayer* layer); @@ -78,7 +77,6 @@ public: void destroyRenderer(); void resize(); void renderSoon(); - void updateScrollFrame(); protected: WKCACFLayer* rootLayer() const; @@ -105,16 +103,12 @@ private: bool m_mightBeAbleToCreateDeviceLater; COMPtr<IDirect3DDevice9> m_d3dDevice; RefPtr<WKCACFRootLayer> m_rootLayer; - RefPtr<WKCACFLayer> m_scrollLayer; RefPtr<WKCACFLayer> m_rootChildLayer; - RefPtr<WKCACFLayer> m_clipLayer; RetainPtr<CACFContextRef> m_context; CARenderContext* m_renderContext; CARenderOGLContext* m_renderer; HWND m_hostWindow; Timer<WKCACFLayerRenderer> m_renderTimer; - IntPoint m_scrollPosition; - IntSize m_scrollSize; bool m_backingStoreDirty; bool m_mustResetLostDeviceBeforeRendering; #ifndef NDEBUG diff --git a/WebCore/platform/graphics/win/WebLayer.cpp b/WebCore/platform/graphics/win/WebLayer.cpp index 70a522d..70a522d 100755..100644 --- a/WebCore/platform/graphics/win/WebLayer.cpp +++ b/WebCore/platform/graphics/win/WebLayer.cpp diff --git a/WebCore/platform/graphics/win/WebTiledLayer.cpp b/WebCore/platform/graphics/win/WebTiledLayer.cpp index 01dd6ae..01dd6ae 100755..100644 --- a/WebCore/platform/graphics/win/WebTiledLayer.cpp +++ b/WebCore/platform/graphics/win/WebTiledLayer.cpp diff --git a/WebCore/platform/graphics/wince/ColorWince.cpp b/WebCore/platform/graphics/wince/ColorWinCE.cpp index 820b9d2..820b9d2 100644 --- a/WebCore/platform/graphics/wince/ColorWince.cpp +++ b/WebCore/platform/graphics/wince/ColorWinCE.cpp diff --git a/WebCore/platform/graphics/wince/FontCacheWince.cpp b/WebCore/platform/graphics/wince/FontCacheWinCE.cpp index 6b5dfa5..ccfc063 100644 --- a/WebCore/platform/graphics/wince/FontCacheWince.cpp +++ b/WebCore/platform/graphics/wince/FontCacheWinCE.cpp @@ -348,5 +348,4 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigne copyToVector(procData.m_traitsMasks, traitsMasks); } -} - +} // namespace WebCore diff --git a/WebCore/platform/graphics/wince/FontWince.cpp b/WebCore/platform/graphics/wince/FontWinCE.cpp index c0948c0..e2ff067 100644 --- a/WebCore/platform/graphics/wince/FontWince.cpp +++ b/WebCore/platform/graphics/wince/FontWinCE.cpp @@ -334,4 +334,4 @@ bool Font::canReturnFallbackFontsForComplexText() return false; } -} +} // namespace WebCore diff --git a/WebCore/platform/graphics/wince/GlyphPageTreeNodeWince.cpp b/WebCore/platform/graphics/wince/GlyphPageTreeNodeWinCE.cpp index 27c4e15..1c22f23 100644 --- a/WebCore/platform/graphics/wince/GlyphPageTreeNodeWince.cpp +++ b/WebCore/platform/graphics/wince/GlyphPageTreeNodeWinCE.cpp @@ -75,5 +75,4 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b return true; } -} - +} // namespace WebCore diff --git a/WebCore/platform/graphics/wince/GradientWince.cpp b/WebCore/platform/graphics/wince/GradientWinCE.cpp index 49fa970..d735881 100644 --- a/WebCore/platform/graphics/wince/GradientWince.cpp +++ b/WebCore/platform/graphics/wince/GradientWinCE.cpp @@ -34,7 +34,7 @@ static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::Co return a.stop < b.stop; } -const Vector<Gradient::ColorStop>& Gradient::getStops() const +const Vector<Gradient::ColorStop, 2>& Gradient::getStops() const { if (!m_stopsSorted) { if (m_stops.size()) @@ -49,4 +49,4 @@ void Gradient::fill(GraphicsContext* c, const FloatRect& r) c->fillRect(r, this); } -} +} // namespace WebCore diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp index 990a31d..a91b988 100644 --- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp +++ b/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp @@ -29,7 +29,7 @@ #include "GraphicsContextPrivate.h" #include "NotImplemented.h" #include "Path.h" -#include "PlatformPathWince.h" +#include "PlatformPathWinCE.h" #include "SharedBitmap.h" #include "SimpleFontData.h" #include <wtf/OwnPtr.h> diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp index 10e502d..15720f3 100644 --- a/WebCore/platform/graphics/wince/ImageBufferWince.cpp +++ b/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp @@ -25,9 +25,7 @@ #include "GraphicsContext.h" #include "Image.h" #include "ImageData.h" -#include "JPEGEncoder.h" #include "NotImplemented.h" -#include "PNGEncoder.h" #include "SharedBitmap.h" #include "UnusedParam.h" #include <wtf/UnusedParam.h> @@ -250,28 +248,8 @@ String ImageBuffer::toDataURL(const String& mimeType, const double*) const if (!m_data.m_bitmap->bytes()) return "data:,"; - Vector<char> output; - const char* header; - if (mimeType.lower() == "image/png") { - if (!compressBitmapToPng(m_data.m_bitmap.get(), output)) - return "data:,"; - header = "data:image/png;base64,"; - } else { - if (!compressBitmapToJpeg(m_data.m_bitmap.get(), output)) - return "data:,"; - header = "data:image/jpeg;base64,"; - } - - Vector<char> base64; - base64Encode(output, base64); - - output.clear(); - - Vector<char> url; - url.append(header, strlen(header)); - url.append(base64); - - return String(url.data(), url.size()); + notImplemented(); + return String(); } -} +} // namespace WebCore diff --git a/WebCore/platform/graphics/wince/ImageWinCE.cpp b/WebCore/platform/graphics/wince/ImageWinCE.cpp new file mode 100644 index 0000000..61ec954 --- /dev/null +++ b/WebCore/platform/graphics/wince/ImageWinCE.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007-2009 Torch Mobile Inc. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Image.h" + +#include "BitmapImage.h" +#include "GraphicsContext.h" +#include "ImageDecoder.h" +#include "NotImplemented.h" +#include "PlatformString.h" +#include "SharedBuffer.h" +#include "TransformationMatrix.h" +#include "WinceGraphicsExtras.h" +#include <wtf/OwnPtr.h> + +#include <windows.h> + +namespace WebCore { + +NativeImagePtr RGBA32Buffer::asNewNativeImage() const +{ + NativeImagePtr image = SharedBitmap::createInstance(false, width(), height(), false); + + memcpy(image->bytes(), m_bytes.data(), m_bytes.size() * sizeof(PixelData)); + + return image; +} + +bool FrameData::clear(bool clearMetaData) +{ + if (clearMetaData) + m_haveMetadata = false; + + if (m_frame) { + m_frame = 0; + return true; + } + + return false; +} + +bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size) +{ + if (!bmp) + return false; + + BITMAP bmpInfo; + GetObject(bmp, sizeof(BITMAP), &bmpInfo); + + ASSERT(bmpInfo.bmBitsPixel == 32); + int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight; + + OwnPtr<HDC> hdc(CreateCompatibleDC(0)); + HGDIOBJ hOldBmp = SelectObject(hdc.get(), bmp); + + { + GraphicsContext gc(hdc.get()); + + IntSize imageSize = BitmapImage::size(); + if (size) + drawFrameMatchingSourceSize(&gc, FloatRect(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), DeviceColorSpace, CompositeCopy); + else + draw(&gc, FloatRect(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0, 0, imageSize.width(), imageSize.height()), DeviceColorSpace, CompositeCopy); + } + + SelectObject(hdc.get(), hOldBmp); + + return true; +} + +void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator compositeOp) +{ + int frames = frameCount(); + for (int i = 0; i < frames; ++i) { + RefPtr<SharedBitmap> bmp = frameAtIndex(i); + if (!bmp || bmp->height() != static_cast<unsigned>(srcSize.height()) || bmp->width() != static_cast<unsigned>(srcSize.width())) + continue; + + size_t currentFrame = m_currentFrame; + m_currentFrame = i; + draw(ctxt, dstRect, FloatRect(0, 0, srcSize.width(), srcSize.height()), styleColorSpace, compositeOp); + m_currentFrame = currentFrame; + return; + } + + // No image of the correct size was found, fallback to drawing the current frame + IntSize imageSize = BitmapImage::size(); + draw(ctxt, dstRect, FloatRect(0, 0, imageSize.width(), imageSize.height()), styleColorSpace, compositeOp); +} + +void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRectIn, ColorSpace styleColorSpace, CompositeOperator compositeOp) +{ + if (!m_source.initialized()) + return; + + if (mayFillWithSolidColor()) + fillWithSolidColor(ctxt, dstRect, solidColor(), styleColorSpace, compositeOp); + else { + IntRect intSrcRect(srcRectIn); + RefPtr<SharedBitmap> bmp = frameAtIndex(m_currentFrame); + + if (bmp->width() != m_source.size().width()) { + double scaleFactor = static_cast<double>(bmp->width()) / m_source.size().width(); + + intSrcRect.setX(stableRound(srcRectIn.x() * scaleFactor)); + intSrcRect.setWidth(stableRound(srcRectIn.width() * scaleFactor)); + intSrcRect.setY(stableRound(srcRectIn.y() * scaleFactor)); + intSrcRect.setHeight(stableRound(srcRectIn.height() * scaleFactor)); + } + bmp->draw(ctxt, enclosingIntRect(dstRect), intSrcRect, styleColorSpace, compositeOp); + } + + startAnimation(); +} + +void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) +{ + notImplemented(); +} + +void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) +{ + RefPtr<SharedBitmap> bmp = nativeImageForCurrentFrame(); + if (!bmp) + return; + + bmp->drawPattern(ctxt, tileRectIn, patternTransform, phase, styleColorSpace, op, destRect, m_source.size()); +} + +void BitmapImage::checkForSolidColor() +{ + if (m_checkedForSolidColor) + return; + + if (frameCount() != 1) { + m_isSolidColor = false; + m_checkedForSolidColor = true; + return; + } + + RefPtr<SharedBitmap> bmp = frameAtIndex(0); + if (!bmp || !bmp->validHeight()) { + m_isSolidColor = false; + return; + } + + if (bmp->width() != 1 || bmp->validHeight() != 1) { + m_isSolidColor = false; + m_checkedForSolidColor = true; + return; + } + + m_isSolidColor = true; + + if (bmp->is16bit()) { + unsigned short c = ((unsigned short *)bmp->bytes())[0]; + int r = (c >> 7) & 0xF8; + int g = (c >> 2) & 0xF8; + int b = (c << 3) & 0xF8; + if (bmp->usesTransparentColor() && bmp->transparentColor() == RGB(r, g, b)) + m_solidColor = Color(r, g, b, 0); + else + m_solidColor = Color(r, g, b); + } else { + unsigned c = ((unsigned *)bmp->bytes())[0]; + m_solidColor = Color(c); + } + + if (bmp->validHeight() == bmp->height()) + m_checkedForSolidColor = true; +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h b/WebCore/platform/graphics/wince/MediaPlayerPrivateWinCE.h index e86b8a9..f49d8e2 100644 --- a/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h +++ b/WebCore/platform/graphics/wince/MediaPlayerPrivateWinCE.h @@ -24,8 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MediaPlayerPrivateWince_h -#define MediaPlayerPrivateWince_h +#ifndef MediaPlayerPrivateWinCE_h +#define MediaPlayerPrivateWinCE_h #if ENABLE(VIDEO) @@ -120,6 +120,6 @@ namespace WebCore { } -#endif +#endif // ENABLE(VIDEO) -#endif +#endif // MediaPlayerPrivateWinCE_h diff --git a/WebCore/platform/graphics/wince/PathWince.cpp b/WebCore/platform/graphics/wince/PathWinCE.cpp index 6aa2864..4f0195c 100644 --- a/WebCore/platform/graphics/wince/PathWince.cpp +++ b/WebCore/platform/graphics/wince/PathWinCE.cpp @@ -23,7 +23,7 @@ #include "AffineTransform.h" #include "FloatRect.h" #include "NotImplemented.h" -#include "PlatformPathWince.h" +#include "PlatformPathWinCE.h" #include "PlatformString.h" #include <wtf/OwnPtr.h> diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.cpp b/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp index b42b52c..4072a18 100644 --- a/WebCore/platform/graphics/wince/PlatformPathWince.cpp +++ b/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp @@ -18,14 +18,14 @@ */ #include "config.h" -#include "PlatformPathWince.h" +#include "PlatformPathWinCE.h" #include "AffineTransform.h" #include "FloatRect.h" #include "GraphicsContext.h" #include "Path.h" #include "PlatformString.h" -#include "WinceGraphicsExtras.h" +#include "WinCEGraphicsExtras.h" #include <wtf/MathExtras.h> #include <wtf/OwnPtr.h> @@ -33,7 +33,7 @@ namespace WebCore { -// Implemented in GraphicsContextWince.cpp +// Implemented in GraphicsContextWinCE.cpp void getEllipsePointByAngle(double angle, double a, double b, float& x, float& y); static void quadCurve(int segments, Vector<PathPoint>& pts, const PathPoint* control) diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.h b/WebCore/platform/graphics/wince/PlatformPathWinCE.h index 614e8c5..3414b04 100644 --- a/WebCore/platform/graphics/wince/PlatformPathWince.h +++ b/WebCore/platform/graphics/wince/PlatformPathWinCE.h @@ -17,8 +17,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef PlatformPathWince_h -#define PlatformPathWince_h +#ifndef PlatformPathWinCE_h +#define PlatformPathWinCE_h #include "FloatPoint.h" #include "FloatRect.h" @@ -180,4 +180,4 @@ namespace WebCore { } -#endif // PlatformPathWince_h +#endif // PlatformPathWinCE_h diff --git a/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp b/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp index 6c815fc..c8c5474 100644 --- a/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp +++ b/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp @@ -163,4 +163,4 @@ void SimpleFontData::platformCharWidthInit() m_maxCharWidth = (tm.tmMaxCharWidth * m_platformData.size() + 36) / 72; } -} +} // namespace WebCore diff --git a/WebCore/platform/graphics/wince/WinceGraphicsExtras.h b/WebCore/platform/graphics/wince/WinCEGraphicsExtras.h index 2a6fae1..4cab21c 100644 --- a/WebCore/platform/graphics/wince/WinceGraphicsExtras.h +++ b/WebCore/platform/graphics/wince/WinCEGraphicsExtras.h @@ -17,8 +17,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WinceGraphicsExtras_h -#define WinceGraphicsExtras_h +#ifndef WinCEGraphicsExtras_h +#define WinCEGraphicsExtras_h // This file is used to contain small utilities used by WINCE graphics code. @@ -36,4 +36,4 @@ namespace WebCore { } } -#endif WinceGraphicsExtras_h +#endif WinCEGraphicsExtras_h |