diff options
author | Teng-Hui Zhu <ztenghui@google.com> | 2010-11-10 15:31:59 -0800 |
---|---|---|
committer | Teng-Hui Zhu <ztenghui@google.com> | 2010-11-17 13:35:59 -0800 |
commit | 28040489d744e0c5d475a88663056c9040ed5320 (patch) | |
tree | c463676791e4a63e452a95f0a12b2a8519730693 /WebCore/platform | |
parent | eff9be92c41913c92fb1d3b7983c071f3e718678 (diff) | |
download | external_webkit-28040489d744e0c5d475a88663056c9040ed5320.zip external_webkit-28040489d744e0c5d475a88663056c9040ed5320.tar.gz external_webkit-28040489d744e0c5d475a88663056c9040ed5320.tar.bz2 |
Merge WebKit at r71558: Initial merge by git.
Change-Id: Ib345578fa29df7e4bc72b4f00e4a6fddcb754c4c
Diffstat (limited to 'WebCore/platform')
127 files changed, 4197 insertions, 2122 deletions
diff --git a/WebCore/platform/AsyncFileSystem.cpp b/WebCore/platform/AsyncFileSystem.cpp index 57305ff..b85a487 100644 --- a/WebCore/platform/AsyncFileSystem.cpp +++ b/WebCore/platform/AsyncFileSystem.cpp @@ -53,7 +53,7 @@ PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create(const String&) } // Default implementation. -void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, Type type, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) +void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, Type type, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) { String typeString = (type == Persistent) ? "Persistent" : "Temporary"; diff --git a/WebCore/platform/AsyncFileSystem.h b/WebCore/platform/AsyncFileSystem.h index 3104ebc..d96c1ad 100644 --- a/WebCore/platform/AsyncFileSystem.h +++ b/WebCore/platform/AsyncFileSystem.h @@ -66,8 +66,8 @@ public: // Creates and returns a new platform-specific AsyncFileSystem instance if the platform has its own implementation. static PassOwnPtr<AsyncFileSystem> create(const String& rootPath); - // Opens a new file system. - static void openFileSystem(const String& basePath, const String& storageIdentifier, Type, PassOwnPtr<AsyncFileSystemCallbacks>); + // Opens a new file system. The create parameter specifies whether or not to create the path if it does not already exists. + static void openFileSystem(const String& basePath, const String& storageIdentifier, Type, bool create, PassOwnPtr<AsyncFileSystemCallbacks>); // Moves a file or directory from srcPath to destPath. // AsyncFileSystemCallbacks::didSucceed() is called when the operation is completed successfully. @@ -128,6 +128,9 @@ public: // Converts a given absolute virtual path to a platform path that starts with the platform root path of this file system. virtual String virtualToPlatformPath(const String& path) const; + // Getter for this file system's root path. + String root() const { return m_platformRootPath; } + protected: AsyncFileSystem(const String& platformRootPath) : m_platformRootPath(platformRootPath) diff --git a/WebCore/platform/ContextMenu.cpp b/WebCore/platform/ContextMenu.cpp index 369f9ce..93cdfdf 100644 --- a/WebCore/platform/ContextMenu.cpp +++ b/WebCore/platform/ContextMenu.cpp @@ -30,6 +30,7 @@ #if ENABLE(CONTEXT_MENUS) +#include "BackForwardController.h" #include "ContextMenuController.h" #include "ContextMenuClient.h" #include "CSSComputedStyleDeclaration.h" @@ -405,10 +406,10 @@ void ContextMenu::populate() #if ENABLE(INSPECTOR) if (!(frame->page() && frame->page()->inspectorController()->hasInspectorFrontendClient())) { #endif - if (frame->page() && frame->page()->canGoBackOrForward(-1)) + if (frame->page() && frame->page()->backForward()->canGoBackOrForward(-1)) appendItem(BackItem); - if (frame->page() && frame->page()->canGoBackOrForward(1)) + if (frame->page() && frame->page()->backForward()->canGoBackOrForward(1)) appendItem(ForwardItem); // use isLoadingInAPISense rather than isLoading because Stop/Reload are @@ -428,7 +429,7 @@ void ContextMenu::populate() } else { // Make an editing context menu SelectionController* selection = frame->selection(); bool inPasswordField = selection->isInPasswordField(); - bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledInFocusedNode(); + bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledFor(node); if (!inPasswordField && spellCheckingEnabled) { // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range @@ -783,10 +784,10 @@ void ContextMenu::checkOrEnableIfNeeded(ContextMenuItem& item) const #endif #if PLATFORM(GTK) case ContextMenuItemTagGoBack: - shouldEnable = frame->page() && frame->page()->canGoBackOrForward(-1); + shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(-1); break; case ContextMenuItemTagGoForward: - shouldEnable = frame->page() && frame->page()->canGoBackOrForward(1); + shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(1); break; case ContextMenuItemTagStop: shouldEnable = frame->loader()->documentLoader()->isLoadingInAPISense(); diff --git a/WebCore/platform/ContextMenu.h b/WebCore/platform/ContextMenu.h index ca21f29..2a2a017 100644 --- a/WebCore/platform/ContextMenu.h +++ b/WebCore/platform/ContextMenu.h @@ -91,6 +91,8 @@ namespace WebCore { #endif }; +Vector<ContextMenuItem> contextMenuItemVector(PlatformMenuDescription); + } #endif // ContextMenu_h diff --git a/WebCore/platform/FileSystem.h b/WebCore/platform/FileSystem.h index e3916cf..32ab417 100644 --- a/WebCore/platform/FileSystem.h +++ b/WebCore/platform/FileSystem.h @@ -144,6 +144,7 @@ static const char PlatformFilePathSeparator = '\\'; static const char PlatformFilePathSeparator = '/'; #endif +void revealFolderInOS(const String&); bool fileExists(const String&); bool deleteFile(const String&); bool deleteEmptyDirectory(const String&); diff --git a/WebCore/platform/HostWindow.h b/WebCore/platform/HostWindow.h index b0ee653..7882d48 100644 --- a/WebCore/platform/HostWindow.h +++ b/WebCore/platform/HostWindow.h @@ -48,7 +48,12 @@ public: // Requests the host invalidate the contents, not the window. This is the slow path for scrolling. virtual void invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate) = 0; - + +#if ENABLE(TILED_BACKING_STORE) + // Requests the host to do the actual scrolling. This is only used in combination with a tiled backing store. + virtual void delegatedScrollRequested(const IntSize& scrollDelta) = 0; +#endif + // Methods for doing coordinate conversions to and from screen coordinates. virtual IntPoint screenToWindow(const IntPoint&) const = 0; virtual IntRect windowToScreen(const IntRect&) const = 0; diff --git a/WebCore/platform/PurgePriority.h b/WebCore/platform/PurgePriority.h new file mode 100644 index 0000000..6a2894e --- /dev/null +++ b/WebCore/platform/PurgePriority.h @@ -0,0 +1,39 @@ +/* + * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PurgePriority_h +#define PurgePriority_h + +namespace WebCore { + +enum PurgePriority { + PurgeLast, + PurgeMiddle, + PurgeFirst, + PurgeDefault = PurgeMiddle +}; + +} + +#endif // PurgePriority_h diff --git a/WebCore/platform/PurgeableBuffer.h b/WebCore/platform/PurgeableBuffer.h index 32341c2..9bda2d5 100644 --- a/WebCore/platform/PurgeableBuffer.h +++ b/WebCore/platform/PurgeableBuffer.h @@ -26,6 +26,7 @@ #ifndef PurgeableBuffer_h #define PurgeableBuffer_h +#include "PurgePriority.h" #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> @@ -35,7 +36,6 @@ namespace WebCore { class PurgeableBuffer : public Noncopyable { public: static PassOwnPtr<PurgeableBuffer> create(const char* data, size_t); - static PassOwnPtr<PurgeableBuffer> create(const Vector<char>& vector) { return create(vector.data(), vector.size()); } ~PurgeableBuffer(); @@ -43,9 +43,8 @@ namespace WebCore { const char* data() const; size_t size() const { return m_size; } - enum PurgePriority { PurgeLast, PurgeMiddle, PurgeFirst, PurgeDefault = PurgeMiddle }; PurgePriority purgePriority() const { return m_purgePriority; } - void setPurgePriority(PurgePriority); + void setPurgePriority(PurgePriority priority) { m_purgePriority = priority; } bool isPurgeable() const { return m_state != NonVolatile; } bool wasPurged() const; @@ -67,7 +66,6 @@ namespace WebCore { inline PassOwnPtr<PurgeableBuffer> PurgeableBuffer::create(const char*, size_t) { return PassOwnPtr<PurgeableBuffer>(); } inline PurgeableBuffer::~PurgeableBuffer() { } inline const char* PurgeableBuffer::data() const { return 0; } - inline void PurgeableBuffer::setPurgePriority(PurgePriority) { } inline bool PurgeableBuffer::wasPurged() const { return false; } inline bool PurgeableBuffer::makePurgeable(bool) { return false; } #endif diff --git a/WebCore/platform/ScrollView.cpp b/WebCore/platform/ScrollView.cpp index 5f745b8..40d598e 100644 --- a/WebCore/platform/ScrollView.cpp +++ b/WebCore/platform/ScrollView.cpp @@ -362,6 +362,13 @@ void ScrollView::setScrollPosition(const IntPoint& scrollPoint) IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition()); newScrollPosition.clampNegativeToZero(); +#if ENABLE(TILED_BACKING_STORE) + if (delegatesScrolling()) { + hostWindow()->delegatedScrollRequested(IntSize(scrollPoint.x(), scrollPoint.y())); + return; + } +#endif + if (newScrollPosition == scrollPosition()) return; diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h index 739e1ac..7fb5d8e 100644 --- a/WebCore/platform/ScrollView.h +++ b/WebCore/platform/ScrollView.h @@ -104,6 +104,7 @@ public: virtual void setCanHaveScrollbars(bool); bool canHaveScrollbars() const { return horizontalScrollbarMode() != ScrollbarAlwaysOff || verticalScrollbarMode() != ScrollbarAlwaysOff; } + virtual bool delegatesScrolling() { return false; } virtual bool avoidScrollbarCreation() { return false; } // By default you only receive paint events for the area that is visible. In the case of using a diff --git a/WebCore/platform/UUID.cpp b/WebCore/platform/UUID.cpp index 5208bee..eb721e0 100644 --- a/WebCore/platform/UUID.cpp +++ b/WebCore/platform/UUID.cpp @@ -39,9 +39,6 @@ #if OS(WINDOWS) #include <objbase.h> -#ifndef ARRAYSIZE -#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0])) -#endif #elif OS(DARWIN) #include <CoreFoundation/CoreFoundation.h> #elif OS(LINUX) && !PLATFORM(CHROMIUM) @@ -69,7 +66,7 @@ String createCanonicalUUIDString() if (FAILED(hr)) return String(); wchar_t uuidStr[40]; - int num = StringFromGUID2(uuid, reinterpret_cast<LPOLESTR>(uuidStr), ARRAYSIZE(uuidStr)); + int num = StringFromGUID2(uuid, reinterpret_cast<LPOLESTR>(uuidStr), WTF_ARRAY_LENGTH(uuidStr)); ASSERT(num == 39); String canonicalUuidStr = String(uuidStr + 1, num - 3).lower(); // remove opening and closing bracket and make it lower. ASSERT(canonicalUuidStr[uuidVersionIdentifierIndex] == uuidVersionRequired); diff --git a/WebCore/platform/android/LanguageAndroid.cpp b/WebCore/platform/android/LanguageAndroid.cpp new file mode 100644 index 0000000..52e614d --- /dev/null +++ b/WebCore/platform/android/LanguageAndroid.cpp @@ -0,0 +1,42 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "Language.h" + +#include "PlatformBridge.h" +#include "PlatformString.h" + +namespace WebCore { + +// This function is used by Javascript to find out what the default language +// the user has selected. It is used by the JS object Navigator.language +// I guess this information should be mapped with the Accept-Language: HTTP header. +String platformDefaultLanguage() +{ + return PlatformBridge::computeDefaultLanguage(); +} + +} // namespace WebCore diff --git a/WebCore/platform/android/PlatformBridge.h b/WebCore/platform/android/PlatformBridge.h index 334629b..3098d6c 100644 --- a/WebCore/platform/android/PlatformBridge.h +++ b/WebCore/platform/android/PlatformBridge.h @@ -108,6 +108,7 @@ public: static bool cookiesEnabled(const Document*); // Plugin static NPObject* pluginScriptableObject(Widget*); +<<<<<<< HEAD // Popups static bool popupsAllowed(NPP); @@ -139,6 +140,10 @@ public: // Updates the layers on the UI static void updateLayers(FrameView* view); +======= + // Language + static String computeDefaultLanguage(); +>>>>>>> webkit.org at r71558 }; } diff --git a/WebCore/platform/android/TemporaryLinkStubs.cpp b/WebCore/platform/android/TemporaryLinkStubs.cpp index cf8aacf..b1c0276 100644 --- a/WebCore/platform/android/TemporaryLinkStubs.cpp +++ b/WebCore/platform/android/TemporaryLinkStubs.cpp @@ -92,6 +92,7 @@ using namespace WebCore; /* Completely empty stubs (mostly to allow DRT to run): */ /********************************************************/ +<<<<<<< HEAD // This function is used by Javascript to find out what the default language // the user has selected. It is used by the JS object Navigator.language // I guess this information should be mapped with the Accept-Language: HTTP header. @@ -101,6 +102,8 @@ String WebCore::platformDefaultLanguage() return "en"; } +======= +>>>>>>> webkit.org at r71558 namespace WebCore { // This function tells the bridge that a resource was loaded from the cache and thus diff --git a/WebCore/platform/animation/Animation.h b/WebCore/platform/animation/Animation.h index 1541b4d..d16f74c 100644 --- a/WebCore/platform/animation/Animation.h +++ b/WebCore/platform/animation/Animation.h @@ -93,7 +93,7 @@ public: enum { IterationCountInfinite = -1 }; int iterationCount() const { return m_iterationCount; } const String& name() const { return m_name; } - unsigned playState() const { return m_playState; } + EAnimPlayState playState() const { return static_cast<EAnimPlayState>(m_playState); } int property() const { return m_property; } const PassRefPtr<TimingFunction> timingFunction() const { return m_timingFunction; } @@ -103,7 +103,7 @@ public: void setFillMode(unsigned f) { m_fillMode = f; m_fillModeSet = true; } void setIterationCount(int c) { m_iterationCount = c; m_iterationCountSet = true; } void setName(const String& n) { m_name = n; m_nameSet = true; } - void setPlayState(unsigned d) { m_playState = d; m_playStateSet = true; } + void setPlayState(EAnimPlayState d) { m_playState = d; m_playStateSet = true; } void setProperty(int t) { m_property = t; m_propertySet = true; } void setTimingFunction(PassRefPtr<TimingFunction> f) { m_timingFunction = f; m_timingFunctionSet = true; } @@ -155,7 +155,7 @@ public: static unsigned initialAnimationFillMode() { return AnimationFillModeNone; } static int initialAnimationIterationCount() { return 1; } static String initialAnimationName() { return String("none"); } - static unsigned initialAnimationPlayState() { return AnimPlayStatePlaying; } + static EAnimPlayState initialAnimationPlayState() { return AnimPlayStatePlaying; } static int initialAnimationProperty() { return cAnimateAll; } static PassRefPtr<TimingFunction> initialAnimationTimingFunction() { return CubicBezierTimingFunction::create(); } }; diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h index 74bad04..55a4ce0 100644 --- a/WebCore/platform/chromium/ChromiumBridge.h +++ b/WebCore/platform/chromium/ChromiumBridge.h @@ -121,6 +121,7 @@ namespace WebCore { static void prefetchDNS(const String& hostname); // File --------------------------------------------------------------- + static void revealFolderInOS(const String&); static bool fileExists(const String&); static bool deleteFile(const String&); static bool deleteEmptyDirectory(const String&); diff --git a/WebCore/platform/chromium/FileSystemChromium.cpp b/WebCore/platform/chromium/FileSystemChromium.cpp index 975caf6..d8a1e3f 100644 --- a/WebCore/platform/chromium/FileSystemChromium.cpp +++ b/WebCore/platform/chromium/FileSystemChromium.cpp @@ -57,6 +57,11 @@ bool getFileModificationTime(const String& path, time_t& result) return ChromiumBridge::getFileModificationTime(path, result); } +void revealFolderInOS(const String& path) +{ + ChromiumBridge::revealFolderInOS(path); +} + String directoryName(const String& path) { return ChromiumBridge::directoryName(path); diff --git a/WebCore/platform/chromium/PopupMenuChromium.cpp b/WebCore/platform/chromium/PopupMenuChromium.cpp index 3c807ba..3ff4ff0 100644 --- a/WebCore/platform/chromium/PopupMenuChromium.cpp +++ b/WebCore/platform/chromium/PopupMenuChromium.cpp @@ -927,15 +927,16 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd // Prepare text to be drawn. String itemText = m_popupClient->itemText(rowIndex); String itemLabel = m_popupClient->itemLabel(rowIndex); + String itemIcon = m_popupClient->itemIcon(rowIndex); if (m_settings.restrictWidthOfListBox) { // Truncate strings to fit in. // FIXME: We should leftTruncate for the rtl case. // StringTruncator::leftTruncate would have to be implemented. String str = StringTruncator::rightTruncate(itemText, maxWidth, itemFont); if (str != itemText) { itemText = str; - // Don't display the label, we already don't have enough room for the - // item text. + // Don't display the label or icon, we already don't have enough room for the item text. itemLabel = ""; + itemIcon = ""; } else if (!itemLabel.isEmpty()) { int availableWidth = maxWidth - kTextToLabelPadding - StringTruncator::width(itemText, itemFont); @@ -966,7 +967,6 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd int remainingWidth = rowRect.width() - rightPadding; // Draw the icon if applicable. - String itemIcon = m_popupClient->itemIcon(rowIndex); RefPtr<Image> image(Image::loadPlatformResource(itemIcon.utf8().data())); if (image && !image->isNull()) { IntRect imageRect = image->rect(); @@ -1089,7 +1089,13 @@ int PopupListBox::getRowHeight(int index) if (index < 0) return 0; - return getRowFont(index).height(); + String icon = m_popupClient->itemIcon(index); + RefPtr<Image> image(Image::loadPlatformResource(icon.utf8().data())); + + int fontHeight = getRowFont(index).height(); + int iconHeight = (image && !image->isNull()) ? image->rect().height() : 0; + + return max(fontHeight, iconHeight); } IntRect PopupListBox::getRowBounds(int index) @@ -1257,6 +1263,8 @@ void PopupListBox::layout() // Ensure the popup is wide enough to fit this item. String text = m_popupClient->itemText(i); String label = m_popupClient->itemLabel(i); + String icon = m_popupClient->itemIcon(i); + RefPtr<Image> iconImage(Image::loadPlatformResource(icon.utf8().data())); int width = 0; if (!text.isEmpty()) width = itemFont.width(TextRun(text)); @@ -1265,6 +1273,12 @@ void PopupListBox::layout() width += kTextToLabelPadding; width += itemFont.width(TextRun(label)); } + if (iconImage && !iconImage->isNull()) { + if (width > 0) + width += kLabelToIconPadding; + width += iconImage->rect().width(); + } + baseWidth = max(baseWidth, width); // FIXME: http://b/1210481 We should get the padding of individual option elements. paddingWidth = max(paddingWidth, diff --git a/WebCore/platform/graphics/Extensions3D.h b/WebCore/platform/graphics/Extensions3D.h new file mode 100644 index 0000000..0aed8e7 --- /dev/null +++ b/WebCore/platform/graphics/Extensions3D.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Extensions3D_h +#define Extensions3D_h + +#include <wtf/text/WTFString.h> + +namespace WebCore { + +// This is a base class containing only pure virtual functions. +// Implementations must provide a subclass. +// +// The supported extensions are defined below and in subclasses, +// possibly platform-specific ones. +// +// Calling any extension function not supported by the current context +// must be a no-op; in particular, it may not have side effects. In +// this situation, if the function has a return value, 0 is returned. +class Extensions3D { +public: + virtual ~Extensions3D() {} + + // Supported extensions: + // GL_EXT_texture_format_BGRA8888 + // GL_EXT_read_format_bgra + // GL_ARB_robustness + // GL_EXT_packed_depth_stencil / GL_OES_packed_depth_stencil + + // Takes full name of extension; for example, + // "GL_EXT_texture_format_BGRA8888". + virtual bool supports(const String&) = 0; + + enum { + // GL_EXT_texture_format_BGRA8888 enums + BGRA_EXT = 0x80E1, + + // GL_ARB_robustness enums + GUILTY_CONTEXT_RESET_ARB = 0x8253, + INNOCENT_CONTEXT_RESET_ARB = 0x8254, + UNKNOWN_CONTEXT_RESET_ARB = 0x8255, + + // GL_EXT/OES_packed_depth_stencil enums + DEPTH24_STENCIL8 = 0x88F0 + }; + + // GL_ARB_robustness + virtual int getGraphicsResetStatusARB() = 0; +}; + +} // namespace WebCore + +#endif // Extensions3D_h diff --git a/WebCore/platform/graphics/FloatPoint3D.cpp b/WebCore/platform/graphics/FloatPoint3D.cpp index bb05e7f..ed1816b 100644 --- a/WebCore/platform/graphics/FloatPoint3D.cpp +++ b/WebCore/platform/graphics/FloatPoint3D.cpp @@ -38,10 +38,5 @@ void FloatPoint3D::normalize() } } -float FloatPoint3D::length() const -{ - return sqrtf(lengthSquared()); -} - } // namespace WebCore diff --git a/WebCore/platform/graphics/FloatPoint3D.h b/WebCore/platform/graphics/FloatPoint3D.h index 9ee548d..b6cbaa8 100644 --- a/WebCore/platform/graphics/FloatPoint3D.h +++ b/WebCore/platform/graphics/FloatPoint3D.h @@ -113,8 +113,8 @@ public: return result; } - float length() const; float lengthSquared() const { return this->dot(*this); } + float length() const { return sqrtf(lengthSquared()); } private: float m_x; diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp index ec15d26..52312a4 100644 --- a/WebCore/platform/graphics/GraphicsContext.cpp +++ b/WebCore/platform/graphics/GraphicsContext.cpp @@ -404,25 +404,27 @@ void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const th = image->height(); if (useLowQualityScale) { - save(); + InterpolationQuality previousInterpolationQuality = imageInterpolationQuality(); + // FIXME: Should be InterpolationLow setImageInterpolationQuality(InterpolationNone); - } - image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), styleColorSpace, op); - if (useLowQualityScale) - restore(); + image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), styleColorSpace, op); + setImageInterpolationQuality(previousInterpolationQuality); + } else + image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), styleColorSpace, op); } void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, bool useLowQualityScale) { if (paintingDisabled() || !image) return; + if (useLowQualityScale) { - save(); + InterpolationQuality previousInterpolationQuality = imageInterpolationQuality(); setImageInterpolationQuality(InterpolationLow); - } - image->drawTiled(this, rect, srcPoint, tileSize, styleColorSpace, op); - if (useLowQualityScale) - restore(); + image->drawTiled(this, rect, srcPoint, tileSize, styleColorSpace, op); + setImageInterpolationQuality(previousInterpolationQuality); + } else + image->drawTiled(this, rect, srcPoint, tileSize, styleColorSpace, op); } void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op, bool useLowQualityScale) @@ -430,17 +432,19 @@ void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, c if (paintingDisabled() || !image) return; - if (useLowQualityScale) { - save(); - setImageInterpolationQuality(InterpolationLow); - } - if (hRule == Image::StretchTile && vRule == Image::StretchTile) + if (hRule == Image::StretchTile && vRule == Image::StretchTile) { // Just do a scale. drawImage(image, styleColorSpace, dest, srcRect, op); - else + return; + } + + if (useLowQualityScale) { + InterpolationQuality previousInterpolationQuality = imageInterpolationQuality(); + setImageInterpolationQuality(InterpolationLow); + image->drawTiled(this, dest, srcRect, hRule, vRule, styleColorSpace, op); + setImageInterpolationQuality(previousInterpolationQuality); + } else image->drawTiled(this, dest, srcRect, hRule, vRule, styleColorSpace, op); - if (useLowQualityScale) - restore(); } void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op) @@ -484,14 +488,13 @@ void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorS th = image->height(); if (useLowQualityScale) { - save(); + InterpolationQuality previousInterpolationQuality = imageInterpolationQuality(); + // FIXME: Should be InterpolationLow setImageInterpolationQuality(InterpolationNone); - } - - image->draw(this, styleColorSpace, dest, src, op, useLowQualityScale); - - if (useLowQualityScale) - restore(); + image->draw(this, styleColorSpace, dest, src, op, useLowQualityScale); + setImageInterpolationQuality(previousInterpolationQuality); + } else + image->draw(this, styleColorSpace, dest, src, op, useLowQualityScale); } void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index b1fa48a..a91f3d3 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -40,7 +40,6 @@ #if PLATFORM(CG) typedef struct CGContext PlatformGraphicsContext; #elif PLATFORM(CAIRO) -#include "PlatformRefPtrCairo.h" namespace WebCore { class ContextShadow; } @@ -260,7 +259,6 @@ namespace WebCore { void clearRect(const FloatRect&); - void strokeRect(const FloatRect&); void strokeRect(const FloatRect&, float lineWidth); void drawImage(Image*, ColorSpace styleColorSpace, const IntPoint&, CompositeOperator = CompositeSourceOver); @@ -289,7 +287,6 @@ namespace WebCore { void addRoundedRectClip(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight); void addInnerRoundedRectClip(const IntRect&, int thickness); void clipOut(const IntRect&); - void clipOutEllipseInRect(const IntRect&); void clipOutRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight); void clipPath(WindRule); void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias = true); @@ -355,7 +352,6 @@ namespace WebCore { void rotate(float angleInRadians); void translate(const FloatSize& size) { translate(size.width(), size.height()); } void translate(float x, float y); - IntPoint origin(); void setURLForRect(const KURL&, const IntRect&); @@ -434,7 +430,6 @@ namespace WebCore { bool inTransparencyLayer() const; PlatformPath* currentPath(); void pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask); - QPen pen(); static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op); #endif diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp index b8c66d5..2a65128 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -132,13 +132,13 @@ bool GraphicsContext3D::extractImageData(ImageData* imageData, int dataBytes = width * height * 4; data.resize(dataBytes); if (!packPixels(imageData->data()->data()->data(), - kSourceFormatRGBA8, + SourceFormatRGBA8, width, height, 0, format, type, - premultiplyAlpha ? kAlphaDoPremultiply : kAlphaDoNothing, + premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing, data.data())) return false; if (flipY) { @@ -164,37 +164,37 @@ bool GraphicsContext3D::extractTextureData(unsigned int width, unsigned int heig Vector<uint8_t>& data) { // Assumes format, type, etc. have already been validated. - SourceDataFormat sourceDataFormat = kSourceFormatRGBA8; + SourceDataFormat sourceDataFormat = SourceFormatRGBA8; switch (type) { case UNSIGNED_BYTE: switch (format) { case RGBA: - sourceDataFormat = kSourceFormatRGBA8; + sourceDataFormat = SourceFormatRGBA8; break; case RGB: - sourceDataFormat = kSourceFormatRGB8; + sourceDataFormat = SourceFormatRGB8; break; case ALPHA: - sourceDataFormat = kSourceFormatA8; + sourceDataFormat = SourceFormatA8; break; case LUMINANCE: - sourceDataFormat = kSourceFormatR8; + sourceDataFormat = SourceFormatR8; break; case LUMINANCE_ALPHA: - sourceDataFormat = kSourceFormatRA8; + sourceDataFormat = SourceFormatRA8; break; default: ASSERT_NOT_REACHED(); } break; case UNSIGNED_SHORT_5_5_5_1: - sourceDataFormat = kSourceFormatRGBA5551; + sourceDataFormat = SourceFormatRGBA5551; break; case UNSIGNED_SHORT_4_4_4_4: - sourceDataFormat = kSourceFormatRGBA4444; + sourceDataFormat = SourceFormatRGBA4444; break; case UNSIGNED_SHORT_5_6_5: - sourceDataFormat = kSourceFormatRGB565; + sourceDataFormat = SourceFormatRGB565; break; default: ASSERT_NOT_REACHED(); @@ -213,7 +213,7 @@ bool GraphicsContext3D::extractTextureData(unsigned int width, unsigned int heig sourceDataFormat, width, height, unpackAlignment, format, type, - (premultiplyAlpha ? kAlphaDoPremultiply : kAlphaDoNothing), + (premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing), data.data())) return false; // The pixel data is now tightly packed. @@ -303,6 +303,14 @@ void unpackRGB16BigToRGBA8(const uint16_t* source, uint8_t* destination) destination[3] = 0xFF; } +void unpackBGR8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[2]; + destination[1] = source[1]; + destination[2] = source[0]; + destination[3] = 0xFF; +} + void unpackARGB8ToRGBA8(const uint8_t* source, uint8_t* destination) { destination[0] = source[1]; @@ -327,6 +335,14 @@ void unpackARGB16BigToRGBA8(const uint16_t* source, uint8_t* destination) destination[3] = convertColor16BigTo8(source[0]); } +void unpackABGR8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[3]; + destination[1] = source[2]; + destination[2] = source[1]; + destination[3] = source[0]; +} + void unpackBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination) { destination[0] = source[2]; @@ -566,7 +582,7 @@ void packRGBA8ToRGB8Unmultiply(const uint8_t* source, uint8_t* destination) destination[2] = sourceB; } -// This is only used when the source format is different than kSourceFormatRGBA8. +// This is only used when the source format is different than SourceFormatRGBA8. void packRGBA8ToRGBA8(const uint8_t* source, uint8_t* destination) { destination[0] = source[0]; @@ -772,7 +788,7 @@ static void doPacking(const void* sourceData, unsigned int destinationElementsPerPixel) { switch (sourceDataFormat) { - case GraphicsContext3D::kSourceFormatRGBA8: { + case GraphicsContext3D::SourceFormatRGBA8: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); if (!sourceElementsPerRow) { @@ -789,157 +805,169 @@ static void doPacking(const void* sourceData, } break; } - case GraphicsContext3D::kSourceFormatRGBA16Little: { + case GraphicsContext3D::SourceFormatRGBA16Little: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackRGBA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatRGBA16Big: { + case GraphicsContext3D::SourceFormatRGBA16Big: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackRGBA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatRGB8: { + case GraphicsContext3D::SourceFormatRGB8: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint8_t>(width, 3, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint8_t, DestType, unpackRGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatRGB16Little: { + case GraphicsContext3D::SourceFormatRGB16Little: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 6, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackRGB16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatRGB16Big: { + case GraphicsContext3D::SourceFormatRGB16Big: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 6, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackRGB16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatARGB8: { + case GraphicsContext3D::SourceFormatBGR8: { + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint8_t>(width, 3, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint8_t, DestType, unpackBGR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); + break; + } + case GraphicsContext3D::SourceFormatARGB8: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint8_t, DestType, unpackARGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatARGB16Little: { + case GraphicsContext3D::SourceFormatARGB16Little: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackARGB16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatARGB16Big: { + case GraphicsContext3D::SourceFormatARGB16Big: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackARGB16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatBGRA8: { + case GraphicsContext3D::SourceFormatABGR8: { + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint8_t, DestType, unpackABGR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); + break; + } + case GraphicsContext3D::SourceFormatBGRA8: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint8_t, DestType, unpackBGRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatBGRA16Little: { + case GraphicsContext3D::SourceFormatBGRA16Little: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackBGRA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatBGRA16Big: { + case GraphicsContext3D::SourceFormatBGRA16Big: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackBGRA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatRGBA5551: { + case GraphicsContext3D::SourceFormatRGBA5551: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackRGBA5551ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatRGBA4444: { + case GraphicsContext3D::SourceFormatRGBA4444: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackRGBA4444ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatRGB565: { + case GraphicsContext3D::SourceFormatRGB565: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackRGB565ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatR8: { + case GraphicsContext3D::SourceFormatR8: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint8_t>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint8_t, DestType, unpackR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatR16Little: { + case GraphicsContext3D::SourceFormatR16Little: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackR16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatR16Big: { + case GraphicsContext3D::SourceFormatR16Big: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackR16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatRA8: { + case GraphicsContext3D::SourceFormatRA8: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint8_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint8_t, DestType, unpackRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatRA16Little: { + case GraphicsContext3D::SourceFormatRA16Little: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackRA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatRA16Big: { + case GraphicsContext3D::SourceFormatRA16Big: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackRA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatAR8: { + case GraphicsContext3D::SourceFormatAR8: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint8_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint8_t, DestType, unpackAR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatAR16Little: { + case GraphicsContext3D::SourceFormatAR16Little: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackAR16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatAR16Big: { + case GraphicsContext3D::SourceFormatAR16Big: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackAR16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatA8: { + case GraphicsContext3D::SourceFormatA8: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint8_t>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint8_t, DestType, unpackA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatA16Little: { + case GraphicsContext3D::SourceFormatA16Little: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } - case GraphicsContext3D::kSourceFormatA16Big: { + case GraphicsContext3D::SourceFormatA16Big: { unsigned int sourceElementsPerPixel, sourceElementsPerRow; computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); doUnpackingAndPacking<uint16_t, DestType, unpackA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); @@ -963,7 +991,7 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, switch (destinationType) { case UNSIGNED_BYTE: { uint8_t* destination = static_cast<uint8_t*>(destinationData); - if (sourceDataFormat == kSourceFormatRGBA8 && destinationFormat == RGBA && sourceUnpackAlignment <= 4 && alphaOp == kAlphaDoNothing) { + if (sourceDataFormat == SourceFormatRGBA8 && destinationFormat == RGBA && sourceUnpackAlignment <= 4 && alphaOp == AlphaDoNothing) { // No conversion necessary. memcpy(destinationData, sourceData, width * height * 4); break; @@ -971,27 +999,27 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, switch (destinationFormat) { case RGB: switch (alphaOp) { - case kAlphaDoNothing: + case AlphaDoNothing: doPacking<uint8_t, packRGBA8ToRGB8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3); break; - case kAlphaDoPremultiply: + case AlphaDoPremultiply: doPacking<uint8_t, packRGBA8ToRGB8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3); break; - case kAlphaDoUnmultiply: + case AlphaDoUnmultiply: doPacking<uint8_t, packRGBA8ToRGB8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3); break; } break; case RGBA: switch (alphaOp) { - case kAlphaDoNothing: - ASSERT(sourceDataFormat != kSourceFormatRGBA8 || sourceUnpackAlignment > 4); // Handled above with fast case. + case AlphaDoNothing: + ASSERT(sourceDataFormat != SourceFormatRGBA8 || sourceUnpackAlignment > 4); // Handled above with fast case. doPacking<uint8_t, packRGBA8ToRGBA8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4); break; - case kAlphaDoPremultiply: + case AlphaDoPremultiply: doPacking<uint8_t, packRGBA8ToRGBA8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4); break; - case kAlphaDoUnmultiply: + case AlphaDoUnmultiply: doPacking<uint8_t, packRGBA8ToRGBA8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4); break; default: @@ -1009,13 +1037,13 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, // specification, Table 3.15), the red channel is chosen // from the RGBA data. switch (alphaOp) { - case kAlphaDoNothing: + case AlphaDoNothing: doPacking<uint8_t, packRGBA8ToR8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; - case kAlphaDoPremultiply: + case AlphaDoPremultiply: doPacking<uint8_t, packRGBA8ToR8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; - case kAlphaDoUnmultiply: + case AlphaDoUnmultiply: doPacking<uint8_t, packRGBA8ToR8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; } @@ -1025,13 +1053,13 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, // specification, Table 3.15), the red and alpha channels // are chosen from the RGBA data. switch (alphaOp) { - case kAlphaDoNothing: + case AlphaDoNothing: doPacking<uint8_t, packRGBA8ToRA8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2); break; - case kAlphaDoPremultiply: + case AlphaDoPremultiply: doPacking<uint8_t, packRGBA8ToRA8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2); break; - case kAlphaDoUnmultiply: + case AlphaDoUnmultiply: doPacking<uint8_t, packRGBA8ToRA8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2); break; } @@ -1042,13 +1070,13 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, case UNSIGNED_SHORT_4_4_4_4: { uint16_t* destination = static_cast<uint16_t*>(destinationData); switch (alphaOp) { - case kAlphaDoNothing: + case AlphaDoNothing: doPacking<uint16_t, packRGBA8ToUnsignedShort4444>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; - case kAlphaDoPremultiply: + case AlphaDoPremultiply: doPacking<uint16_t, packRGBA8ToUnsignedShort4444Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; - case kAlphaDoUnmultiply: + case AlphaDoUnmultiply: doPacking<uint16_t, packRGBA8ToUnsignedShort4444Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; } @@ -1057,13 +1085,13 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, case UNSIGNED_SHORT_5_5_5_1: { uint16_t* destination = static_cast<uint16_t*>(destinationData); switch (alphaOp) { - case kAlphaDoNothing: + case AlphaDoNothing: doPacking<uint16_t, packRGBA8ToUnsignedShort5551>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; - case kAlphaDoPremultiply: + case AlphaDoPremultiply: doPacking<uint16_t, packRGBA8ToUnsignedShort5551Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; - case kAlphaDoUnmultiply: + case AlphaDoUnmultiply: doPacking<uint16_t, packRGBA8ToUnsignedShort5551Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; } @@ -1072,13 +1100,13 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, case UNSIGNED_SHORT_5_6_5: { uint16_t* destination = static_cast<uint16_t*>(destinationData); switch (alphaOp) { - case kAlphaDoNothing: + case AlphaDoNothing: doPacking<uint16_t, packRGBA8ToUnsignedShort565>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; - case kAlphaDoPremultiply: + case AlphaDoPremultiply: doPacking<uint16_t, packRGBA8ToUnsignedShort565Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; - case kAlphaDoUnmultiply: + case AlphaDoUnmultiply: doPacking<uint16_t, packRGBA8ToUnsignedShort565Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; } @@ -1088,55 +1116,6 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, return true; } -#if !PLATFORM(CHROMIUM) -bool GraphicsContext3D::supportsBGRA() -{ - // For OpenGL ES2.0, this requires checking for - // GL_EXT_texture_format_BGRA8888 and GL_EXT_read_format_bgra. - // For desktop GL, BGRA has been supported since OpenGL 1.2. - - // However, note that the GL ES2 extension requires the internalFormat to - // glTexImage2D() be GL_BGRA, while desktop GL will not accept GL_BGRA - // (must be GL_RGBA), so this must be checked on each platform. - // 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 #endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index 20b4e2d..e34a2f8 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -76,6 +76,10 @@ const Platform3DObject NullPlatform3DObject = 0; namespace WebCore { class CanvasRenderingContext; class DrawingBuffer; +class Extensions3D; +#if PLATFORM(MAC) +class Extensions3DOpenGL; +#endif class HostWindow; class Image; class ImageData; @@ -347,8 +351,6 @@ public: VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A, VERTEX_ATTRIB_ARRAY_POINTER = 0x8645, VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F, - IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A, - IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B, COMPILE_STATUS = 0x8B81, INFO_LOG_LENGTH = 0x8B84, SHADER_SOURCE_LENGTH = 0x8B88, @@ -401,19 +403,7 @@ public: // WebGL-specific enums UNPACK_FLIP_Y_WEBGL = 0x9240, UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241, - - // 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, - - // GL_ARB_robustness enums - GUILTY_CONTEXT_RESET_ARB = 0x8253, - INNOCENT_CONTEXT_RESET_ARB = 0x8254, - UNKNOWN_CONTEXT_RESET_ARB = 0x8255 - + CONTEXT_LOST_WEBGL = 0x9242, }; // Context creation attributes. @@ -424,6 +414,7 @@ public: , stencil(false) , antialias(true) , premultipliedAlpha(true) + , canRecoverFromContextLoss(true) { } @@ -432,6 +423,7 @@ public: bool stencil; bool antialias; bool premultipliedAlpha; + bool canRecoverFromContextLoss; }; enum RenderStyle { @@ -540,34 +532,36 @@ public: // uploading. This enum must be public because it is accessed // by non-member functions. enum SourceDataFormat { - kSourceFormatRGBA8 = 0, - kSourceFormatRGBA16Little, - kSourceFormatRGBA16Big, - kSourceFormatRGB8, - kSourceFormatRGB16Little, - kSourceFormatRGB16Big, - kSourceFormatBGRA8, - kSourceFormatBGRA16Little, - kSourceFormatBGRA16Big, - kSourceFormatARGB8, - kSourceFormatARGB16Little, - kSourceFormatARGB16Big, - kSourceFormatRGBA5551, - kSourceFormatRGBA4444, - kSourceFormatRGB565, - kSourceFormatR8, - kSourceFormatR16Little, - kSourceFormatR16Big, - kSourceFormatRA8, - kSourceFormatRA16Little, - kSourceFormatRA16Big, - kSourceFormatAR8, - kSourceFormatAR16Little, - kSourceFormatAR16Big, - kSourceFormatA8, - kSourceFormatA16Little, - kSourceFormatA16Big, - kSourceFormatNumFormats + SourceFormatRGBA8 = 0, + SourceFormatRGBA16Little, + SourceFormatRGBA16Big, + SourceFormatRGB8, + SourceFormatRGB16Little, + SourceFormatRGB16Big, + SourceFormatBGR8, + SourceFormatBGRA8, + SourceFormatBGRA16Little, + SourceFormatBGRA16Big, + SourceFormatARGB8, + SourceFormatARGB16Little, + SourceFormatARGB16Big, + SourceFormatABGR8, + SourceFormatRGBA5551, + SourceFormatRGBA4444, + SourceFormatRGB565, + SourceFormatR8, + SourceFormatR16Little, + SourceFormatR16Big, + SourceFormatRA8, + SourceFormatRA16Little, + SourceFormatRA16Big, + SourceFormatAR8, + SourceFormatAR16Little, + SourceFormatAR16Big, + SourceFormatA8, + SourceFormatA16Little, + SourceFormatA16Big, + SourceFormatNumFormats }; //---------------------------------------------------------------------- @@ -786,22 +780,11 @@ 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); - - // GL_ARB_robustness - int getGraphicsResetStatusARB(); + // Support for extensions. Returns a non-null object, though not + // all methods it contains may necessarily be supported on the + // current hardware. Must call Extensions3D::supports() to + // determine this. + Extensions3D* getExtensions(); private: GraphicsContext3D(Attributes attrs, HostWindow* hostWindow, bool renderDirectlyToHostWindow); @@ -832,9 +815,9 @@ public: // pixel packing. FIXME: kAlphaDoUnmultiply is lossy and must // be removed. enum AlphaOp { - kAlphaDoNothing = 0, - kAlphaDoPremultiply = 1, - kAlphaDoUnmultiply = 2 + AlphaDoNothing = 0, + AlphaDoPremultiply = 1, + AlphaDoUnmultiply = 2 }; // Helper for getImageData which implements packing of pixel @@ -872,6 +855,8 @@ public: ANGLEWebKitBridge m_compiler; + OwnPtr<Extensions3DOpenGL> m_extensions; + Attributes m_attrs; Vector<Vector<float> > m_vertexArray; diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index 79c33e0..9fb2d4a 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -648,6 +648,11 @@ MediaPlayer::MovieLoadType MediaPlayer::movieLoadType() const return m_private->movieLoadType(); } +float MediaPlayer::mediaTimeForTimeValue(float timeValue) const +{ + return m_private->mediaTimeForTimeValue(timeValue); +} + // Client callbacks. void MediaPlayer::networkStateChanged() { diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h index bf445e3..a199352 100644 --- a/WebCore/platform/graphics/MediaPlayer.h +++ b/WebCore/platform/graphics/MediaPlayer.h @@ -279,6 +279,8 @@ public: bool hasSingleSecurityOrigin() const; + float mediaTimeForTimeValue(float) const; + private: MediaPlayer(MediaPlayerClient*); diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h index a8d9b86..6a74714 100644 --- a/WebCore/platform/graphics/MediaPlayerPrivate.h +++ b/WebCore/platform/graphics/MediaPlayerPrivate.h @@ -125,6 +125,10 @@ public: virtual void prepareForRendering() { } + // Time value in the movie's time scale. It is only necessary to override this if the media + // engine uses rational numbers to represent media time. + virtual float mediaTimeForTimeValue(float timeValue) const { return timeValue; } + }; } diff --git a/WebCore/platform/graphics/cairo/CairoUtilities.cpp b/WebCore/platform/graphics/cairo/CairoUtilities.cpp index 7af5577..709ee8f 100644 --- a/WebCore/platform/graphics/cairo/CairoUtilities.cpp +++ b/WebCore/platform/graphics/cairo/CairoUtilities.cpp @@ -34,7 +34,7 @@ #include "IntRect.h" #include "OwnPtrCairo.h" #include "Path.h" -#include "PlatformRefPtrCairo.h" +#include "RefPtrCairo.h" #include <wtf/Vector.h> namespace WebCore { @@ -126,11 +126,11 @@ void drawPatternToCairoContext(cairo_t* cr, cairo_surface_t* image, const IntSiz cairo_save(cr); - PlatformRefPtr<cairo_surface_t> clippedImageSurface = 0; + RefPtr<cairo_surface_t> clippedImageSurface = 0; if (tileRect.size() != imageSize) { IntRect imageRect = enclosingIntRect(tileRect); - clippedImageSurface = adoptPlatformRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, imageRect.width(), imageRect.height())); - PlatformRefPtr<cairo_t> clippedImageContext(cairo_create(clippedImageSurface.get())); + clippedImageSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, imageRect.width(), imageRect.height())); + RefPtr<cairo_t> clippedImageContext(cairo_create(clippedImageSurface.get())); cairo_set_source_surface(clippedImageContext.get(), image, -tileRect.x(), -tileRect.y()); cairo_paint(clippedImageContext.get()); image = clippedImageSurface.get(); diff --git a/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp b/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp index cd9ee46..61ee625 100644 --- a/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp +++ b/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp @@ -25,7 +25,7 @@ #include "CString.h" #include "Font.h" #include "OwnPtrCairo.h" -#include "PlatformRefPtrCairo.h" +#include "RefPtrCairo.h" #include "SimpleFontData.h" #include <cairo-ft.h> #include <cairo.h> @@ -83,17 +83,17 @@ FcPattern* findBestFontGivenFallbacks(const FontPlatformData& fontData, FcPatter const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { - PlatformRefPtr<FcPattern> pattern = adoptPlatformRef(createFontConfigPatternForCharacters(characters, length)); + RefPtr<FcPattern> pattern = adoptRef(createFontConfigPatternForCharacters(characters, length)); const FontPlatformData& fontData = font.primaryFont()->platformData(); - PlatformRefPtr<FcPattern> fallbackPattern = adoptPlatformRef(findBestFontGivenFallbacks(fontData, pattern.get())); + RefPtr<FcPattern> fallbackPattern = adoptRef(findBestFontGivenFallbacks(fontData, pattern.get())); if (fallbackPattern) { FontPlatformData alternateFontData(fallbackPattern.get(), font.fontDescription()); return getCachedFontData(&alternateFontData); } FcResult fontConfigResult; - PlatformRefPtr<FcPattern> resultPattern = adoptPlatformRef(FcFontMatch(0, pattern.get(), &fontConfigResult)); + RefPtr<FcPattern> resultPattern = adoptRef(FcFontMatch(0, pattern.get(), &fontConfigResult)); if (!resultPattern) return 0; FontPlatformData alternateFontData(resultPattern.get(), font.fontDescription()); @@ -147,7 +147,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD // The CSS font matching algorithm (http://www.w3.org/TR/css3-fonts/#font-matching-algorithm) // says that we must find an exact match for font family, slant (italic or oblique can be used) // and font weight (we only match bold/non-bold here). - PlatformRefPtr<FcPattern> pattern = adoptPlatformRef(FcPatternCreate()); + RefPtr<FcPattern> pattern = adoptRef(FcPatternCreate()); String familyNameString(getFamilyNameStringFromFontDescriptionAndFamily(fontDescription, family)); if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(familyNameString.utf8().data()))) return 0; @@ -174,7 +174,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD String familyNameAfterConfiguration = String::fromUTF8(reinterpret_cast<char*>(fontConfigFamilyNameAfterConfiguration)); FcResult fontConfigResult; - PlatformRefPtr<FcPattern> resultPattern = adoptPlatformRef(FcFontMatch(0, pattern.get(), &fontConfigResult)); + RefPtr<FcPattern> resultPattern = adoptRef(FcFontMatch(0, pattern.get(), &fontConfigResult)); if (!resultPattern) // No match. return 0; diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp index ba307fa..394082d 100644 --- a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp +++ b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp @@ -120,8 +120,9 @@ FontPlatformData::FontPlatformData(FcPattern* pattern, const FontDescription& fo , m_syntheticBold(false) , m_syntheticOblique(false) , m_fixedWidth(false) + , m_scaledFont(0) { - PlatformRefPtr<cairo_font_face_t> fontFace = adoptPlatformRef(cairo_ft_font_face_create_for_pattern(m_pattern.get())); + RefPtr<cairo_font_face_t> fontFace = adoptRef(cairo_ft_font_face_create_for_pattern(m_pattern.get())); initializeWithFontFace(fontFace.get()); int spacing; @@ -142,6 +143,7 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool italic) , m_syntheticBold(bold) , m_syntheticOblique(italic) , m_fixedWidth(false) + , m_scaledFont(0) { // We cannot create a scaled font here. } @@ -151,13 +153,14 @@ FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool , m_size(size) , m_syntheticBold(bold) , m_syntheticOblique(italic) + , m_scaledFont(0) { initializeWithFontFace(fontFace); - FT_Face fontConfigFace = cairo_ft_scaled_font_lock_face(m_scaledFont.get()); + FT_Face fontConfigFace = cairo_ft_scaled_font_lock_face(m_scaledFont); if (fontConfigFace) { m_fixedWidth = fontConfigFace->face_flags & FT_FACE_FLAG_FIXED_WIDTH; - cairo_ft_scaled_font_unlock_face(m_scaledFont.get()); + cairo_ft_scaled_font_unlock_face(m_scaledFont); } } @@ -171,7 +174,6 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other) m_syntheticBold = other.m_syntheticBold; m_syntheticOblique = other.m_syntheticOblique; m_fixedWidth = other.m_fixedWidth; - m_scaledFont = other.m_scaledFont; m_pattern = other.m_pattern; if (m_fallbacks) { @@ -180,11 +182,16 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other) m_fallbacks = 0; } + if (m_scaledFont && m_scaledFont != hashTableDeletedFontValue()) + cairo_scaled_font_destroy(m_scaledFont); + m_scaledFont = cairo_scaled_font_reference(other.m_scaledFont); + return *this; } FontPlatformData::FontPlatformData(const FontPlatformData& other) : m_fallbacks(0) + , m_scaledFont(0) { *this = other; } @@ -196,7 +203,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& other, float size) // We need to reinitialize the instance, because the difference in size // necessitates a new scaled font instance. m_size = size; - initializeWithFontFace(cairo_scaled_font_get_font_face(m_scaledFont.get())); + initializeWithFontFace(cairo_scaled_font_get_font_face(m_scaledFont)); } FontPlatformData::~FontPlatformData() @@ -205,6 +212,9 @@ FontPlatformData::~FontPlatformData() FcFontSetDestroy(m_fallbacks); m_fallbacks = 0; } + + if (m_scaledFont && m_scaledFont != hashTableDeletedFontValue()) + cairo_scaled_font_destroy(m_scaledFont); } bool FontPlatformData::isFixedPitch() @@ -216,7 +226,7 @@ bool FontPlatformData::operator==(const FontPlatformData& other) const { if (m_pattern == other.m_pattern) return true; - if (!m_pattern || m_pattern.isHashTableDeletedValue() || !other.m_pattern || other.m_pattern.isHashTableDeletedValue()) + if (!m_pattern || !other.m_pattern) return false; return FcPatternEqual(m_pattern.get(), other.m_pattern.get()); } @@ -256,7 +266,7 @@ void FontPlatformData::initializeWithFontFace(cairo_font_face_t* fontFace) cairo_matrix_scale(&fontMatrix, m_size, m_size); } - m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options)); + m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options); cairo_font_options_destroy(options); } diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h index d47d556..016489e 100644 --- a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h +++ b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h @@ -29,7 +29,7 @@ #include "FontDescription.h" #include "GlyphBuffer.h" #include "HashFunctions.h" -#include "PlatformRefPtrCairo.h" +#include "RefPtrCairo.h" #include <wtf/Forward.h> typedef struct _FcFontSet FcFontSet; @@ -43,7 +43,7 @@ public: , m_size(0) , m_syntheticBold(false) , m_syntheticOblique(false) - , m_scaledFont(WTF::HashTableDeletedValue) + , m_scaledFont(hashTableDeletedFontValue()) { } FontPlatformData() @@ -51,6 +51,7 @@ public: , m_size(0) , m_syntheticBold(false) , m_syntheticOblique(false) + , m_scaledFont(0) { } FontPlatformData(FcPattern*, const FontDescription&); @@ -67,34 +68,35 @@ public: bool syntheticBold() const { return m_syntheticBold; } bool syntheticOblique() const { return m_syntheticOblique; } - cairo_scaled_font_t* scaledFont() const { return m_scaledFont.get(); } + cairo_scaled_font_t* scaledFont() const { return m_scaledFont; } unsigned hash() const { - return PtrHash<cairo_scaled_font_t*>::hash(m_scaledFont.get()); + return PtrHash<cairo_scaled_font_t*>::hash(m_scaledFont); } bool operator==(const FontPlatformData&) const; FontPlatformData& operator=(const FontPlatformData&); bool isHashTableDeletedValue() const { - return m_scaledFont.isHashTableDeletedValue(); + return m_scaledFont == hashTableDeletedFontValue(); } #ifndef NDEBUG String description() const; #endif - PlatformRefPtr<FcPattern> m_pattern; + RefPtr<FcPattern> m_pattern; mutable FcFontSet* m_fallbacks; // Initialized lazily. float m_size; bool m_syntheticBold; bool m_syntheticOblique; bool m_fixedWidth; - PlatformRefPtr<cairo_scaled_font_t> m_scaledFont; + cairo_scaled_font_t* m_scaledFont; private: void initializeWithFontFace(cairo_font_face_t*); + static cairo_scaled_font_t* hashTableDeletedFontValue() { return reinterpret_cast<cairo_scaled_font_t*>(-1); } }; } diff --git a/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp index 66e9c16..e2f09f4 100644 --- a/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp +++ b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp @@ -45,7 +45,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.get()); + FT_Face face = cairo_ft_scaled_font_lock_face(fontData->platformData().scaledFont()); if (!face) return false; @@ -60,7 +60,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b } } - cairo_ft_scaled_font_unlock_face(fontData->platformData().m_scaledFont.get()); + cairo_ft_scaled_font_unlock_face(fontData->platformData().scaledFont()); return haveGlyphs; } diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 0847da1..755adff 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -46,7 +46,7 @@ #include "NotImplemented.h" #include "Path.h" #include "Pattern.h" -#include "PlatformRefPtrCairo.h" +#include "RefPtrCairo.h" #include "SimpleFontData.h" #include <cairo.h> #include <math.h> @@ -766,14 +766,6 @@ void GraphicsContext::translate(float x, float y) m_data->translate(x, y); } -IntPoint GraphicsContext::origin() -{ - cairo_matrix_t matrix; - cairo_t* cr = m_data->cr; - cairo_get_matrix(cr, &matrix); - return IntPoint(static_cast<int>(matrix.x0), static_cast<int>(matrix.y0)); -} - void GraphicsContext::setPlatformFillColor(const Color& col, ColorSpace colorSpace) { // Cairo contexts can't hold separate fill and stroke colors @@ -1092,16 +1084,6 @@ void GraphicsContext::clipOut(const IntRect& r) cairo_set_fill_rule(cr, savedFillRule); } -void GraphicsContext::clipOutEllipseInRect(const IntRect& r) -{ - if (paintingDisabled()) - return; - - Path p; - p.addEllipse(r); - clipOut(p); -} - static inline FloatPoint getPhase(const FloatRect& dest, const FloatRect& tile) { FloatPoint phase = dest.location(); diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp index 8f7a194..0ac3955 100644 --- a/WebCore/platform/graphics/cairo/ImageCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp @@ -35,10 +35,10 @@ #include "Color.h" #include "ContextShadow.h" #include "FloatRect.h" -#include "PlatformRefPtrCairo.h" #include "GraphicsContext.h" #include "ImageBuffer.h" #include "ImageObserver.h" +#include "RefPtrCairo.h" #include <cairo.h> #include <math.h> #include <wtf/OwnPtr.h> diff --git a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp b/WebCore/platform/graphics/cairo/RefPtrCairo.cpp index d289585..a6c983e 100644 --- a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp +++ b/WebCore/platform/graphics/cairo/RefPtrCairo.cpp @@ -17,7 +17,7 @@ */ #include "config.h" -#include "PlatformRefPtrCairo.h" +#include "RefPtrCairo.h" #include <cairo.h> @@ -28,71 +28,67 @@ namespace WTF { -template <> cairo_t* refPlatformPtr(cairo_t* ptr) +template<> void refIfNotNull(cairo_t* ptr) { - if (ptr) + if (LIKELY(ptr != 0)) cairo_reference(ptr); - return ptr; } -template <> void derefPlatformPtr(cairo_t* ptr) +template<> void derefIfNotNull(cairo_t* ptr) { - if (ptr) + if (LIKELY(ptr != 0)) cairo_destroy(ptr); } -template <> cairo_surface_t* refPlatformPtr(cairo_surface_t* ptr) +template<> void refIfNotNull(cairo_surface_t* ptr) { - if (ptr) + if (LIKELY(ptr != 0)) cairo_surface_reference(ptr); - return ptr; } -template <> void derefPlatformPtr(cairo_surface_t* ptr) +template<> void derefIfNotNull(cairo_surface_t* ptr) { - if (ptr) + if (LIKELY(ptr != 0)) cairo_surface_destroy(ptr); } -template <> cairo_font_face_t* refPlatformPtr(cairo_font_face_t* ptr) +template<> void refIfNotNull(cairo_font_face_t* ptr) { - if (ptr) + if (LIKELY(ptr != 0)) cairo_font_face_reference(ptr); - return ptr; } -template <> void derefPlatformPtr(cairo_font_face_t* ptr) +template<> void derefIfNotNull(cairo_font_face_t* ptr) { - if (ptr) - cairo_font_face_destroy(ptr); + if (LIKELY(ptr != 0)) + cairo_font_face_reference(ptr); } -template <> cairo_scaled_font_t* refPlatformPtr(cairo_scaled_font_t* ptr) +template<> void refIfNotNull(cairo_scaled_font_t* ptr) { - if (ptr) + if (LIKELY(ptr != 0)) cairo_scaled_font_reference(ptr); - return ptr; } -template <> void derefPlatformPtr(cairo_scaled_font_t* ptr) +template<> void derefIfNotNull(cairo_scaled_font_t* ptr) { - if (ptr) + if (LIKELY(ptr != 0)) cairo_scaled_font_destroy(ptr); } #if defined(USE_FREETYPE) -template <> FcPattern* refPlatformPtr(FcPattern* ptr) +template<> void refIfNotNull(FcPattern* ptr) { - if (ptr) + if (LIKELY(ptr != 0)) FcPatternReference(ptr); - return ptr; } -template <> void derefPlatformPtr(FcPattern* ptr) +template<> void derefIfNotNull(FcPattern* ptr) { - if (ptr) + if (LIKELY(ptr != 0)) FcPatternDestroy(ptr); } + #endif } diff --git a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h b/WebCore/platform/graphics/cairo/RefPtrCairo.h index 3b720c6..0429ec5 100644 --- a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h +++ b/WebCore/platform/graphics/cairo/RefPtrCairo.h @@ -17,10 +17,10 @@ * Boston, MA 02110-1301, USA. */ -#ifndef PlatformRefPtrCairo_h -#define PlatformRefPtrCairo_h +#ifndef RefPtrCairo_h +#define RefPtrCairo_h -#include "PlatformRefPtr.h" +#include "RefPtr.h" typedef struct _cairo cairo_t; typedef struct _cairo_surface cairo_surface_t; @@ -33,23 +33,23 @@ typedef struct _FcPattern FcPattern; namespace WTF { -template <> cairo_t* refPlatformPtr(cairo_t* ptr); -template <> void derefPlatformPtr(cairo_t* ptr); +template<> void refIfNotNull(cairo_t* ptr); +template<> void derefIfNotNull(cairo_t* ptr); -template <> cairo_surface_t* refPlatformPtr(cairo_surface_t* ptr); -template <> void derefPlatformPtr(cairo_surface_t* ptr); +template<> void refIfNotNull(cairo_surface_t* ptr); +template<> void derefIfNotNull(cairo_surface_t* ptr); -template <> cairo_font_face_t* refPlatformPtr(cairo_font_face_t*); -template <> void derefPlatformPtr(cairo_font_face_t*); +template<> void refIfNotNull(cairo_font_face_t* ptr); +template<> void derefIfNotNull(cairo_font_face_t* ptr); -template <> cairo_scaled_font_t* refPlatformPtr(cairo_scaled_font_t*); -template <> void derefPlatformPtr(cairo_scaled_font_t*); +template<> void refIfNotNull(cairo_scaled_font_t* ptr); +template<> void derefIfNotNull(cairo_scaled_font_t* ptr); #if defined(USE_FREETYPE) -template <> FcPattern* refPlatformPtr(FcPattern*); -template <> void derefPlatformPtr(FcPattern*); +template<> void refIfNotNull(FcPattern* ptr); +template<> void derefIfNotNull(FcPattern* ptr); #endif } -#endif +#endif // RefPtrCairo_h diff --git a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp index 3d7c34b..d350294 100644 --- a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp +++ b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp @@ -49,7 +49,7 @@ void SimpleFontData::platformInit() { cairo_font_extents_t font_extents; cairo_text_extents_t text_extents; - cairo_scaled_font_extents(m_platformData.m_scaledFont.get(), &font_extents); + cairo_scaled_font_extents(m_platformData.scaledFont(), &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)); @@ -60,9 +60,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.get(), "x", &text_extents); + cairo_scaled_font_text_extents(m_platformData.scaledFont(), "x", &text_extents); m_xHeight = text_extents.height; - cairo_scaled_font_text_extents(m_platformData.m_scaledFont.get(), " ", &text_extents); + cairo_scaled_font_text_extents(m_platformData.scaledFont(), " ", &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; @@ -94,19 +94,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.get()); + FT_Face face = cairo_ft_scaled_font_lock_face(m_platformData.scaledFont()); 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.get()); + cairo_ft_scaled_font_unlock_face(m_platformData.scaledFont()); return false; } } - cairo_ft_scaled_font_unlock_face(m_platformData.m_scaledFont.get()); + cairo_ft_scaled_font_unlock_face(m_platformData.scaledFont()); return true; } @@ -123,14 +123,14 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { - ASSERT(m_platformData.m_scaledFont); + ASSERT(m_platformData.scaledFont()); cairo_glyph_t cglyph = { glyph, 0, 0 }; cairo_text_extents_t extents; - cairo_scaled_font_glyph_extents(m_platformData.m_scaledFont.get(), &cglyph, 1, &extents); + cairo_scaled_font_glyph_extents(m_platformData.scaledFont(), &cglyph, 1, &extents); float w = (float)m_spaceWidth; - if (cairo_scaled_font_status(m_platformData.m_scaledFont.get()) == CAIRO_STATUS_SUCCESS && extents.x_advance) + if (cairo_scaled_font_status(m_platformData.scaledFont()) == CAIRO_STATUS_SUCCESS && extents.x_advance) w = (float)extents.x_advance; return w; diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp index a1cc805..0c6acf9 100644 --- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -59,7 +59,7 @@ enum AlphaFormat { AlphaFormatNumFormats }; -// This returns kSourceFormatNumFormats if the combination of input parameters is unsupported. +// This returns SourceFormatNumFormats if the combination of input parameters is unsupported. static GraphicsContext3D::SourceDataFormat getSourceDataFormat(unsigned int componentsPerPixel, AlphaFormat alphaFormat, bool is16BitFormat, bool bigEndian) { const static SourceDataFormatBase formatTableBase[4][AlphaFormatNumFormats] = { // componentsPerPixel x AlphaFormat @@ -69,26 +69,22 @@ static GraphicsContext3D::SourceDataFormat getSourceDataFormat(unsigned int comp { SourceFormatBaseRGB, SourceFormatBaseNumFormats, SourceFormatBaseNumFormats }, // 3 componentsPerPixel { SourceFormatBaseNumFormats, SourceFormatBaseARGB, SourceFormatBaseRGBA } // 4 componentsPerPixel }; - const static GraphicsContext3D::SourceDataFormat formatTable[SourceFormatBaseNumFormats][3] = { // SourceDataFormatBase x bitsPerComponentAndEndian - // 8bits 16bits, little endian 16bits, big endian - { GraphicsContext3D::kSourceFormatR8, GraphicsContext3D::kSourceFormatR16Little, GraphicsContext3D::kSourceFormatR16Big }, - { GraphicsContext3D::kSourceFormatA8, GraphicsContext3D::kSourceFormatA16Little, GraphicsContext3D::kSourceFormatA16Big }, - { GraphicsContext3D::kSourceFormatRA8, GraphicsContext3D::kSourceFormatRA16Little, GraphicsContext3D::kSourceFormatRA16Big }, - { GraphicsContext3D::kSourceFormatAR8, GraphicsContext3D::kSourceFormatAR16Little, GraphicsContext3D::kSourceFormatAR16Big }, - { GraphicsContext3D::kSourceFormatRGB8, GraphicsContext3D::kSourceFormatRGB16Little, GraphicsContext3D::kSourceFormatRGB16Big }, - { GraphicsContext3D::kSourceFormatRGBA8, GraphicsContext3D::kSourceFormatRGBA16Little, GraphicsContext3D::kSourceFormatRGBA16Big }, - { GraphicsContext3D::kSourceFormatARGB8, GraphicsContext3D::kSourceFormatARGB16Little, GraphicsContext3D::kSourceFormatARGB16Big } + const static GraphicsContext3D::SourceDataFormat formatTable[SourceFormatBaseNumFormats][4] = { // SourceDataFormatBase x bitsPerComponent x endian + // 8bits, little endian 8bits, big endian 16bits, little endian 16bits, big endian + { GraphicsContext3D::SourceFormatR8, GraphicsContext3D::SourceFormatR8, GraphicsContext3D::SourceFormatR16Little, GraphicsContext3D::SourceFormatR16Big }, + { GraphicsContext3D::SourceFormatA8, GraphicsContext3D::SourceFormatA8, GraphicsContext3D::SourceFormatA16Little, GraphicsContext3D::SourceFormatA16Big }, + { GraphicsContext3D::SourceFormatAR8, GraphicsContext3D::SourceFormatRA8, GraphicsContext3D::SourceFormatRA16Little, GraphicsContext3D::SourceFormatRA16Big }, + { GraphicsContext3D::SourceFormatRA8, GraphicsContext3D::SourceFormatAR8, GraphicsContext3D::SourceFormatAR16Little, GraphicsContext3D::SourceFormatAR16Big }, + { GraphicsContext3D::SourceFormatBGR8, GraphicsContext3D::SourceFormatRGB8, GraphicsContext3D::SourceFormatRGB16Little, GraphicsContext3D::SourceFormatRGB16Big }, + { GraphicsContext3D::SourceFormatABGR8, GraphicsContext3D::SourceFormatRGBA8, GraphicsContext3D::SourceFormatRGBA16Little, GraphicsContext3D::SourceFormatRGBA16Big }, + { GraphicsContext3D::SourceFormatBGRA8, GraphicsContext3D::SourceFormatARGB8, GraphicsContext3D::SourceFormatARGB16Little, GraphicsContext3D::SourceFormatARGB16Big } }; ASSERT(componentsPerPixel <= 4 && componentsPerPixel > 0); SourceDataFormatBase formatBase = formatTableBase[componentsPerPixel - 1][alphaFormat]; if (formatBase == SourceFormatBaseNumFormats) - return GraphicsContext3D::kSourceFormatNumFormats; - if (!is16BitFormat) - return formatTable[formatBase][0]; - if (!bigEndian) - return formatTable[formatBase][1]; - return formatTable[formatBase][2]; + return GraphicsContext3D::SourceFormatNumFormats; + return formatTable[formatBase][(is16BitFormat ? 2 : 0) + (bigEndian ? 1 : 0)]; } bool GraphicsContext3D::getImageData(Image* image, @@ -125,28 +121,47 @@ bool GraphicsContext3D::getImageData(Image* image, return false; size_t componentsPerPixel = bitsPerPixel / bitsPerComponent; - bool srcByteOrder16Big = false; + CGBitmapInfo bitInfo = CGImageGetBitmapInfo(cgImage); + bool bigEndianSource = false; + // These could technically be combined into one large switch + // statement, but we prefer not to so that we fail fast if we + // encounter an unexpected image configuration. if (bitsPerComponent == 16) { - CGBitmapInfo bitInfo = CGImageGetBitmapInfo(cgImage); switch (bitInfo & kCGBitmapByteOrderMask) { case kCGBitmapByteOrder16Big: - srcByteOrder16Big = true; + bigEndianSource = true; break; case kCGBitmapByteOrder16Little: - srcByteOrder16Big = false; + bigEndianSource = false; break; case kCGBitmapByteOrderDefault: // This is a bug in earlier version of cg where the default endian // is little whereas the decoded 16-bit png image data is actually // Big. Later version (10.6.4) no longer returns ByteOrderDefault. - srcByteOrder16Big = true; + bigEndianSource = true; + break; + default: + return false; + } + } else { + switch (bitInfo & kCGBitmapByteOrderMask) { + case kCGBitmapByteOrder32Big: + bigEndianSource = true; + break; + case kCGBitmapByteOrder32Little: + bigEndianSource = false; + break; + case kCGBitmapByteOrderDefault: + // It appears that the default byte order is actually big + // endian even on little endian architectures. + bigEndianSource = true; break; default: return false; } } - AlphaOp neededAlphaOp = kAlphaDoNothing; + AlphaOp neededAlphaOp = AlphaDoNothing; AlphaFormat alphaFormat = AlphaFormatNone; switch (CGImageGetAlphaInfo(cgImage)) { case kCGImageAlphaPremultipliedFirst: @@ -155,13 +170,13 @@ bool GraphicsContext3D::getImageData(Image* image, // in which case image->data() should be null. ASSERT(!image->data()); if (!premultiplyAlpha) - neededAlphaOp = kAlphaDoUnmultiply; + neededAlphaOp = AlphaDoUnmultiply; alphaFormat = AlphaFormatFirst; break; case kCGImageAlphaFirst: // This path is only accessible for MacOS earlier than 10.6.4. if (premultiplyAlpha) - neededAlphaOp = kAlphaDoPremultiply; + neededAlphaOp = AlphaDoPremultiply; alphaFormat = AlphaFormatFirst; break; case kCGImageAlphaNoneSkipFirst: @@ -173,12 +188,12 @@ bool GraphicsContext3D::getImageData(Image* image, // in which case image->data() should be null. ASSERT(!image->data()); if (!premultiplyAlpha) - neededAlphaOp = kAlphaDoUnmultiply; + neededAlphaOp = AlphaDoUnmultiply; alphaFormat = AlphaFormatLast; break; case kCGImageAlphaLast: if (premultiplyAlpha) - neededAlphaOp = kAlphaDoPremultiply; + neededAlphaOp = AlphaDoPremultiply; alphaFormat = AlphaFormatLast; break; case kCGImageAlphaNoneSkipLast: @@ -190,8 +205,8 @@ bool GraphicsContext3D::getImageData(Image* image, default: return false; } - SourceDataFormat srcDataFormat = getSourceDataFormat(componentsPerPixel, alphaFormat, bitsPerComponent == 16, srcByteOrder16Big); - if (srcDataFormat == kSourceFormatNumFormats) + SourceDataFormat srcDataFormat = getSourceDataFormat(componentsPerPixel, alphaFormat, bitsPerComponent == 16, bigEndianSource); + if (srcDataFormat == SourceFormatNumFormats) return false; RetainPtr<CFDataRef> pixelData; diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index 9e0a2f5..8d72b85 100644 --- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -669,17 +669,6 @@ void GraphicsContext::clipOut(const IntRect& rect) CGContextEOClip(platformContext()); } -void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) -{ - if (paintingDisabled()) - return; - - CGContextBeginPath(platformContext()); - CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext())); - CGContextAddEllipseInRect(platformContext(), rect); - CGContextEOClip(platformContext()); -} - void GraphicsContext::clipPath(WindRule clipRule) { if (paintingDisabled()) diff --git a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp index b54a427..e44ec9d 100644 --- a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp +++ b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp @@ -32,6 +32,7 @@ #include "DrawingBuffer.h" +#include "Extensions3DChromium.h" #include "GraphicsContext3D.h" #include "SharedGraphicsContext3D.h" @@ -69,9 +70,14 @@ static unsigned generateColorTexture(GraphicsContext3D* context, const IntSize& DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, const IntSize& size) : m_context(context) , m_size(size) - , m_fbo(context->createFramebuffer()) + , m_fbo(0) , m_internal(new DrawingBufferInternal) { + if (!m_context->getExtensions()->supports("GL_CHROMIUM_copy_texture_to_parent_texture")) { + m_context.clear(); + return; + } + m_fbo = context->createFramebuffer(); context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_internal->offscreenColorTexture = generateColorTexture(context, size); } @@ -107,7 +113,7 @@ 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(); - m_context->copyTextureToParentTextureCHROMIUM(m_internal->offscreenColorTexture, parentTexture); + static_cast<Extensions3DChromium*>(m_context->getExtensions())->copyTextureToParentTextureCHROMIUM(m_internal->offscreenColorTexture, parentTexture); m_context->flush(); } #endif diff --git a/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/WebCore/platform/graphics/chromium/Extensions3DChromium.h new file mode 100644 index 0000000..0fd1fff --- /dev/null +++ b/WebCore/platform/graphics/chromium/Extensions3DChromium.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Extensions3DChromium_h +#define Extensions3DChromium_h + +#include "Extensions3D.h" + +namespace WebCore { + +class GraphicsContext3DInternal; + +class Extensions3DChromium : public Extensions3D { +public: + virtual ~Extensions3DChromium(); + + // Extensions3D methods. + virtual bool supports(const String&); + virtual int getGraphicsResetStatusARB(); + + enum { + // GL_CHROMIUM_map_sub (enums inherited from GL_ARB_vertex_buffer_object) + READ_ONLY = 0x88B8, + WRITE_ONLY = 0x88B9 + }; + + // GL_CHROMIUM_map_sub + 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 + void copyTextureToParentTextureCHROMIUM(unsigned texture, unsigned parentTexture); + +private: + // Instances of this class are strictly owned by the GraphicsContext3D implementation and do not + // need to be instantiated by any other code. + friend class GraphicsContext3DInternal; + explicit Extensions3DChromium(GraphicsContext3DInternal*); + + // Weak pointer back to GraphicsContext3DInternal + GraphicsContext3DInternal* m_internal; +}; + +} // namespace WebCore + +#endif // Extensions3DChromium_h diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp index 7c3e450..384b1c5 100644 --- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp @@ -391,10 +391,10 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons int numFonts = 0; if (script == USCRIPT_HAN) { panUniFonts = cjkFonts; - numFonts = ARRAYSIZE(cjkFonts); + numFonts = WTF_ARRAY_LENGTH(cjkFonts); } else { panUniFonts = commonFonts; - numFonts = ARRAYSIZE(commonFonts); + numFonts = WTF_ARRAY_LENGTH(commonFonts); } // Font returned from GetFallbackFamily may not cover |characters| // because it's based on script to font mapping. This problem is diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index f668bbf..23e54e5 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -370,6 +370,7 @@ void LayerChromium::setNeedsDisplay() { m_dirtyRect.setSize(m_bounds); m_contentsDirty = true; + setNeedsCommit(); } void LayerChromium::resetNeedsDisplay() diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index e93e296..e1b525b 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -730,7 +730,10 @@ bool LayerRendererChromium::initializeSharedObjects() m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues(m_context.get())); m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues(m_context.get())); m_videoLayerSharedValues = adoptPtr(new VideoLayerChromium::SharedValues(m_context.get())); - if (!m_layerSharedValues->initialized() || !m_contentLayerSharedValues->initialized() || !m_canvasLayerSharedValues->initialized() || !m_videoLayerSharedValues->initialized()) { + m_pluginLayerSharedValues = adoptPtr(new PluginLayerChromium::SharedValues(m_context.get())); + + if (!m_layerSharedValues->initialized() || !m_contentLayerSharedValues->initialized() || !m_canvasLayerSharedValues->initialized() + || !m_videoLayerSharedValues->initialized() || !m_pluginLayerSharedValues->initialized()) { cleanupSharedObjects(); return false; } @@ -746,6 +749,7 @@ void LayerRendererChromium::cleanupSharedObjects() m_contentLayerSharedValues.clear(); m_canvasLayerSharedValues.clear(); m_videoLayerSharedValues.clear(); + m_pluginLayerSharedValues.clear(); if (m_scrollShaderProgram) { GLC(m_context, m_context->deleteProgram(m_scrollShaderProgram)); diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h index b2a32ee..52fbe36 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -38,6 +38,7 @@ #include "ContentLayerChromium.h" #include "IntRect.h" #include "LayerChromium.h" +#include "PluginLayerChromium.h" #include "SkBitmap.h" #include "VideoLayerChromium.h" #include <wtf/HashMap.h> @@ -107,6 +108,7 @@ public: const ContentLayerChromium::SharedValues* contentLayerSharedValues() const { return m_contentLayerSharedValues.get(); } const CanvasLayerChromium::SharedValues* canvasLayerSharedValues() const { return m_canvasLayerSharedValues.get(); } const VideoLayerChromium::SharedValues* videoLayerSharedValues() const { return m_videoLayerSharedValues.get(); } + const PluginLayerChromium::SharedValues* pluginLayerSharedValues() const { return m_pluginLayerSharedValues.get(); } void resizeOnscreenContent(const IntSize&); @@ -180,6 +182,7 @@ private: OwnPtr<ContentLayerChromium::SharedValues> m_contentLayerSharedValues; OwnPtr<CanvasLayerChromium::SharedValues> m_canvasLayerSharedValues; OwnPtr<VideoLayerChromium::SharedValues> m_videoLayerSharedValues; + OwnPtr<PluginLayerChromium::SharedValues> m_pluginLayerSharedValues; RefPtr<GraphicsContext3D> m_context; }; diff --git a/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp b/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp new file mode 100644 index 0000000..2d1852f --- /dev/null +++ b/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "PluginLayerChromium.h" + +#include "GraphicsContext3D.h" +#include "LayerRendererChromium.h" +#include <GLES2/gl2.h> + +namespace WebCore { + +PluginLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) + : m_context(context) + , m_shaderProgram(0) + , m_shaderSamplerLocation(-1) + , m_shaderMatrixLocation(-1) + , m_shaderAlphaLocation(-1) + , m_initialized(false) +{ + char vertexShaderString[] = + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "uniform mat4 matrix; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = matrix * a_position; \n" + " v_texCoord = a_texCoord; \n" + "} \n"; + + char fragmentShaderString[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "uniform float alpha; \n" + "void main() \n" + "{ \n" + " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, v_texCoord.y)); \n" + " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" + "} \n"; + + m_shaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString); + if (!m_shaderProgram) { + LOG_ERROR("PluginLayerChromium: Failed to create shader program"); + return; + } + + m_shaderSamplerLocation = m_context->getUniformLocation(m_shaderProgram, "s_texture"); + m_shaderMatrixLocation = m_context->getUniformLocation(m_shaderProgram, "matrix"); + m_shaderAlphaLocation = m_context->getUniformLocation(m_shaderProgram, "alpha"); + ASSERT(m_shaderSamplerLocation != -1); + ASSERT(m_shaderMatrixLocation != -1); + ASSERT(m_shaderAlphaLocation != -1); + + m_initialized = true; +} + +PluginLayerChromium::SharedValues::~SharedValues() +{ + if (m_shaderProgram) + GLC(m_context, m_context->deleteProgram(m_shaderProgram)); +} + +PassRefPtr<PluginLayerChromium> PluginLayerChromium::create(GraphicsLayerChromium* owner) +{ + return adoptRef(new PluginLayerChromium(owner)); +} + +PluginLayerChromium::PluginLayerChromium(GraphicsLayerChromium* owner) + : LayerChromium(owner) +{ +} + +void PluginLayerChromium::setTextureId(unsigned id) +{ + m_textureId = id; +} + +void PluginLayerChromium::updateContents() +{ +} + +void PluginLayerChromium::draw() +{ + ASSERT(layerRenderer()); + const PluginLayerChromium::SharedValues* sv = layerRenderer()->pluginLayerSharedValues(); + ASSERT(sv && sv->initialized()); + GraphicsContext3D* context = layerRendererContext(); + GLC(context, context->activeTexture(GL_TEXTURE0)); + GLC(context, context->bindTexture(GL_TEXTURE_2D, m_textureId)); + + // FIXME: setting the texture parameters every time is redundant. Move this code somewhere + // where it will only happen once per texture. + GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + + layerRenderer()->useShader(sv->shaderProgram()); + GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0)); + drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + sv->shaderMatrixLocation(), sv->shaderAlphaLocation()); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/PluginLayerChromium.h b/WebCore/platform/graphics/chromium/PluginLayerChromium.h new file mode 100644 index 0000000..44a6cc9 --- /dev/null +++ b/WebCore/platform/graphics/chromium/PluginLayerChromium.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef PluginLayerChromium_h +#define PluginLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" + +namespace WebCore { + +// A Layer containing a the rendered output of a plugin instance. +class PluginLayerChromium : public LayerChromium { +public: + static PassRefPtr<PluginLayerChromium> create(GraphicsLayerChromium* owner = 0); + virtual bool drawsContent() { return true; } + virtual void updateContents(); + virtual void draw(); + + void setTextureId(unsigned textureId); + + class SharedValues { + public: + SharedValues(GraphicsContext3D* context); + ~SharedValues(); + + unsigned shaderProgram() const { return m_shaderProgram; } + int shaderSamplerLocation() const { return m_shaderSamplerLocation; } + int shaderMatrixLocation() const { return m_shaderMatrixLocation; } + int shaderAlphaLocation() const { return m_shaderAlphaLocation; } + bool initialized() const { return m_initialized; } + + private: + GraphicsContext3D* m_context; + unsigned m_shaderProgram; + int m_shaderSamplerLocation; + int m_shaderMatrixLocation; + int m_shaderAlphaLocation; + bool m_initialized; + }; + +private: + PluginLayerChromium(GraphicsLayerChromium* owner); + unsigned m_textureId; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp index 46c73a1..fa6c2c8 100644 --- a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp @@ -33,6 +33,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "VideoLayerChromium.h" +#include "Extensions3DChromium.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" #include "RenderLayerBacking.h" @@ -302,10 +303,10 @@ void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned text { ASSERT(context); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); - void* mem = context->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, GraphicsContext3D::WRITE_ONLY); + void* mem = static_cast<Extensions3DChromium*>(context->getExtensions())->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY); if (mem) { memcpy(mem, data, dimensions.width() * dimensions.height()); - GLC(context, context->unmapTexSubImage2DCHROMIUM(mem)); + GLC(context, static_cast<Extensions3DChromium*>(context->getExtensions())->unmapTexSubImage2DCHROMIUM(mem)); } else { // FIXME: We should have some sort of code to handle the case when // mapTexSubImage2D fails. diff --git a/WebCore/platform/graphics/filters/FELighting.cpp b/WebCore/platform/graphics/filters/FELighting.cpp index e1df580..803b9c1 100644 --- a/WebCore/platform/graphics/filters/FELighting.cpp +++ b/WebCore/platform/graphics/filters/FELighting.cpp @@ -54,85 +54,182 @@ FELighting::FELighting(LightingType lightingType, const Color& lightingColor, fl const static int cPixelSize = 4; const static int cAlphaChannelOffset = 3; const static unsigned char cOpaqueAlpha = static_cast<unsigned char>(0xff); +const static float cFactor1div2 = -1 / 2.f; +const static float cFactor1div3 = -1 / 3.f; +const static float cFactor1div4 = -1 / 4.f; +const static float cFactor2div3 = -2 / 3.f; -ALWAYS_INLINE int FELighting::LightingData::upLeftPixelValue() +// << 1 is signed multiply by 2 +inline void FELighting::LightingData::topLeft(int offset, IntPoint& normalVector) { - return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize; + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-(center << 1) + (right << 1) - bottom + bottomRight); + normalVector.setY(-(center << 1) - right + (bottom << 1) + bottomRight); } -ALWAYS_INLINE int FELighting::LightingData::upPixelValue() +inline void FELighting::LightingData::topRow(int offset, IntPoint& normalVector) { - return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize + cAlphaChannelOffset)); + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize; + int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-(left << 1) + (right << 1) - bottomLeft + bottomRight); + normalVector.setY(-left - (center << 1) - right + bottomLeft + (bottom << 1) + bottomRight); } -ALWAYS_INLINE int FELighting::LightingData::upRightPixelValue() +inline void FELighting::LightingData::topRight(int offset, IntPoint& normalVector) { - return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize + cPixelSize + cAlphaChannelOffset)); + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize; + int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + normalVector.setX(-(left << 1) + (center << 1) - bottomLeft + bottom); + normalVector.setY(-left - (center << 1) + bottomLeft + (bottom << 1)); } -ALWAYS_INLINE int FELighting::LightingData::leftPixelValue() +inline void FELighting::LightingData::leftColumn(int offset, IntPoint& normalVector) { - return static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize << 1; + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-top + topRight - (center << 1) + (right << 1) - bottom + bottomRight); + normalVector.setY(-(top << 1) - topRight + (bottom << 1) + bottomRight); } -ALWAYS_INLINE int FELighting::LightingData::centerPixelValue() +inline void FELighting::LightingData::interior(int offset, IntPoint& normalVector) { - return static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize << 1; + int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1) - bottomLeft + bottomRight); + normalVector.setY(-topLeft - (top << 1) - topRight + bottomLeft + (bottom << 1) + bottomRight); } -ALWAYS_INLINE int FELighting::LightingData::rightPixelValue() +inline void FELighting::LightingData::rightColumn(int offset, IntPoint& normalVector) { - return static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize << 1; + int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + normalVector.setX(-topLeft + top - (left << 1) + (center << 1) - bottomLeft + bottom); + normalVector.setY(-topLeft - (top << 1) + bottomLeft + (bottom << 1)); } -ALWAYS_INLINE int FELighting::LightingData::downLeftPixelValue() +inline void FELighting::LightingData::bottomLeft(int offset, IntPoint& normalVector) { - return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-top + topRight - (center << 1) + (right << 1)); + normalVector.setY(-(top << 1) - topRight + (center << 1) + right); } -ALWAYS_INLINE int FELighting::LightingData::downPixelValue() +inline void FELighting::LightingData::bottomRow(int offset, IntPoint& normalVector) { - return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize + cAlphaChannelOffset)); + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1)); + normalVector.setY(-topLeft - (top << 1) - topRight + left + (center << 1) + right); } -ALWAYS_INLINE int FELighting::LightingData::downRightPixelValue() +inline void FELighting::LightingData::bottomRight(int offset, IntPoint& normalVector) { - return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize + cPixelSize + cAlphaChannelOffset)); + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + normalVector.setX(-topLeft + top - (left << 1) + (center << 1)); + normalVector.setY(-topLeft - (top << 1) + left + (center << 1)); } -ALWAYS_INLINE void FELighting::setPixel(LightingData& data, LightSource::PaintingData& paintingData, - int lightX, int lightY, float factorX, int normalX, float factorY, int normalY) +inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, + int lightX, int lightY, float factorX, float factorY, IntPoint& normal2DVector) { - m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(data.offset + 3)) * data.surfaceScale); - - data.normalVector.setX(factorX * static_cast<float>(normalX) * data.surfaceScale); - data.normalVector.setY(factorY * static_cast<float>(normalY) * data.surfaceScale); - data.normalVector.setZ(1.0f); - data.normalVector.normalize(); - - if (m_lightingType == FELighting::DiffuseLighting) - data.lightStrength = m_diffuseConstant * (data.normalVector * paintingData.lightVector); - else { - FloatPoint3D halfwayVector = paintingData.lightVector; - halfwayVector.setZ(halfwayVector.z() + 1.0f); - halfwayVector.normalize(); - if (m_specularExponent == 1.0f) - data.lightStrength = m_specularConstant * (data.normalVector * halfwayVector); - else - data.lightStrength = m_specularConstant * powf(data.normalVector * halfwayVector, m_specularExponent); + m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(offset + cAlphaChannelOffset)) * data.surfaceScale); + + float lightStrength; + if (!normal2DVector.x() && !normal2DVector.y()) { + // Normal vector is (0, 0, 1). This is a quite frequent case. + if (m_lightingType == FELighting::DiffuseLighting) + lightStrength = m_diffuseConstant * paintingData.lightVector.z() / paintingData.lightVectorLength; + else { + FloatPoint3D halfwayVector = paintingData.lightVector; + halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength); + float halfwayVectorLength = halfwayVector.length(); + if (m_specularExponent == 1) + lightStrength = m_specularConstant * halfwayVector.z() / halfwayVectorLength; + else + lightStrength = m_specularConstant * powf(halfwayVector.z() / halfwayVectorLength, m_specularExponent); + } + } else { + FloatPoint3D normalVector; + normalVector.setX(factorX * static_cast<float>(normal2DVector.x()) * data.surfaceScale); + normalVector.setY(factorY * static_cast<float>(normal2DVector.y()) * data.surfaceScale); + normalVector.setZ(1); + float normalVectorLength = normalVector.length(); + + if (m_lightingType == FELighting::DiffuseLighting) + lightStrength = m_diffuseConstant * (normalVector * paintingData.lightVector) / (normalVectorLength * paintingData.lightVectorLength); + else { + FloatPoint3D halfwayVector = paintingData.lightVector; + halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength); + float halfwayVectorLength = halfwayVector.length(); + if (m_specularExponent == 1) + lightStrength = m_specularConstant * (normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength); + else + lightStrength = m_specularConstant * powf((normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength), m_specularExponent); + } } - if (data.lightStrength > 1.0f) - data.lightStrength = 1.0f; - if (data.lightStrength < 0.0f) - data.lightStrength = 0.0f; + if (lightStrength > 1) + lightStrength = 1; + if (lightStrength < 0) + lightStrength = 0; - data.pixels->set(data.offset, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.x())); - data.pixels->set(data.offset + 1, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.y())); - data.pixels->set(data.offset + 2, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.z())); + data.pixels->set(offset, static_cast<unsigned char>(lightStrength * paintingData.colorVector.x())); + data.pixels->set(offset + 1, static_cast<unsigned char>(lightStrength * paintingData.colorVector.y())); + data.pixels->set(offset + 2, static_cast<unsigned char>(lightStrength * paintingData.colorVector.z())); +} + +void FELighting::setPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, + int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector) +{ + inlineSetPixel(offset, data, paintingData, lightX, lightY, factorX, factorY, normalVector); } -bool FELighting::drawLighting(CanvasPixelArray* pixels, int width, int height) +bool FELighting::drawLighting(ByteArray* pixels, int width, int height) { LightSource::PaintingData paintingData; LightingData data; @@ -154,81 +251,73 @@ bool FELighting::drawLighting(CanvasPixelArray* pixels, int width, int height) m_lightSource->initPaintingData(paintingData); // Top/Left corner - data.offset = 0; - setPixel(data, paintingData, 0, 0, - -2.0f / 3.0f, -2 * data.centerPixelValue() + 2 * data.rightPixelValue() - data.downPixelValue() + data.downRightPixelValue(), - -2.0f / 3.0f, -2 * data.centerPixelValue() - data.rightPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + IntPoint normalVector; + int offset = 0; + data.topLeft(offset, normalVector); + setPixel(offset, data, paintingData, 0, 0, cFactor2div3, cFactor2div3, normalVector); // Top/Right pixel - data.offset = data.widthMultipliedByPixelSize - cPixelSize; - setPixel(data, paintingData, data.widthDecreasedByOne, 0, - -2.0f / 3.0f, -2 * data.leftPixelValue() + 2 * data.centerPixelValue() - data.downLeftPixelValue() + data.downPixelValue(), - -2.0f / 3.0f, -data.leftPixelValue() - 2 * data.centerPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue()); + offset = data.widthMultipliedByPixelSize - cPixelSize; + data.topRight(offset, normalVector); + setPixel(offset, data, paintingData, data.widthDecreasedByOne, 0, cFactor2div3, cFactor2div3, normalVector); // Bottom/Left pixel - data.offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize; - setPixel(data, paintingData, 0, data.heightDecreasedByOne, - -2.0f / 3.0f, -data.upPixelValue() + data.upRightPixelValue() - 2 * data.centerPixelValue() + 2 * data.rightPixelValue(), - -2.0f / 3.0f, -2 * data.upPixelValue() - data.upRightPixelValue() + 2 * data.centerPixelValue() + data.rightPixelValue()); + offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize; + data.bottomLeft(offset, normalVector); + setPixel(offset, data, paintingData, 0, data.heightDecreasedByOne, cFactor2div3, cFactor2div3, normalVector); // Bottom/Right pixel - data.offset = height * data.widthMultipliedByPixelSize - cPixelSize; - setPixel(data, paintingData, data.widthDecreasedByOne, data.heightDecreasedByOne, - -2.0f / 3.0f, -data.upLeftPixelValue() + data.upPixelValue() - 2 * data.leftPixelValue() + 2 * data.centerPixelValue(), - -2.0f / 3.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() + data.leftPixelValue() + 2 * data.centerPixelValue()); + offset = height * data.widthMultipliedByPixelSize - cPixelSize; + data.bottomRight(offset, normalVector); + setPixel(offset, data, paintingData, data.widthDecreasedByOne, data.heightDecreasedByOne, cFactor2div3, cFactor2div3, normalVector); if (width >= 3) { - // Top line - data.offset = cPixelSize; - for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) { - setPixel(data, paintingData, x, 0, - -1.0f / 3.0f, -2 * data.leftPixelValue() + 2 * data.rightPixelValue() - data.downLeftPixelValue() + data.downRightPixelValue(), - -1.0f / 2.0f, -data.leftPixelValue() - 2 * data.centerPixelValue() - data.rightPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + // Top row + offset = cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) { + data.topRow(offset, normalVector); + inlineSetPixel(offset, data, paintingData, x, 0, cFactor1div3, cFactor1div2, normalVector); } - // Bottom line - data.offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize; - for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) { - setPixel(data, paintingData, x, data.heightDecreasedByOne, - -1.0f / 3.0f, -data.upLeftPixelValue() + data.upRightPixelValue() - 2 * data.leftPixelValue() + 2 * data.rightPixelValue(), - -1.0f / 2.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() - data.upRightPixelValue() + data.leftPixelValue() + 2 * data.centerPixelValue() + data.rightPixelValue()); + // Bottom row + offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) { + data.bottomRow(offset, normalVector); + inlineSetPixel(offset, data, paintingData, x, data.heightDecreasedByOne, cFactor1div3, cFactor1div2, normalVector); } } if (height >= 3) { - // Left line - data.offset = data.widthMultipliedByPixelSize; - for (int y = 1; y < data.heightDecreasedByOne; ++y, data.offset += data.widthMultipliedByPixelSize) { - setPixel(data, paintingData, 0, y, - -1.0f / 2.0f, -data.upPixelValue() + data.upRightPixelValue() - 2 * data.centerPixelValue() + 2 * data.rightPixelValue() - data.downPixelValue() + data.downRightPixelValue(), - -1.0f / 3.0f, -2 * data.upPixelValue() - data.upRightPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + // Left column + offset = data.widthMultipliedByPixelSize; + for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize) { + data.leftColumn(offset, normalVector); + inlineSetPixel(offset, data, paintingData, 0, y, cFactor1div2, cFactor1div3, normalVector); } - // Right line - data.offset = data.widthMultipliedByPixelSize + data.widthMultipliedByPixelSize - cPixelSize; - for (int y = 1; y < data.heightDecreasedByOne; ++y, data.offset += data.widthMultipliedByPixelSize) { - setPixel(data, paintingData, data.widthDecreasedByOne, y, - -1.0f / 2.0f, -data.upLeftPixelValue() + data.upPixelValue() -2 * data.leftPixelValue() + 2 * data.centerPixelValue() - data.downLeftPixelValue() + data.downPixelValue(), - -1.0f / 3.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue()); + // Right column + offset = (data.widthMultipliedByPixelSize << 1) - cPixelSize; + for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize) { + data.rightColumn(offset, normalVector); + inlineSetPixel(offset, data, paintingData, data.widthDecreasedByOne, y, cFactor1div2, cFactor1div3, normalVector); } } if (width >= 3 && height >= 3) { // Interior pixels for (int y = 1; y < data.heightDecreasedByOne; ++y) { - data.offset = y * data.widthMultipliedByPixelSize + cPixelSize; - for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) { - setPixel(data, paintingData, x, y, - -1.0f / 4.0f, -data.upLeftPixelValue() + data.upRightPixelValue() - 2 * data.leftPixelValue() + 2 * data.rightPixelValue() - data.downLeftPixelValue() + data.downRightPixelValue(), - -1.0f / 4.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() - data.upRightPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + offset = y * data.widthMultipliedByPixelSize + cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) { + data.interior(offset, normalVector); + inlineSetPixel(offset, data, paintingData, x, y, cFactor1div4, cFactor1div4, normalVector); } } } - int totalSize = data.widthMultipliedByPixelSize * height; + int lastPixel = data.widthMultipliedByPixelSize * height; if (m_lightingType == DiffuseLighting) { - for (int i = 3; i < totalSize; i += 4) + for (int i = cAlphaChannelOffset; i < lastPixel; i += cPixelSize) data.pixels->set(i, cOpaqueAlpha); } else { - for (int i = 0; i < totalSize; i += 4) { + for (int i = 0; i < lastPixel; i += cPixelSize) { unsigned char a1 = data.pixels->get(i); unsigned char a2 = data.pixels->get(i + 1); unsigned char a3 = data.pixels->get(i + 2); @@ -253,8 +342,8 @@ void FELighting::apply(Filter* filter) setIsAlphaImage(false); IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); - RefPtr<ImageData> srcImageData(in->resultImage()->getUnmultipliedImageData(effectDrawingRect)); - CanvasPixelArray* srcPixelArray(srcImageData->data()); + RefPtr<ImageData> srcImageData = in->resultImage()->getUnmultipliedImageData(effectDrawingRect); + ByteArray* srcPixelArray = srcImageData->data()->data(); // FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3 // standard has no test case for them, and other browsers (like Firefox) has strange diff --git a/WebCore/platform/graphics/filters/FELighting.h b/WebCore/platform/graphics/filters/FELighting.h index bd56cee..c0f62ab 100644 --- a/WebCore/platform/graphics/filters/FELighting.h +++ b/WebCore/platform/graphics/filters/FELighting.h @@ -32,14 +32,12 @@ #include "Filter.h" #include "FilterEffect.h" #include "LightSource.h" -#include <wtf/AlwaysInline.h> +#include <wtf/ByteArray.h> // Common base class for FEDiffuseLighting and FESpecularLighting namespace WebCore { -class CanvasPixelArray; - class FELighting : public FilterEffect { public: virtual void apply(Filter*); @@ -53,31 +51,33 @@ protected: }; struct LightingData { - FloatPoint3D normalVector; - CanvasPixelArray* pixels; - float lightStrength; + // This structure contains only read-only (SMP safe) data + ByteArray* pixels; float surfaceScale; - int offset; int widthMultipliedByPixelSize; int widthDecreasedByOne; int heightDecreasedByOne; - ALWAYS_INLINE int upLeftPixelValue(); - ALWAYS_INLINE int upPixelValue(); - ALWAYS_INLINE int upRightPixelValue(); - ALWAYS_INLINE int leftPixelValue(); - ALWAYS_INLINE int centerPixelValue(); - ALWAYS_INLINE int rightPixelValue(); - ALWAYS_INLINE int downLeftPixelValue(); - ALWAYS_INLINE int downPixelValue(); - ALWAYS_INLINE int downRightPixelValue(); + inline void topLeft(int offset, IntPoint& normalVector); + inline void topRow(int offset, IntPoint& normalVector); + inline void topRight(int offset, IntPoint& normalVector); + inline void leftColumn(int offset, IntPoint& normalVector); + inline void interior(int offset, IntPoint& normalVector); + inline void rightColumn(int offset, IntPoint& normalVector); + inline void bottomLeft(int offset, IntPoint& normalVector); + inline void bottomRow(int offset, IntPoint& normalVector); + inline void bottomRight(int offset, IntPoint& normalVector); }; FELighting(LightingType, const Color&, float, float, float, float, float, float, PassRefPtr<LightSource>); - bool drawLighting(CanvasPixelArray*, int, int); - ALWAYS_INLINE void setPixel(LightingData&, LightSource::PaintingData&, - int lightX, int lightY, float factorX, int normalX, float factorY, int normalY); + bool drawLighting(ByteArray*, int, int); + inline void inlineSetPixel(int offset, LightingData&, LightSource::PaintingData&, + int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector); + + // Not worth to inline every occurence of setPixel. + void setPixel(int offset, LightingData&, LightSource::PaintingData&, + int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector); LightingType m_lightingType; RefPtr<LightSource> m_lightSource; diff --git a/WebCore/platform/graphics/filters/LightSource.cpp b/WebCore/platform/graphics/filters/LightSource.cpp index a80b14b..de0691e 100644 --- a/WebCore/platform/graphics/filters/LightSource.cpp +++ b/WebCore/platform/graphics/filters/LightSource.cpp @@ -42,7 +42,7 @@ void PointLightSource::updatePaintingData(PaintingData& paintingData, int x, int paintingData.lightVector.setX(m_position.x() - x); paintingData.lightVector.setY(m_position.y() - y); paintingData.lightVector.setZ(m_position.z() - z); - paintingData.lightVector.normalize(); + paintingData.lightVectorLength = paintingData.lightVector.length(); } // spot-light edge darkening depends on an absolute treshold @@ -84,9 +84,9 @@ void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int paintingData.lightVector.setX(m_position.x() - x); paintingData.lightVector.setY(m_position.y() - y); paintingData.lightVector.setZ(m_position.z() - z); - paintingData.lightVector.normalize(); + paintingData.lightVectorLength = paintingData.lightVector.length(); - float cosineOfAngle = paintingData.lightVector * paintingData.directionVector; + float cosineOfAngle = (paintingData.lightVector * paintingData.directionVector) / paintingData.lightVectorLength; if (cosineOfAngle > paintingData.coneCutOffLimit) { // No light is produced, scanlines are not updated paintingData.colorVector.setX(0.0f); @@ -127,6 +127,7 @@ void DistantLightSource::initPaintingData(PaintingData& paintingData) paintingData.lightVector.setX(cosf(azimuth) * cosf(elevation)); paintingData.lightVector.setY(sinf(azimuth) * cosf(elevation)); paintingData.lightVector.setZ(sinf(elevation)); + paintingData.lightVectorLength = 1; } void DistantLightSource::updatePaintingData(PaintingData&, int, int, float) diff --git a/WebCore/platform/graphics/filters/LightSource.h b/WebCore/platform/graphics/filters/LightSource.h index 2e4c579..013e910 100644 --- a/WebCore/platform/graphics/filters/LightSource.h +++ b/WebCore/platform/graphics/filters/LightSource.h @@ -51,6 +51,7 @@ public: // SVGFELighting also use them FloatPoint3D lightVector; FloatPoint3D colorVector; + float lightVectorLength; // Private members FloatPoint3D directionVector; FloatPoint3D privateColorVector; diff --git a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp index 87a0b69..a230384 100644 --- a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp +++ b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp @@ -36,6 +36,7 @@ #include "AffineTransform.h" #include "Color.h" +#include "Extensions3D.h" #include "FloatRect.h" #include "GraphicsContext3D.h" #include "GraphicsTypes.h" @@ -52,6 +53,7 @@ namespace WebCore { PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(HostWindow* hostWindow) { GraphicsContext3D::Attributes attr; + attr.canRecoverFromContextLoss = false; // Canvas contexts can not handle lost contexts. RefPtr<GraphicsContext3D> context = GraphicsContext3D::create(attr, hostWindow); if (!context) return 0; @@ -178,18 +180,8 @@ void SharedGraphicsContext3D::readPixels(long x, long y, unsigned long width, un 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); + return m_context->getExtensions()->supports("GL_EXT_texture_format_BGRA8888") + && m_context->getExtensions()->supports("GL_EXT_read_format_bgra"); } Texture* SharedGraphicsContext3D::createTexture(NativeImagePtr ptr, Texture::Format format, int width, int height) diff --git a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h index 05008c2..86c64b4 100644 --- a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h +++ b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h @@ -100,10 +100,6 @@ 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); diff --git a/WebCore/platform/graphics/gpu/Texture.cpp b/WebCore/platform/graphics/gpu/Texture.cpp index 74807dc..18c9ead 100644 --- a/WebCore/platform/graphics/gpu/Texture.cpp +++ b/WebCore/platform/graphics/gpu/Texture.cpp @@ -34,6 +34,7 @@ #include "Texture.h" +#include "Extensions3D.h" #include "FloatRect.h" #include "GraphicsContext3D.h" #include "IntRect.h" @@ -69,8 +70,8 @@ static void convertFormat(GraphicsContext3D* context, Texture::Format format, un *glType = GraphicsContext3D::UNSIGNED_BYTE; break; case Texture::BGRA8: - if (context->supportsBGRA()) { - *glFormat = GraphicsContext3D::BGRA_EXT; + if (context->getExtensions()->supports("GL_EXT_texture_format_BGRA8888")) { + *glFormat = Extensions3D::BGRA_EXT; *glType = GraphicsContext3D::UNSIGNED_BYTE; } else { *glFormat = GraphicsContext3D::RGBA; diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp index 252abd7..6911b31 100644 --- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp +++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp @@ -416,12 +416,6 @@ void GraphicsContext::translate(float x, float y) notImplemented(); } -IntPoint GraphicsContext::origin() -{ - notImplemented(); - return IntPoint(0, 0); -} - void GraphicsContext::rotate(float radians) { if (paintingDisabled()) @@ -446,14 +440,6 @@ void GraphicsContext::clipOut(const IntRect& rect) notImplemented(); } -void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) -{ - if (paintingDisabled()) - return; - - notImplemented(); -} - void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) { if (paintingDisabled()) @@ -482,6 +468,12 @@ void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) { } +InterpolationQuality GraphicsContext::imageInterpolationQuality() const +{ + notImplemented(); + return InterpolationDefault; +} + void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) { notImplemented(); diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index 78d004a..ab6993f 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -36,6 +36,7 @@ #include "ArrayBufferView.h" #include "CanvasRenderingContext.h" #include <CoreGraphics/CGBitmapContext.h> +#include "Extensions3DOpenGL.h" #include "Float32Array.h" #include "GraphicsContext.h" #include "HTMLCanvasElement.h" diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm index aa754f2..15cae20 100644 --- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm +++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm @@ -147,6 +147,7 @@ void GraphicsContext::drawLineForTextChecking(const IntPoint& point, int width, break; } #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + // To support correction panel. case TextCheckingReplacementLineStyle: { // Constants for spelling pattern color. diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h index 3895a00..876bc16 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h @@ -173,6 +173,8 @@ private: bool isReadyForVideoSetup() const; + virtual float mediaTimeForTimeValue(float) const; + MediaPlayer* m_player; RetainPtr<QTMovie> m_qtMovie; RetainPtr<QTMovieView> m_qtMovieView; diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index 7b0e7af..06c7924 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -1540,6 +1540,15 @@ void MediaPlayerPrivate::setPreload(MediaPlayer::Preload preload) resumeLoad(); } +float MediaPlayerPrivate::mediaTimeForTimeValue(float timeValue) const +{ + if (!metaDataAvailable()) + return timeValue; + + QTTime qttime = createQTTime(timeValue); + return static_cast<float>(qttime.timeValue) / qttime.timeScale; +} + } // namespace WebCore @implementation WebCoreMovieObserver diff --git a/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp new file mode 100644 index 0000000..8c62e9d --- /dev/null +++ b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "Extensions3DOpenGL.h" + +#include "GraphicsContext3D.h" +#include <wtf/Vector.h> + +#if PLATFORM(MAC) +#include <OpenGL/gl.h> +#endif + +namespace WebCore { + +Extensions3DOpenGL::Extensions3DOpenGL() + : m_initializedAvailableExtensions(false) +{ +} + +Extensions3DOpenGL::~Extensions3DOpenGL() +{ +} + +bool Extensions3DOpenGL::supports(const String& name) +{ + // Note on support for BGRA: + // + // For OpenGL ES2.0, requires checking for + // GL_EXT_texture_format_BGRA8888 and GL_EXT_read_format_bgra. + // For desktop GL, BGRA has been supported since OpenGL 1.2. + // + // However, note that the GL ES2 extension requires the + // internalFormat to glTexImage2D() be GL_BGRA, while desktop GL + // will not accept GL_BGRA (must be GL_RGBA), so this must be + // checked on each platform. Desktop GL offers neither + // GL_EXT_texture_format_BGRA8888 or GL_EXT_read_format_bgra, so + // treat them as unsupported here. + if (!m_initializedAvailableExtensions) { + String extensionsString(reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS))); + Vector<String> availableExtensions; + extensionsString.split(" ", availableExtensions); + for (size_t i = 0; i < availableExtensions.size(); ++i) + m_availableExtensions.add(availableExtensions[i]); + m_initializedAvailableExtensions = true; + } + return m_availableExtensions.contains(name); +} + +int Extensions3DOpenGL::getGraphicsResetStatusARB() +{ + return GraphicsContext3D::NO_ERROR; +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h new file mode 100644 index 0000000..1b333b2 --- /dev/null +++ b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Extensions3DOpenGL_h +#define Extensions3DOpenGL_h + +#include "Extensions3D.h" + +#include "GraphicsContext3D.h" +#include <wtf/HashSet.h> +#include <wtf/text/StringHash.h> + +namespace WebCore { + +class Extensions3DOpenGL : public Extensions3D { +public: + virtual ~Extensions3DOpenGL(); + + // Extensions3D methods. + virtual bool supports(const String&); + virtual int getGraphicsResetStatusARB(); + +private: + // This class only needs to be instantiated by GraphicsContext3D implementations. + friend class GraphicsContext3D; + Extensions3DOpenGL(); + + bool m_initializedAvailableExtensions; + HashSet<String> m_availableExtensions; +}; + +} // namespace WebCore + +#endif // Extensions3DOpenGL_h diff --git a/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp index daf3b12..85089a0 100644 --- a/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp +++ b/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp @@ -33,6 +33,7 @@ #include "ArrayBufferView.h" #include "WebGLObject.h" #include "CanvasRenderingContext.h" +#include "Extensions3DOpenGL.h" #include "Float32Array.h" #include "GraphicsContext.h" #include "HTMLCanvasElement.h" @@ -568,12 +569,7 @@ void GraphicsContext3D::flush() 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); + ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, (GLuint) buffer); } void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, Platform3DObject texture, long level) @@ -1116,21 +1112,12 @@ void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target 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; @@ -1445,9 +1432,11 @@ void GraphicsContext3D::synthesizeGLError(unsigned long error) m_syntheticErrors.add(error); } -int GraphicsContext3D::getGraphicsResetStatusARB() +Extensions3D* GraphicsContext3D::getExtensions() { - return NO_ERROR; + if (!m_extensions) + m_extensions = adoptPtr(new Extensions3DOpenGL); + return m_extensions.get(); } } diff --git a/WebCore/platform/graphics/opengl/TextureMapperGL.cpp b/WebCore/platform/graphics/opengl/TextureMapperGL.cpp index 6527ce4..03f9b7c 100644 --- a/WebCore/platform/graphics/opengl/TextureMapperGL.cpp +++ b/WebCore/platform/graphics/opengl/TextureMapperGL.cpp @@ -30,8 +30,12 @@ #if defined(TEXMAP_OPENGL_ES_2) #include <GLES2/gl2.h> #elif OS(MAC_OS_X) +#include <AGL/agl.h> #include <gl.h> #else +#if OS(UNIX) +#include <GL/glx.h> +#endif #include <GL/gl.h> #endif @@ -90,6 +94,132 @@ inline static void debugGLCommand(const char* command, int line) #define GL_CMD(x) x #endif +static const GLuint gInVertexAttributeIndex = 0; + +struct TextureMapperGLData { + static struct ShaderInfo { + enum ShaderProgramIndex { + SimpleProgram, + OpacityAndMaskProgram, + TargetProgram, + + ProgramCount + }; + + enum ShaderVariableIndex { + InMatrixVariable, + InSourceMatrixVariable, + InMaskMatrixVariable, + OpacityVariable, + SourceTextureVariable, + MaskTextureVariable, + + VariableCount + }; + + struct ProgramInfo { + GLuint id; + GLint vars[VariableCount]; + }; + + GLint getUniformLocation(ShaderProgramIndex prog, ShaderVariableIndex var, const char* name) + { + return programs[prog].vars[var] = glGetUniformLocation(programs[prog].id, name); + } + + void createShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource, ShaderProgramIndex index) + { + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + GL_CMD(glShaderSource(vertexShader, 1, &vertexShaderSource, 0)) + GL_CMD(glShaderSource(fragmentShader, 1, &fragmentShaderSource, 0)) + GLuint programID = glCreateProgram(); + GL_CMD(glCompileShader(vertexShader)) + GL_CMD(glCompileShader(fragmentShader)) + GL_CMD(glAttachShader(programID, vertexShader)) + GL_CMD(glAttachShader(programID, fragmentShader)) + GL_CMD(glBindAttribLocation(programID, gInVertexAttributeIndex, "InVertex")) + GL_CMD(glLinkProgram(programID)) + programs[index].id = programID; +#ifdef PRINT_PROGRAM_INFO_LOG + char infoLog[1024]; + int len; + GL_CMD(glGetProgramInfoLog(programID, 1024, &len, infoLog)); + LOG(Graphics, "Compiled program for texture mapper. Log: %s\n", infoLog); +#endif + } + + ProgramInfo programs[ProgramCount]; + + } shaderInfo; + + struct DirectlyCompositedImageRepository { + struct Entry { + GLuint texture; + int refCount; + }; + HashMap<NativeImagePtr, Entry> imageToTexture; + + GLuint findOrCreate(NativeImagePtr image, bool& found) + { + HashMap<NativeImagePtr, Entry>::iterator it = imageToTexture.find(image); + found = false; + if (it != imageToTexture.end()) { + it->second.refCount++; + found = true; + return it->second.texture; + } + Entry entry; + GL_CMD(glGenTextures(1, &entry.texture)); + entry.refCount = 1; + imageToTexture.add(image, entry); + return entry.texture; + } + + bool deref(NativeImagePtr image) + { + HashMap<NativeImagePtr, Entry>::iterator it = imageToTexture.find(image); + if (it != imageToTexture.end()) { + if (it->second.refCount < 2) { + imageToTexture.remove(it); + return false; + } + } + return true; + } + + DirectlyCompositedImageRepository() + { + } + + ~DirectlyCompositedImageRepository() + { + for (HashMap<NativeImagePtr, Entry>::iterator it = imageToTexture.begin(); it != imageToTexture.end(); ++it) { + GLuint texture = it->second.texture; + if (texture) + GL_CMD(glDeleteTextures(1, &texture)); + } + + } + } directlyCompositedImages; + + TextureMapperGLData() + : currentProgram(TextureMapperGLData::ShaderInfo::TargetProgram) + { } + + TransformationMatrix projectionMatrix; + int currentProgram; + +#if OS(MAC_OS_X) + AGLContext aglContext; +#elif OS(UNIX) + Drawable glxDrawable; + GLXContext glxContext; +#endif +}; + +TextureMapperGLData::ShaderInfo TextureMapperGLData::shaderInfo; + class BitmapTextureGL : public BitmapTexture { public: virtual void destroy(); @@ -99,6 +229,7 @@ public: virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect); virtual void endPaint(); virtual void setContentsToImage(Image*); + ~BitmapTextureGL() { destroy(); } private: GLuint m_id; @@ -111,78 +242,32 @@ private: GLuint m_fbo; IntSize m_actualSize; bool m_surfaceNeedsReset; + TextureMapperGL* m_textureMapper; BitmapTextureGL() : m_id(0) , m_image(0) , m_opaque(false) , m_fbo(0) , m_surfaceNeedsReset(true) + , m_textureMapper(0) { } friend class TextureMapperGL; }; -static struct TexmapShaderInfo { - enum ShaderProgramIndex { - SimpleProgram, - OpacityAndMaskProgram, - TargetProgram, - NumPrograms - }; - - enum ShaderVariableIndex { - InMatrixVariable, - InSourceMatrixVariable, - InMaskMatrixVariable, - InVertexVariable, - - OpacityVariable, - SourceTextureVariable, - MaskTextureVariable, - NumVariables - }; - - struct ProgramInfo { - GLuint id; - GLint vars[NumVariables]; - }; - - GLint getUniformLocation(ShaderProgramIndex prog, ShaderVariableIndex var, const char* name) - { - return programs[prog].vars[var] = glGetUniformLocation(programs[prog].id, name); - } - - void createShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource, ShaderProgramIndex index) - { - GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); - GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - GL_CMD(glShaderSource(vertexShader, 1, &vertexShaderSource, 0)) - GL_CMD(glShaderSource(fragmentShader, 1, &fragmentShaderSource, 0)) - GLuint programID = glCreateProgram(); - GL_CMD(glCompileShader(vertexShader)) - GL_CMD(glCompileShader(fragmentShader)) - GL_CMD(glAttachShader(programID, vertexShader)) - GL_CMD(glAttachShader(programID, fragmentShader)) - GL_CMD(glBindAttribLocation(programID, 0, "InVertex")) - GL_CMD(glLinkProgram(programID)) - programs[index].id = programID; - } - - ProgramInfo programs[NumPrograms]; - -} gShaderInfo; - #define TEXMAP_GET_SHADER_VAR_LOCATION(prog, var) \ - if (gShaderInfo.getUniformLocation(TexmapShaderInfo::prog##Program, TexmapShaderInfo::var##Variable, #var) < 0) \ - LOG_ERROR("Couldn't find variable "#var" in program "#prog"\n"); -#define TEXMAP_BUILD_SHADER(program) gShaderInfo.createShaderProgram(vertexShaderSource##program, fragmentShaderSource##program, TexmapShaderInfo::program##Program); + if (TextureMapperGLData::shaderInfo.getUniformLocation(TextureMapperGLData::shaderInfo.prog##Program, TextureMapperGLData::shaderInfo.var##Variable, #var) < 0) \ + LOG_ERROR("Couldn't find variable "#var" in program "#prog"\n"); + +#define TEXMAP_BUILD_SHADER(program) \ + TextureMapperGLData::shaderInfo.createShaderProgram(vertexShaderSource##program, fragmentShaderSource##program, TextureMapperGLData::shaderInfo.program##Program); -TextureMapperGL::TextureMapperGL(GraphicsContext* context) - : TextureMapper(context) - , m_currentProgram(TexmapShaderInfo::TargetProgram) +TextureMapperGL::TextureMapperGL() + : m_data(new TextureMapperGLData) { static bool shadersCompiled = false; + obtainCurrentContext(); if (shadersCompiled) return; shadersCompiled = true; @@ -282,18 +367,18 @@ void TextureMapperGL::drawTexture(const BitmapTexture& texture, const IntRect& t const BitmapTextureGL& textureGL = static_cast<const BitmapTextureGL&>(texture); - TexmapShaderInfo::ShaderProgramIndex program; + TextureMapperGLData::ShaderInfo::ShaderProgramIndex program; if (maskTexture) - program = TexmapShaderInfo::OpacityAndMaskProgram; + program = TextureMapperGLData::ShaderInfo::OpacityAndMaskProgram; else - program = TexmapShaderInfo::SimpleProgram; + program = TextureMapperGLData::ShaderInfo::SimpleProgram; - const TexmapShaderInfo::ProgramInfo& programInfo = gShaderInfo.programs[program]; - if (m_currentProgram != program) { + const TextureMapperGLData::ShaderInfo::ProgramInfo& programInfo = data().shaderInfo.programs[program]; + if (data().currentProgram != program) { GL_CMD(glUseProgram(programInfo.id)) - GL_CMD(glDisableVertexAttribArray(gShaderInfo.programs[m_currentProgram].vars[TexmapShaderInfo::InVertexVariable])) - m_currentProgram = program; - GL_CMD(glEnableVertexAttribArray(programInfo.vars[TexmapShaderInfo::InVertexVariable])) + GL_CMD(glDisableVertexAttribArray(gInVertexAttributeIndex)) + data().currentProgram = program; + GL_CMD(glEnableVertexAttribArray(gInVertexAttributeIndex)) } GL_CMD(glDisable(GL_DEPTH_TEST)) @@ -305,7 +390,7 @@ void TextureMapperGL::drawTexture(const BitmapTexture& texture, const IntRect& t const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1}; GL_CMD(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, unitRect)) - TransformationMatrix matrix = TransformationMatrix(m_projectionMatrix).multLeft(modelViewMatrix).multLeft(TransformationMatrix( + TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multLeft(modelViewMatrix).multLeft(TransformationMatrix( targetRect.width(), 0, 0, 0, 0, targetRect.height(), 0, 0, 0, 0, 1, 0, @@ -321,10 +406,10 @@ void TextureMapperGL::drawTexture(const BitmapTexture& texture, const IntRect& t 0, textureGL.m_relativeSize.height(), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; - GL_CMD(glUniformMatrix4fv(programInfo.vars[TexmapShaderInfo::InMatrixVariable], 1, GL_FALSE, m4)) - GL_CMD(glUniformMatrix4fv(programInfo.vars[TexmapShaderInfo::InSourceMatrixVariable], 1, GL_FALSE, m4src)) - GL_CMD(glUniform1i(programInfo.vars[TexmapShaderInfo::SourceTextureVariable], 0)) - GL_CMD(glUniform1f(programInfo.vars[TexmapShaderInfo::OpacityVariable], opacity)) + GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InMatrixVariable], 1, GL_FALSE, m4)) + GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InSourceMatrixVariable], 1, GL_FALSE, m4src)) + GL_CMD(glUniform1i(programInfo.vars[TextureMapperGLData::ShaderInfo::SourceTextureVariable], 0)) + GL_CMD(glUniform1f(programInfo.vars[TextureMapperGLData::ShaderInfo::OpacityVariable], opacity)) if (maskTexture && maskTexture->isValid()) { const BitmapTextureGL* maskTextureGL = static_cast<const BitmapTextureGL*>(maskTexture); @@ -334,12 +419,11 @@ void TextureMapperGL::drawTexture(const BitmapTexture& texture, const IntRect& t 0, maskTextureGL->m_relativeSize.height(), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; - glUniformMatrix4fv(programInfo.vars[TexmapShaderInfo::InMaskMatrixVariable], 1, GL_FALSE, m4mask); - GL_CMD(glUniform1i(programInfo.vars[TexmapShaderInfo::MaskTextureVariable], 1)) + GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InMaskMatrixVariable], 1, GL_FALSE, m4mask)); + GL_CMD(glUniform1i(programInfo.vars[TextureMapperGLData::ShaderInfo::MaskTextureVariable], 1)) GL_CMD(glActiveTexture(GL_TEXTURE0)) } - if (textureGL.m_opaque && opacity > 0.99 && !maskTexture) GL_CMD(glDisable(GL_BLEND)) else { @@ -350,7 +434,6 @@ void TextureMapperGL::drawTexture(const BitmapTexture& texture, const IntRect& t GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)) } - const char* TextureMapperGL::type() const { return "OpenGL"; @@ -399,43 +482,6 @@ void BitmapTextureGL::endPaint() m_buffer.clear(); } -struct TexmapGLShaderTextures { - struct Entry { - GLuint texture; - int refCount; - }; - HashMap<NativeImagePtr, Entry> imageToTexture; - GLuint findOrCreate(NativeImagePtr image, bool& found) - { - HashMap<NativeImagePtr, Entry>::iterator it = imageToTexture.find(image); - found = false; - if (it != imageToTexture.end()) { - it->second.refCount++; - found = true; - return it->second.texture; - } - Entry entry; - GL_CMD(glGenTextures(1, &entry.texture)); - entry.refCount = 1; - imageToTexture.add(image, entry); - return entry.texture; - } - - bool deref(NativeImagePtr image) - { - HashMap<NativeImagePtr, Entry>::iterator it = imageToTexture.find(image); - if (it != imageToTexture.end()) { - if (it->second.refCount < 2) { - imageToTexture.remove(it); - return false; - } - } - return true; - } -}; - -static TexmapGLShaderTextures gTextureRepository; - void BitmapTextureGL::setContentsToImage(Image* image) { NativeImagePtr nativeImage = image ? image->nativeImageForCurrentFrame() : 0; @@ -448,7 +494,7 @@ void BitmapTextureGL::setContentsToImage(Image* image) if (nativeImage == m_image) return; bool found = false; - GLuint newTextureID = gTextureRepository.findOrCreate(nativeImage, found); + GLuint newTextureID = m_textureMapper->data().directlyCompositedImages.findOrCreate(nativeImage, found); if (newTextureID != m_id) { destroy(); m_id = newTextureID; @@ -464,7 +510,7 @@ void BitmapTextureGL::setContentsToImage(Image* image) void BitmapTextureGL::destroy() { - if (m_id && (!m_image || !gTextureRepository.deref(m_image))) + if (m_id && (!m_image || !m_textureMapper->data().directlyCompositedImages.deref(m_image))) GL_CMD(glDeleteTextures(1, &m_id)) if (m_fbo) GL_CMD(glDeleteFramebuffers(1, &m_fbo)) @@ -493,8 +539,32 @@ static inline TransformationMatrix createProjectionMatrix(const IntSize& size, b -1, flip ? 1 : -1, 0, 1); } -void TextureMapperGL::cleanup() +TextureMapperGL::~TextureMapperGL() { + makeContextCurrent(); + delete m_data; +} + +bool TextureMapperGL::makeContextCurrent() +{ +#if OS(MAC_OS_X) + return aglSetCurrentContext(data().aglContext); +#elif OS(UNIX) + Display* display = XOpenDisplay(0); + if (!display) + return false; + return glXMakeCurrent(display, data().glxDrawable, data().glxContext); +#endif +} + +void TextureMapperGL::obtainCurrentContext() +{ +#if OS(MAC_OS_X) + data().aglContext = aglGetCurrentContext(); +#elif OS(UNIX) + data().glxDrawable = glXGetCurrentDrawable(); + data().glxContext = glXGetCurrentContext(); +#endif } void TextureMapperGL::bindSurface(BitmapTexture *surfacePointer) @@ -503,6 +573,7 @@ void TextureMapperGL::bindSurface(BitmapTexture *surfacePointer) if (!surface) return; + TransformationMatrix matrix = createProjectionMatrix(surface->size(), false); matrix.translate(-surface->offset().x(), -surface->offset().y()); @@ -520,7 +591,7 @@ void TextureMapperGL::bindSurface(BitmapTexture *surfacePointer) } GL_CMD(glViewport(0, 0, surface->size().width(), surface->size().height())) - m_projectionMatrix = matrix; + data().projectionMatrix = matrix; } void TextureMapperGL::setClip(const IntRect& rect) @@ -540,8 +611,7 @@ void TextureMapperGL::paintToTarget(const BitmapTexture& aSurface, const IntSize surface.m_actualSize.width(), 0, 0, 0, 0, surface.m_actualSize.height(), 0, 0, 0, 0, 1, 0, - surface.offset().x(), surface.offset().y(), 0, 1 - ) + surface.offset().x(), surface.offset().y(), 0, 1) ); const GLfloat m4[] = { @@ -557,18 +627,18 @@ void TextureMapperGL::paintToTarget(const BitmapTexture& aSurface, const IntSize 0, 0, 0, 1}; // We already blended the alpha in; the result is premultiplied. - GL_CMD(glUseProgram(gShaderInfo.programs[TexmapShaderInfo::TargetProgram].id)) + GL_CMD(glUseProgram(data().shaderInfo.programs[TextureMapperGLData::ShaderInfo::TargetProgram].id)) GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, 0)) GL_CMD(glViewport(0, 0, surfaceSize.width(), surfaceSize.height())) GL_CMD(glDisable(GL_STENCIL_TEST)) - const TexmapShaderInfo::ProgramInfo& programInfo = gShaderInfo.programs[TexmapShaderInfo::TargetProgram]; - GL_CMD(glUniform1f(programInfo.vars[TexmapShaderInfo::OpacityVariable], opacity)) + const TextureMapperGLData::ShaderInfo::ProgramInfo& programInfo = data().shaderInfo.programs[TextureMapperGLData::ShaderInfo::TargetProgram]; + GL_CMD(glUniform1f(programInfo.vars[TextureMapperGLData::ShaderInfo::OpacityVariable], opacity)) GL_CMD(glActiveTexture(GL_TEXTURE0)) GL_CMD(glBindTexture(GL_TEXTURE_2D, surface.m_id)) - GL_CMD(glUniform1i(programInfo.vars[TexmapShaderInfo::SourceTextureVariable], 0)) - GL_CMD(glEnableVertexAttribArray(programInfo.vars[TexmapShaderInfo::InVertexVariable])) - GL_CMD(glUniformMatrix4fv(programInfo.vars[TexmapShaderInfo::InMatrixVariable], 1, GL_FALSE, m4)) - GL_CMD(glUniformMatrix4fv(programInfo.vars[TexmapShaderInfo::InSourceMatrixVariable], 1, GL_FALSE, m4src)) + GL_CMD(glUniform1i(programInfo.vars[TextureMapperGLData::ShaderInfo::SourceTextureVariable], 0)) + GL_CMD(glEnableVertexAttribArray(gInVertexAttributeIndex)) + GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InMatrixVariable], 1, GL_FALSE, m4)) + GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InSourceMatrixVariable], 1, GL_FALSE, m4src)) GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0)) const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1}; GL_CMD(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, unitRect)) @@ -577,15 +647,17 @@ void TextureMapperGL::paintToTarget(const BitmapTexture& aSurface, const IntSize setClip(visibleRect); GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)) - GL_CMD(glDisableVertexAttribArray(programInfo.vars[TexmapShaderInfo::InVertexVariable])) + GL_CMD(glDisableVertexAttribArray(0)) GL_CMD(glUseProgram(0)) GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0)) - m_currentProgram = TexmapShaderInfo::TargetProgram; + data().currentProgram = TextureMapperGLData::ShaderInfo::TargetProgram; } PassRefPtr<BitmapTexture> TextureMapperGL::createTexture() { - return adoptRef(new BitmapTextureGL()); + BitmapTextureGL* texture = new BitmapTextureGL(); + texture->m_textureMapper = this; + return adoptRef(texture); } }; diff --git a/WebCore/platform/graphics/opengl/TextureMapperGL.h b/WebCore/platform/graphics/opengl/TextureMapperGL.h index 7a12c72..8035abf 100644 --- a/WebCore/platform/graphics/opengl/TextureMapperGL.h +++ b/WebCore/platform/graphics/opengl/TextureMapperGL.h @@ -29,11 +29,13 @@ namespace WebCore { +class TextureMapperGLData; + // An OpenGL-ES2 implementation of TextureMapper. class TextureMapperGL : public TextureMapper { public: - TextureMapperGL(GraphicsContext* gc); - virtual ~TextureMapperGL() {} + TextureMapperGL(); + virtual ~TextureMapperGL(); // reimps from TextureMapper virtual void drawTexture(const BitmapTexture& texture, const IntRect&, const TransformationMatrix& transform, float opacity, const BitmapTexture* maskTexture); @@ -43,11 +45,17 @@ public: virtual bool allowSurfaceForRoot() const { return true; } virtual PassRefPtr<BitmapTexture> createTexture(); virtual const char* type() const; - virtual void cleanup(); + void obtainCurrentContext(); + bool makeContextCurrent(); + static PassOwnPtr<TextureMapperGL> create() + { + return new TextureMapperGL; + } private: - TransformationMatrix m_projectionMatrix; - int m_currentProgram; + inline TextureMapperGLData& data() { return *m_data; } + TextureMapperGLData* m_data; + friend class BitmapTextureGL; }; // An offscreen buffer to be rendered by software. diff --git a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp index 37fd8ad..0d16d4d 100644 --- a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp +++ b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp @@ -340,14 +340,6 @@ void GraphicsContext::clearRect(const FloatRect& rect) m_data->setCompositeOperation(op); } -void GraphicsContext::strokeRect(const FloatRect& rect) -{ - if (paintingDisabled()) - return; - - m_data->drawRect(rect, VG_STROKE_PATH); -} - void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) { if (paintingDisabled()) @@ -452,15 +444,6 @@ void GraphicsContext::translate(float dx, float dy) m_data->translate(dx, dy); } -IntPoint GraphicsContext::origin() -{ - if (paintingDisabled()) - return IntPoint(); - - AffineTransform transformation = m_data->transformation(); - return IntPoint(roundf(transformation.e()), roundf(transformation.f())); -} - void GraphicsContext::clipOut(const IntRect& rect) { if (paintingDisabled()) @@ -471,16 +454,6 @@ void GraphicsContext::clipOut(const IntRect& rect) m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule); } -void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) -{ - if (paintingDisabled()) - return; - - Path path; - path.addEllipse(rect); - m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule); -} - void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer) { if (paintingDisabled()) diff --git a/WebCore/platform/graphics/qt/Extensions3DQt.cpp b/WebCore/platform/graphics/qt/Extensions3DQt.cpp new file mode 100644 index 0000000..6a34671 --- /dev/null +++ b/WebCore/platform/graphics/qt/Extensions3DQt.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "Extensions3DQt.h" + +#include "GraphicsContext3D.h" + +namespace WebCore { + +Extensions3DQt::Extensions3DQt() +{ +} + +Extensions3DQt::~Extensions3DQt() +{ +} + +bool Extensions3DQt::supports(const String&) +{ + return false; +} + +int Extensions3DQt::getGraphicsResetStatusARB() +{ + return GraphicsContext3D::NO_ERROR; +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/qt/Extensions3DQt.h b/WebCore/platform/graphics/qt/Extensions3DQt.h new file mode 100644 index 0000000..29209ba --- /dev/null +++ b/WebCore/platform/graphics/qt/Extensions3DQt.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Extensions3DQt_h +#define Extensions3DQt_h + +#include "Extensions3D.h" + +namespace WebCore { + +class Extensions3DQt : public Extensions3D { +public: + virtual ~Extensions3DQt(); + + // Extensions3D methods. + virtual bool supports(const String&); + virtual int getGraphicsResetStatusARB(); + +private: + // This class only needs to be instantiated by GraphicsContext3D implementations. + friend class GraphicsContext3D; + Extensions3DQt(); +}; + +} // namespace WebCore + +#endif // Extensions3DQt_h diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index cda8606..26db220 100644 --- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -22,6 +22,7 @@ #include "WebGLObject.h" #include "CanvasRenderingContext.h" +#include "Extensions3DQt.h" #include "GraphicsContext.h" #include "HTMLCanvasElement.h" #include "HostWindow.h" @@ -253,6 +254,8 @@ public: QImage m_pixels; ListHashSet<unsigned long> m_syntheticErrors; + OwnPtr<Extensions3DQt> m_extensions; + private: void* getProcAddress(const String& proc); @@ -1632,6 +1635,13 @@ void GraphicsContext3D::synthesizeGLError(unsigned long error) m_internal->m_syntheticErrors.add(error); } +Extensions3D* GraphicsContext3D::getExtensions() +{ + if (!m_internal->m_extensions) + m_internal->m_extensions = adoptPtr(new Extensions3DQt); + return m_internal->m_extensions; +} + bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 50971b5..4f68577 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -504,16 +504,18 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin for (size_t i = 1; i < numPoints; ++i) path.lineTo(points[i]); path.setFillRule(Qt::WindingFill); - m_data->p()->setClipPath(path, Qt::IntersectClip); -} - -QPen GraphicsContext::pen() -{ - if (paintingDisabled()) - return QPen(); QPainter* p = m_data->p(); - return p->pen(); + + bool painterWasAntialiased = p->testRenderHint(QPainter::Antialiasing); + + if (painterWasAntialiased != antialiased) + p->setRenderHint(QPainter::Antialiasing, antialiased); + + p->setClipPath(path, Qt::IntersectClip); + + if (painterWasAntialiased != antialiased) + p->setRenderHint(QPainter::Antialiasing, painterWasAntialiased); } void GraphicsContext::fillPath() @@ -733,9 +735,21 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight); QPainter* p = m_data->p(); if (m_data->hasShadow()) { - p->translate(m_data->shadow.offset()); - p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color)); - p->translate(-m_data->shadow.offset()); + ContextShadow* shadow = contextShadow(); + + if (shadow->m_type != ContextShadow::BlurShadow) { + // We do not need any layer for simple shadow. + p->translate(m_data->shadow.offset()); + p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color)); + p->translate(-m_data->shadow.offset()); + } else { + QPainter* shadowPainter = shadow->beginShadowLayer(p, rect); + if (shadowPainter) { + shadowPainter->setCompositionMode(QPainter::CompositionMode_Source); + shadowPainter->fillPath(path.platformPath(), QColor(m_data->shadow.m_color)); + shadow->endShadowLayer(p); + } + } } p->fillPath(path.platformPath(), QColor(color)); } @@ -1128,14 +1142,6 @@ void GraphicsContext::translate(float x, float y) } } -IntPoint GraphicsContext::origin() -{ - if (paintingDisabled()) - return IntPoint(); - const QTransform &transform = m_data->p()->transform(); - return IntPoint(qRound(transform.dx()), qRound(transform.dy())); -} - void GraphicsContext::rotate(float radians) { if (paintingDisabled()) @@ -1186,28 +1192,6 @@ void GraphicsContext::clipOut(const IntRect& rect) } } -void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) -{ - if (paintingDisabled()) - return; - - QPainter* p = m_data->p(); - QPainterPath newClip; - newClip.setFillRule(Qt::OddEvenFill); - if (p->hasClipping()) { - newClip.addRect(m_data->clipBoundingRect()); - newClip.addEllipse(QRect(rect)); - p->setClipPath(newClip, Qt::IntersectClip); - } else { - QRect clipOutRect(rect); - QRect window(p->window()); - clipOutRect &= window; - newClip.addRect(window); - newClip.addEllipse(clipOutRect); - p->setClipPath(newClip); - } -} - void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) { diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index aa7ed2f..49387a2 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -37,12 +37,21 @@ #include <QtGui/qgraphicseffect.h> #include <QtGui/qgraphicsitem.h> #include <QtGui/qgraphicsscene.h> +#include <QtGui/qgraphicsview.h> #include <QtGui/qgraphicswidget.h> #include <QtGui/qpainter.h> #include <QtGui/qpixmap.h> #include <QtGui/qpixmapcache.h> #include <QtGui/qstyleoption.h> +#if ENABLE(TILED_BACKING_STORE) +#include "TiledBackingStore.h" +#include "TiledBackingStoreClient.h" + +// The minimum width/height for tiling. We use the same value as the Windows implementation. +#define GRAPHICS_LAYER_TILING_THRESHOLD 2000 +#endif + #define QT_DEBUG_RECACHE 0 #define QT_DEBUG_CACHEDUMP 0 @@ -112,7 +121,11 @@ public: }; #endif // QT_NO_GRAPHICSEFFECT -class GraphicsLayerQtImpl : public QGraphicsObject { +class GraphicsLayerQtImpl : public QGraphicsObject +#if ENABLE(TILED_BACKING_STORE) +, public virtual TiledBackingStoreClient +#endif +{ Q_OBJECT public: @@ -182,6 +195,16 @@ public: // ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP) void flushChanges(bool recursive = true, bool forceTransformUpdate = false); +#if ENABLE(TILED_BACKING_STORE) + // reimplementations from TiledBackingStoreClient + virtual void tiledBackingStorePaintBegin(); + virtual void tiledBackingStorePaint(GraphicsContext*, const IntRect&); + virtual void tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea); + virtual IntRect tiledBackingStoreContentsRect(); + virtual IntRect tiledBackingStoreVisibleRect(); + virtual Color tiledBackingStoreBackgroundColor() const; +#endif + public slots: // We need to notify the client (ie. the layer compositor) when the animation actually starts. void notifyAnimationStarted(); @@ -232,6 +255,10 @@ public: int m_changeMask; +#if ENABLE(TILED_BACKING_STORE) + TiledBackingStore* m_tiledBackingStore; +#endif + QSizeF m_size; struct { QPixmapCache::Key key; @@ -303,6 +330,9 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) , m_opacityAnimationRunning(false) , m_blockNotifySyncRequired(false) , m_changeMask(NoChanges) +#if ENABLE(TILED_BACKING_STORE) + , m_tiledBackingStore(0) +#endif #if ENABLE(3D_CANVAS) , m_gc3D(0) #endif @@ -330,7 +360,9 @@ GraphicsLayerQtImpl::~GraphicsLayerQtImpl() item->setParentItem(0); } } - +#if ENABLE(TILED_BACKING_STORE) + delete m_tiledBackingStore; +#endif #ifndef QT_NO_ANIMATION // We do, however, own the animations. QList<QWeakPointer<QAbstractAnimation> >::iterator it; @@ -352,6 +384,27 @@ QPixmap GraphicsLayerQtImpl::recache(const QRegion& regionToUpdate) if (!m_layer->drawsContent() || m_size.isEmpty() || !m_size.isValid()) return QPixmap(); +#if ENABLE(TILED_BACKING_STORE) + const bool requiresTiling = (m_state.drawsContent && m_currentContent.contentType == HTMLContentType) && (m_size.width() > GRAPHICS_LAYER_TILING_THRESHOLD || m_size.height() > GRAPHICS_LAYER_TILING_THRESHOLD); + if (requiresTiling && !m_tiledBackingStore) { + m_tiledBackingStore = new TiledBackingStore(this); + m_tiledBackingStore->setTileCreationDelay(0); + setFlag(ItemUsesExtendedStyleOption, true); + } else if (!requiresTiling && m_tiledBackingStore) { + delete m_tiledBackingStore; + m_tiledBackingStore = 0; + setFlag(ItemUsesExtendedStyleOption, false); + } + + if (m_tiledBackingStore) { + m_tiledBackingStore->adjustVisibleRect(); + const QVector<QRect> rects = regionToUpdate.rects(); + for (int i = 0; i < rects.size(); ++i) + m_tiledBackingStore->invalidate(rects[i]); + return QPixmap(); + } +#endif + QPixmap pixmap; QRegion region = regionToUpdate; if (QPixmapCache::find(m_backingStore.key, &pixmap)) { @@ -562,8 +615,15 @@ QRectF GraphicsLayerQtImpl::boundingRect() const void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { +#if ENABLE(TILED_BACKING_STORE) + // FIXME: There's currently no Qt API to know if a new region of an item is exposed outside of the paint event. + // Suggested for Qt: http://bugreports.qt.nokia.com/browse/QTBUG-14877. + if (m_tiledBackingStore) + m_tiledBackingStore->adjustVisibleRect(); +#endif + if (m_currentContent.backgroundColor.isValid()) - painter->fillRect(option->rect, QColor(m_currentContent.backgroundColor)); + painter->fillRect(option->exposedRect, QColor(m_currentContent.backgroundColor)); switch (m_currentContent.contentType) { case HTMLContentType: @@ -828,6 +888,56 @@ afterLayerChanges: } } +#if ENABLE(TILED_BACKING_STORE) +/* \reimp (TiledBackingStoreClient.h) +*/ +void GraphicsLayerQtImpl::tiledBackingStorePaintBegin() +{ +} + +/* \reimp (TiledBackingStoreClient.h) +*/ +void GraphicsLayerQtImpl::tiledBackingStorePaint(GraphicsContext* gc, const IntRect& rect) +{ + m_layer->paintGraphicsLayerContents(*gc, rect); +} + +/* \reimp (TiledBackingStoreClient.h) +*/ +void GraphicsLayerQtImpl::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea) +{ + for (int i = 0; i < paintedArea.size(); ++i) + update(QRectF(paintedArea[i])); +} + +/* \reimp (TiledBackingStoreClient.h) +*/ +IntRect GraphicsLayerQtImpl::tiledBackingStoreContentsRect() +{ + return m_layer->contentsRect(); +} + +/* \reimp (TiledBackingStoreClient.h) +*/ +Color GraphicsLayerQtImpl::tiledBackingStoreBackgroundColor() const +{ + if (m_currentContent.contentType == PixmapContentType && !m_currentContent.pixmap.hasAlphaChannel()) + return Color(0, 0, 0); + // We return a transparent color so that the tiles initialize with alpha. + return Color(0, 0, 0, 0); +} + +IntRect GraphicsLayerQtImpl::tiledBackingStoreVisibleRect() +{ + const QGraphicsView* view = scene()->views().isEmpty() ? 0 : scene()->views().first(); + if (!view) + return mapFromScene(scene()->sceneRect()).boundingRect().toAlignedRect(); + + // All we get is the viewport's visible region. We have to map it to the scene and then to item coordinates. + return mapFromScene(view->mapToScene(view->viewport()->visibleRegion().boundingRect()).boundingRect()).boundingRect().toAlignedRect(); +} +#endif + void GraphicsLayerQtImpl::notifyAnimationStarted() { // WebCore notifies javascript when the animation starts. Here we're letting it know. diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index 508ba6a..b686fef 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -134,10 +134,10 @@ bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) ASSERT(applier); QPainterPathStroker stroke; - GraphicsContext* gc = scratchContext(); - applier->strokeStyle(gc); + GraphicsContext* context = scratchContext(); + applier->strokeStyle(context); - QPen pen = gc->pen(); + QPen pen = context->platformContext()->pen(); stroke.setWidth(pen.widthF()); stroke.setCapStyle(pen.capStyle()); stroke.setJoinStyle(pen.joinStyle()); @@ -162,12 +162,12 @@ FloatRect Path::boundingRect() const FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) { - GraphicsContext* gc = scratchContext(); + GraphicsContext* context = scratchContext(); QPainterPathStroker stroke; if (applier) { - applier->strokeStyle(gc); + applier->strokeStyle(context); - QPen pen = gc->pen(); + QPen pen = context->platformContext()->pen(); stroke.setWidth(pen.widthF()); stroke.setCapStyle(pen.capStyle()); stroke.setJoinStyle(pen.joinStyle()); diff --git a/WebCore/platform/graphics/qt/TextureMapperQt.cpp b/WebCore/platform/graphics/qt/TextureMapperQt.cpp index 9236dae..6fdd7df 100644 --- a/WebCore/platform/graphics/qt/TextureMapperQt.cpp +++ b/WebCore/platform/graphics/qt/TextureMapperQt.cpp @@ -18,7 +18,7 @@ */ #include "config.h" -#include "texmap/TextureMapper.h" +#include "TextureMapperQt.h" #include <QtCore/qdebug.h> #include <QtGui/qpaintengine.h> @@ -30,45 +30,6 @@ namespace WebCore { -class BitmapTextureQt : public BitmapTexture { - friend class TextureMapperQt; -public: - BitmapTextureQt() {} - virtual void destroy(); - virtual IntSize size() const { return IntSize(m_pixmap.width(), m_pixmap.height()); } - virtual void reset(const IntSize&, bool opaque); - virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect); - virtual void endPaint(); - virtual void setContentsToImage(Image*); - virtual bool save(const String& path); - virtual bool isValid() const { return !m_pixmap.isNull(); } - virtual bool allowOfflineTextureUpload() const { return true; } - IntRect sourceRect() const { return IntRect(0, 0, contentSize().width(), contentSize().height()); } -private: - QPainter m_painter; - QPixmap m_pixmap; -}; - -class TextureMapperQt : public TextureMapper { -public: - virtual void drawTexture(const BitmapTexture& texture, const IntRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture); - virtual void bindSurface(BitmapTexture* surface); - virtual void setClip(const IntRect&); - virtual bool allowSurfaceForRoot() const { return false; } - TextureMapperQt(GraphicsContext* context); - virtual const char* type() const { return "TextureMapperQt"; } - virtual PassRefPtr<BitmapTexture> createTexture(); - - static void initialize(QPainter* painter) - { - painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false); - } - -private: - QPainter* m_painter; - RefPtr<BitmapTextureQt> m_currentSurface; -}; - void BitmapTextureQt::destroy() { if (m_pixmap.paintingActive()) @@ -117,18 +78,41 @@ void BitmapTextureQt::setContentsToImage(Image* image) m_pixmap = *pixmap; } +void BitmapTextureQt::pack() +{ + if (m_pixmap.isNull()) + return; + + m_image = m_pixmap.toImage(); + m_pixmap = QPixmap(); + m_isPacked = true; +} + +void BitmapTextureQt::unpack() +{ + m_isPacked = false; + if (m_image.isNull()) + return; + + m_pixmap = QPixmap::fromImage(m_image); + m_image = QImage(); +} + void TextureMapperQt::setClip(const IntRect& rect) { QPainter* painter = m_currentSurface ? &m_currentSurface->m_painter : m_painter; painter->setClipRect(rect); } -TextureMapperQt::TextureMapperQt(GraphicsContext* context) - : TextureMapper(context) - , m_painter(context->platformContext()) - , m_currentSurface(0) +TextureMapperQt::TextureMapperQt() + : m_currentSurface(0) { - TextureMapperQt::initialize(m_painter); +} + +void TextureMapperQt::setGraphicsContext(GraphicsContext* context) +{ + m_painter = context->platformContext(); + initialize(m_painter); } void TextureMapperQt::bindSurface(BitmapTexture* surface) @@ -178,21 +162,26 @@ void TextureMapperQt::drawTexture(const BitmapTexture& texture, const IntRect& t painter->setOpacity(prevOpacity); } -PassRefPtr<TextureMapper> TextureMapper::create(GraphicsContext* context) +PassOwnPtr<TextureMapper> TextureMapper::create(GraphicsContext* context) { #ifdef QT_OPENGL_LIB - if (context->platformContext()->paintEngine()->type() == QPaintEngine::OpenGL2) - return adoptRef(new TextureMapperGL(context)); + if (context && context->platformContext()->paintEngine()->type() == QPaintEngine::OpenGL2) + return new TextureMapperGL; #endif - return adoptRef(new TextureMapperQt(context)); + return new TextureMapperQt; } - PassRefPtr<BitmapTexture> TextureMapperQt::createTexture() { return adoptRef(new BitmapTextureQt()); } +BitmapTextureQt::BitmapTextureQt() + : m_isPacked(false) +{ + +} + #ifdef QT_OPENGL_LIB class RGBA32PremultimpliedBufferQt : public RGBA32PremultimpliedBuffer { public: diff --git a/WebCore/platform/graphics/qt/TextureMapperQt.h b/WebCore/platform/graphics/qt/TextureMapperQt.h new file mode 100644 index 0000000..e17b968 --- /dev/null +++ b/WebCore/platform/graphics/qt/TextureMapperQt.h @@ -0,0 +1,76 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "texmap/TextureMapper.h" + +#ifndef TextureMapperQt_h +#define TextureMapperQt_h + +namespace WebCore { + +class BitmapTextureQt : public BitmapTexture { + friend class TextureMapperQt; +public: + BitmapTextureQt(); + ~BitmapTextureQt() { destroy(); } + virtual void destroy(); + virtual IntSize size() const { return IntSize(m_pixmap.width(), m_pixmap.height()); } + virtual void reset(const IntSize&, bool opaque); + virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect); + virtual void endPaint(); + virtual void setContentsToImage(Image*); + virtual bool save(const String& path); + virtual bool isValid() const { return !m_pixmap.isNull() || !m_image.isNull(); } + IntRect sourceRect() const { return IntRect(0, 0, contentSize().width(), contentSize().height()); } + virtual void pack(); + virtual void unpack(); + virtual bool isPacked() const { return m_isPacked; } + +private: + QPainter m_painter; + QPixmap m_pixmap; + QImage m_image; + bool m_isPacked; +}; + +class TextureMapperQt : public TextureMapper { +public: + TextureMapperQt(); + + virtual void drawTexture(const BitmapTexture& texture, const IntRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture); + virtual void bindSurface(BitmapTexture* surface); + virtual void setClip(const IntRect&); + virtual void setGraphicsContext(GraphicsContext*); + virtual bool allowSurfaceForRoot() const { return false; } + virtual PassRefPtr<BitmapTexture> createTexture(); + + static void initialize(QPainter* painter) + { + painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false); + } + + static PassOwnPtr<TextureMapper> create() { return new TextureMapperQt; } + +private: + QPainter* m_painter; + RefPtr<BitmapTextureQt> m_currentSurface; +}; + +} +#endif diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp index c503307..d0dafb1 100644 --- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp @@ -48,7 +48,7 @@ bool GraphicsContext3D::getImageData(Image* image, return false; OwnPtr<NativeImageSkia> pixels; NativeImageSkia* skiaImage = 0; - AlphaOp neededAlphaOp = kAlphaDoNothing; + AlphaOp neededAlphaOp = AlphaDoNothing; if (image->data()) { ImageSource decoder(false); decoder.setData(image->data(), true); @@ -63,12 +63,12 @@ bool GraphicsContext3D::getImageData(Image* image, return false; skiaImage = pixels.get(); if (hasAlpha && premultiplyAlpha) - neededAlphaOp = kAlphaDoPremultiply; + neededAlphaOp = AlphaDoPremultiply; } else { // This is a special case for texImage2D with HTMLCanvasElement input. skiaImage = image->nativeImageForCurrentFrame(); if (!premultiplyAlpha) - neededAlphaOp = kAlphaDoUnmultiply; + neededAlphaOp = AlphaDoUnmultiply; } if (!skiaImage) return false; @@ -77,7 +77,7 @@ bool GraphicsContext3D::getImageData(Image* image, ASSERT(skiaImage->rowBytes() == skiaImage->width() * 4); outputVector.resize(skiaImage->rowBytes() * skiaImage->height()); return packPixels(reinterpret_cast<const uint8_t*>(skiaImage->getPixels()), - kSourceFormatBGRA8, skiaImage->width(), skiaImage->height(), 0, + SourceFormatBGRA8, skiaImage->width(), skiaImage->height(), 0, format, type, neededAlphaOp, outputVector.data()); } diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 4bc98fb..e506e5d 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -420,20 +420,6 @@ void GraphicsContext::clipOut(const Path& p) platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op); } -void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) -{ - if (paintingDisabled()) - return; - - SkRect oval(rect); - if (!isRectSkiaSafe(getCTM(), oval)) - return; - - SkPath path; - path.addOval(oval, SkPath::kCCW_Direction); - platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op); -} - void GraphicsContext::clipPath(WindRule clipRule) { if (paintingDisabled()) @@ -946,6 +932,11 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op) platformContext()->setXfermodeMode(WebCoreCompositeToSkiaComposite(op)); } +InterpolationQuality GraphicsContext::imageInterpolationQuality() const +{ + return platformContext()->interpolationQuality(); +} + void GraphicsContext::setImageInterpolationQuality(InterpolationQuality q) { platformContext()->setInterpolationQuality(q); diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index 6204597..d610c2a 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -34,6 +34,7 @@ #include "AffineTransform.h" #include "DrawingBuffer.h" +#include "Extensions3D.h" #include "GraphicsContext.h" #include "GraphicsContext3D.h" #include "ImageBuffer.h" @@ -861,7 +862,7 @@ void PlatformContextSkia::readbackHardwareToSoftware() const for (int y = 0; y < height; ++y) { uint32_t* pixels = bitmap.getAddr32(0, y); if (context->supportsBGRA()) - context->readPixels(0, height - 1 - y, width, 1, GraphicsContext3D::BGRA_EXT, GraphicsContext3D::UNSIGNED_BYTE, pixels); + context->readPixels(0, height - 1 - y, width, 1, Extensions3D::BGRA_EXT, GraphicsContext3D::UNSIGNED_BYTE, pixels); else { context->readPixels(0, height - 1 - y, width, 1, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels); for (int i = 0; i < width; ++i) { diff --git a/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp index 057bcfc..4698239 100644 --- a/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp +++ b/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp @@ -20,1077 +20,36 @@ #include "config.h" #include "GraphicsLayerTextureMapper.h" -#include "CurrentTime.h" -#include "FloatRect.h" -#include "GraphicsContext.h" -#include "HashMap.h" -#include "Image.h" -#include "RefCounted.h" -#include "TextureMapper.h" -#include "TextureMapperPlatformLayer.h" -#include "Timer.h" -#include "TransformOperations.h" -#include "TranslateTransformOperation.h" -#include "UnitBezier.h" - -#define DEBUG_TEXMAP_FPS 0 +#include "TextureMapperNode.h" namespace WebCore { -struct TexmapPaintOptions { - BitmapTexture* surface; - TextureMapper* textureMapper; - GraphicsContext* context; - TextureMapperNode* rootLayer; - float opacity; - IntRect scissorRect; - IntRect visibleRect; - bool isSurface; -}; -class TextureMapperCache { -public: - void mark(BitmapTexture* texture); - - class Entry { - public: - RefPtr<BitmapTexture> texture; - Entry() : previousCost(0) { } - inline int calculateCost() const - { - if (!texture || !texture->isValid()) - return 0; - const IntSize textureSize = texture->size(); - // an image's cost in bytes is width * height * bytes per pixel (4). - return textureSize.width() * textureSize.height() * 4; - } - Entry(BitmapTexture* newTexture) - : texture(newTexture) - { - } - bool operator==(const Entry& other) const { return texture == other.texture; } - int previousCost; - }; - - TextureMapperCache() : m_totalCost(0) {} - - void purge(); - Vector<Entry> m_data; - int m_totalCost; -#ifndef TEXMAP_TEXTURE_CACHE_KBS -#define TEXMAP_TEXTURE_CACHE_KBS 24 * 1024 -#endif - static const int MaxCost = TEXMAP_TEXTURE_CACHE_KBS * 1024; - static const int PurgeAmount = MaxCost / 4; -}; - - -void TextureMapperCache::purge() -{ - // If this is in the GL implementation, we need an active GL context, because we might call glDeleteTextures. - const int size = m_data.size(); - - if (m_totalCost <= TextureMapperCache::MaxCost) - return; - - // Ensure that we have the right count. It might be inaccurate if content changed size. - // We only do this when we're actually ready to purge. - m_totalCost = 0; - for (int i = 0; i < size; ++i) - m_totalCost += m_data[i].calculateCost(); - - for (int i = size-1; i >= 0 && m_totalCost > TextureMapperCache::MaxCost - TextureMapperCache::PurgeAmount; --i) { - Entry& entry = m_data[i]; - if (entry.texture->isLocked() || !entry.texture->isValid()) - continue; - m_totalCost -= entry.previousCost; - entry.texture->destroy(); - m_data.remove(i); - } -} - -void TextureMapperCache::mark(BitmapTexture* texture) -{ - if (!texture || !texture->isValid()) - return; - - Entry entry(texture); - size_t index = m_data.find(entry); - if (!index) - return; - - if (index < m_data.size()) - m_data.remove(index); - const int cost = entry.calculateCost(); - m_totalCost -= entry.previousCost; - m_totalCost += (entry.previousCost = cost); - m_data.prepend(entry); -} - -TextureMapperCache gTextureMapperCache; - -class TextureMapperCacheLock { -public: - TextureMapperCacheLock(BitmapTexture* texture) : m_texture(texture) - { - if (m_texture) - m_texture->lock(); - } - ~TextureMapperCacheLock() - { - if (m_texture) - m_texture->unlock(); - } - -private: - RefPtr<BitmapTexture> m_texture; -}; - -class TextureMapperNode : public TextureMapperContentLayer { - -public: - // This set of flags help us defer which properties of the layer have been - // modified by the compositor, so we can know what to look for in the next flush. - enum ChangeMask { - NoChanges = 0, - - ParentChange = (1L << 0), - ChildrenChange = (1L << 1), - MaskLayerChange = (1L << 2), - PositionChange = (1L << 3), - - AnchorPointChange = (1L << 4), - SizeChange = (1L << 5), - TransformChange = (1L << 6), - ContentChange = (1L << 7), - - ContentsOrientationChange = (1L << 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), - - ReplicaLayerChange = (1L << 20) - }; - - // The compositor lets us special-case images and colors, so we try to do so. - enum StaticContentType { HTMLContentType, DirectImageContentType, ColorContentType, MediaContentType, Canvas3DContentType}; - - TextureMapperNode* rootLayer(); - - TextureMapperNode(GraphicsLayerTextureMapper* newLayer); - virtual ~TextureMapperNode(); - - void clearDirectImage(); - void computeTransformations(); - IntSize nearestSurfaceSize() const; - void computeReplicaTransform(); - void computeLayerType(); - void computeLocalTransform(); - void flattenTo2DSpaceIfNecessary(); - void initializeTextureMapper(TextureMapper*); - void invalidateTransform(); - void notifyChange(ChangeMask); - void syncCompositingState(bool recurse); - void performPostSyncOperations(); - void setNeedsDisplay(); - void setNeedsDisplayInRect(IntRect); - virtual void cleanupTextureMapper(); - - void paintRecursive(TexmapPaintOptions options); - void paintSelf(const TexmapPaintOptions& options); - void uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect); - - int countDescendantsWithContent() const; - bool hasSurfaceDescendants() const; - - IntSize size() const { return m_size; } - - virtual void setPlatformLayerClient(TextureMapperLayerClient*); - virtual void paint(GraphicsContext*, const IntSize&, const IntRect& targetRect, const IntRect& exposedRect, const TransformationMatrix& transform, float opacity); - - static TextureMapperNode* toTextureMapperNode(GraphicsLayer*); -public: - GraphicsLayerTextureMapper* m_layer; - const char* m_lastTextureMapperType; - RefPtr<TextureMapper> m_lastTextureMapper; - struct TransformData { - TransformationMatrix base, target, replica, forDescendants, perspective, local; - IntRect targetBoundingRect; - float centerZ; - bool dirty, localDirty, perspectiveDirty; - IntRect boundingRectFromRoot; - TransformData() : dirty(true), localDirty(true), perspectiveDirty(true) { } - }; - - TransformData m_transforms; - - enum LayerType { - DefaultLayer, - RootLayer, - ScissorLayer, - ClipLayer, - TransparencyLayer - }; - - LayerType m_layerType; - - struct ContentData { - IntRect needsDisplayRect; - bool needsDisplay; - Color backgroundColor; - - StaticContentType contentType; - RefPtr<Image> image; - TextureMapperVideoLayer* media; - - ContentData() - : needsDisplay(false) - , contentType(HTMLContentType) - , image(0) - , media(0) - { - } - - }; - - inline IntRect targetRect() const - { - return m_currentContent.contentType == HTMLContentType ? entireRect() : m_state.contentsRect; - } - - inline IntRect entireRect() const - { - return IntRect(0, 0, m_size.width(), m_size.height()); - } - - inline IntRect replicaRect() const - { - return m_layerType == TransparencyLayer ? IntRect(0, 0, m_nearestSurfaceSize.width(), m_nearestSurfaceSize.height()) : entireRect(); - } - - RefPtr<BitmapTexture> m_texture; - RefPtr<BitmapTexture> m_surface, m_replicaSurface; - - ContentData m_pendingContent; - ContentData m_currentContent; - - Vector<TextureMapperNode*> m_children; - TextureMapperNode* m_parent; - TextureMapperNode* m_effectTarget; - int m_changeMask; - IntSize m_size, m_nearestSurfaceSize; - String m_name; - TextureMapperLayerClient* m_platformClient; - - struct State { - FloatPoint pos; - FloatPoint3D anchorPoint; - FloatSize size; - TransformationMatrix transform; - TransformationMatrix childrenTransform; - Color backgroundColor; - Color currentColor; - GraphicsLayer::CompositingCoordinatesOrientation geoOrientation; - GraphicsLayer::CompositingCoordinatesOrientation contentsOrientation; - float opacity; - IntRect contentsRect; - int descendantsWithContent; - TextureMapperNode* maskLayer; - TextureMapperNode* replicaLayer; - bool preserves3D; - bool masksToBounds; - bool drawsContent; - bool contentsOpaque; - bool backfaceVisibility; - bool visible; - bool dirty; - bool tiled; - bool hasSurfaceDescendants; - - State() - : opacity(1.f) - , descendantsWithContent(0) - , maskLayer(0) - , replicaLayer(0) - , preserves3D(false) - , masksToBounds(false) - , drawsContent(false) - , contentsOpaque(false) - , backfaceVisibility(false) - , visible(true) - , dirty(true) - , tiled(false) - , hasSurfaceDescendants(false) - { - } - }; - State m_state; -}; - -void TextureMapperNode::setNeedsDisplayInRect(IntRect rect) -{ - if (m_platformClient) { - if (m_state.hasSurfaceDescendants) { - m_platformClient->setNeedsDisplay(); - return; - } - rect.intersect(IntRect(0, 0, m_size.width(), m_size.height())); - if (rect.isEmpty()) - return; - m_platformClient->setNeedsDisplayInRect(rect); - return; - } - - if (!m_parent) - return; - - m_parent->setNeedsDisplayInRect(rect); -} - -void TextureMapperNode::setNeedsDisplay() -{ - if (m_effectTarget) - m_effectTarget->setNeedsDisplay(); - if (m_transforms.targetBoundingRect.isEmpty()) - return; - if (m_state.drawsContent || m_currentContent.contentType != HTMLContentType) - setNeedsDisplayInRect(m_transforms.targetBoundingRect); -} - - -void TextureMapperNode::setPlatformLayerClient(TextureMapperLayerClient* client) -{ - m_platformClient = client; -} - -static int compareGraphicsLayersZValue(const void* a, const void* b) -{ - typedef const TextureMapperNode* NodePtr; - const NodePtr* nodeA = static_cast<const NodePtr*>(a); - const NodePtr* nodeB = static_cast<const NodePtr*>(b); - return int(((*nodeA)->m_transforms.centerZ - (*nodeB)->m_transforms.centerZ) * 1000); -} -inline static void sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last) -{ - qsort(array.data(), array.size(), sizeof(TextureMapperNode*), compareGraphicsLayersZValue); -} - -bool TextureMapperNode::hasSurfaceDescendants() const -{ - if (m_layerType == ClipLayer || m_layerType == TransparencyLayer || m_state.replicaLayer) - return true; - const int size = m_children.size(); - for (int i = 0; i < size; ++i) { - if (TextureMapperNode* child = m_children[i]) { - if (child->hasSurfaceDescendants()) - return true; - } - } - return false; - -} - -void TextureMapperNode::paint(GraphicsContext* context, const IntSize& size, const IntRect& targetRect, const IntRect& exposedRect, const TransformationMatrix& transform, float opacity) -{ - ASSERT(m_layerType == RootLayer); - if (m_size.isEmpty()) - return; - -#if 0 - WTF::StopWatch stopWatch; - ("[TextureMapper] RootPaint!!\n"); -#endif - - RefPtr<TextureMapper> textureMapper = TextureMapper::create(context); - - if (textureMapper->type() != m_lastTextureMapperType) - gTextureMapperCache.m_data.clear(); - - m_lastTextureMapper = textureMapper; - TexmapPaintOptions opt; - opt.opacity = 1; - opt.rootLayer = this; - opt.scissorRect = targetRect; - opt.visibleRect = exposedRect; - opt.textureMapper = textureMapper.get(); - opt.context = textureMapper->graphicsContext(); - opt.surface = 0; - paintRecursive(opt); - - if (textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants) { - textureMapper->bindSurface(0); - textureMapper->paintToTarget(*m_surface.get(), size, transform, opacity * m_state.opacity, targetRect); - } - gTextureMapperCache.purge(); -} - -int TextureMapperNode::countDescendantsWithContent() const -{ - if (!m_state.visible || m_state.opacity < 0.001) - return 0; - int descendantsWithContent = (m_state.drawsContent || m_currentContent.contentType != HTMLContentType) ? 1 : 0; - - const int size = m_children.size(); - for (int i = 0; i < size; ++i) { - if (TextureMapperNode* child = m_children[i]) - descendantsWithContent += child->countDescendantsWithContent(); - } - - return descendantsWithContent; -} - -inline TextureMapperNode* TextureMapperNode::toTextureMapperNode(GraphicsLayer* layer) -{ - return layer ? static_cast<GraphicsLayerTextureMapper*>(layer)->m_node.get() : 0; -} - -void TextureMapperNode::computeLayerType() -{ - // calculate layer type. A layer can be one of the following: - // RootLayer: the top level. Draws to a framebuffer, and the target texture draws into the viewport. - // only one layer is the root layer. - // ScissorLayer: draws to the current framebuffer, and applies an extra scissor before drawing its children. - // A scissor layer is a layer with children that masks to bounds, is not a transparency layer, and has a rectangular clip. - // ClipLayer: creates a new framebuffer, the size of the layer, and then paints it to the enclosing BitmapTexture with the layer's transform/opacity. - // A clip layer is a layer that masks to bounds, doesn't preserve 3D, has children, and has a transparency/mask or a non-rectangular transform. - // TransparencyLayer: creates a new framebuffer idetical in size to the current framebuffer. Then draws the fb's texture to the current framebuffer with identity transform. - // Used for layers with children and transparency/mask that preserve 3D or don't mask to bounds. - // DefaultLayer: draws itself and its children directly to the current framebuffer. - // any layer that doesn't conform to the other rules is a DefaultLayer. - - const bool selfHasContent = m_state.drawsContent || (m_currentContent.contentType != HTMLContentType); - const bool hasDescendantsWithContent = m_state.descendantsWithContent - (selfHasContent ? 1 : 0); - const bool hasTransparency = m_state.opacity < 0.99 || m_state.maskLayer; - const bool hasReplica = m_state.replicaLayer; - m_layerType = DefaultLayer; - - // Layer has no parent, it must be a root layer. - if (!m_parent && !m_effectTarget) { - m_layerType = RootLayer; - return; - } - - // A layer with no contents is always a default layer. - if (!m_state.descendantsWithContent) - return; - - // A layer with content-descendants and a mask is always a clip layer. - if (hasDescendantsWithContent && m_state.maskLayer) { - m_layerType = ClipLayer; - return; - } - - // A masks-to bounds layer can be a clip or a scissor layer. It's a scissor layer only if it has a trivial clip (identity or translation), or if it has transparency. - // That's because a ClipLayer would create an intermediate drawing surface (FB) - we want to limit it to when it's actually necessary, i.e. transparency or non-trivial clip. - if (m_state.masksToBounds && hasDescendantsWithContent) { - if (hasTransparency || !m_state.transform.isIdentityOrTranslation() || m_parent->m_state.preserves3D) - m_layerType = ClipLayer; - else - m_layerType = ScissorLayer; - return; - } - - // We use a transparency layer when we have two of the following 3: replica, transparency, descendants with contents. - if ((hasReplica && hasDescendantsWithContent) || (hasReplica && hasTransparency) || (hasTransparency && m_state.descendantsWithContent > 1)) - m_layerType = TransparencyLayer; -} -void TextureMapperNode::initializeTextureMapper(TextureMapper* textureMapper) -{ - if (textureMapper->type() == m_lastTextureMapperType) - return; - m_surface = textureMapper->createTexture(); - m_replicaSurface = textureMapper->createTexture(); - m_texture = textureMapper->createTexture(); - gTextureMapperCache.mark(m_texture.get()); - m_lastTextureMapperType = textureMapper->type(); -} - -TextureMapperNode::TextureMapperNode(GraphicsLayerTextureMapper* newLayer) - : m_layer(newLayer) - , m_lastTextureMapperType(0) - , m_lastTextureMapper(0) - , m_layerType(DefaultLayer) - , m_surface(0) - , m_parent(0) - , m_effectTarget(0) - , m_changeMask(NoChanges) - , m_platformClient(0) -{ - -} - -TextureMapperNode* TextureMapperNode::rootLayer() -{ - if (m_effectTarget) - return m_effectTarget->rootLayer(); - if (m_parent) - return m_parent->rootLayer(); - return this; -} - -void TextureMapperNode::invalidateTransform() -{ - m_transforms.dirty = true; - if (m_layerType != ClipLayer) - m_state.dirty = true; - if (m_state.replicaLayer) - m_state.replicaLayer->invalidateTransform(); - const int size = m_children.size(); - for (int i = 0; i < size; ++i) { - if (TextureMapperNode* layer = m_children[i]) - layer->invalidateTransform(); - } -} - -void TextureMapperNode::computeLocalTransform() -{ - if (!m_transforms.localDirty) - return; - const float originX = m_state.anchorPoint.x() * m_size.width(); - const float originY = m_state.anchorPoint.y() * m_size.height(); - m_transforms.local = - TransformationMatrix() - .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z()) - .multLeft(m_state.transform) - .translate3d(-originX, -originY, -m_state.anchorPoint.z()); - m_transforms.localDirty = false; -} - -void TextureMapperNode::flattenTo2DSpaceIfNecessary() -{ - if (m_state.preserves3D) - return; - m_transforms.forDescendants.setM13(0); - m_transforms.forDescendants.setM23(0); - m_transforms.forDescendants.setM31(0); - m_transforms.forDescendants.setM32(0); - m_transforms.forDescendants.setM33(1); - m_transforms.forDescendants.setM34(0); - m_transforms.forDescendants.setM43(0); -} - -IntSize TextureMapperNode::nearestSurfaceSize() const -{ - if (m_layerType == ClipLayer || m_layerType == RootLayer) - return m_surface && !m_surface->size().isEmpty() ? m_surface->size() : m_size; - return m_parent->nearestSurfaceSize(); -} - -void TextureMapperNode::computeReplicaTransform() -{ - if (!m_state.replicaLayer) - return; - - m_nearestSurfaceSize = nearestSurfaceSize(); - - if (m_layerType != TransparencyLayer) { - m_transforms.replica = TransformationMatrix(m_transforms.target).multLeft(m_state.replicaLayer->m_transforms.local); - return; - } - - const float originX = m_transforms.target.m41(); - const float originY = m_transforms.target.m42(); - m_transforms.replica = - TransformationMatrix() - .translate(originX, originY) - .multLeft(m_state.replicaLayer->m_transforms.local) - .translate(-originX, -originY); -} - -void TextureMapperNode::computeTransformations() -{ - if (!m_transforms.dirty) - return; - - m_transforms.dirty = false; - if ((m_size.isEmpty() && m_state.masksToBounds)) - return; - - TextureMapperNode* parent = m_parent; - computeLocalTransform(); - - m_transforms.target = TransformationMatrix(parent ? parent->m_transforms.forDescendants : TransformationMatrix()).multLeft(m_transforms.local); - m_transforms.forDescendants = (m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target); - - if (m_effectTarget) - return; - - m_transforms.targetBoundingRect = IntRect(m_transforms.target.mapRect(entireRect())); - if (m_state.replicaLayer) - m_state.replicaLayer->computeTransformations(); - - flattenTo2DSpaceIfNecessary(); - - if (!m_state.backfaceVisibility && m_transforms.target.inverse().m33() < 0) { - m_state.visible = false; - return; - } - m_state.visible = true; - - if (parent && parent->m_state.preserves3D) - m_transforms.centerZ = m_transforms.target.mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z(); - - if (!m_children.size()) - return; - - if (m_state.childrenTransform.isIdentity()) - return; - - const FloatPoint centerPoint = FloatPoint(m_size.width() / 2, m_size.height() / 2); - if (m_transforms.perspectiveDirty) - m_transforms.perspective = TransformationMatrix() - .translate(centerPoint.x(), centerPoint.y()) - .multLeft(m_state.childrenTransform) - .translate(-centerPoint.x(), -centerPoint.y()); - m_transforms.perspectiveDirty = false; - m_transforms.forDescendants.multLeft(m_transforms.perspective); -} - -void TextureMapperNode::uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect) -{ - if (m_size.isEmpty() || !m_layer) { - m_texture->destroy(); - return; - } - - if (m_currentContent.contentType == DirectImageContentType) { - if (m_currentContent.image) - m_texture->setContentsToImage(m_currentContent.image.get()); - return; - } - - if (m_currentContent.contentType == MediaContentType) { - if (!m_currentContent.media) - return; - m_texture->reset(m_size, true); - PlatformGraphicsContext* platformContext = m_texture->beginPaintMedia(); - GraphicsContext context(platformContext); - m_currentContent.media->paint(&context); - m_texture->endPaint(); - return; - } - - const bool needsReset = (m_texture->contentSize() != m_size) || !m_texture->isValid(); - if ((m_currentContent.contentType != HTMLContentType) - || (!m_currentContent.needsDisplay && m_currentContent.needsDisplayRect.isEmpty() && !needsReset)) - return; - - IntRect dirtyRect = IntRect(0, 0, m_size.width(), m_size.height()); - if (!needsReset && !m_currentContent.needsDisplay) - dirtyRect.intersect(m_currentContent.needsDisplayRect); - if (needsReset) - m_texture->reset(m_size, m_state.contentsOpaque); - m_pendingContent.needsDisplayRect = IntRect(); - - { - GraphicsContext context(m_texture->beginPaint(dirtyRect)); - if (textureMapper && textureMapper->graphicsContext()) { - GraphicsContext* originalContext = textureMapper->graphicsContext(); - context.setImageInterpolationQuality(originalContext->imageInterpolationQuality()); - context.setTextDrawingMode(originalContext->textDrawingMode()); - } - m_layer->paintGraphicsLayerContents(context, dirtyRect); - } - m_texture->endPaint(); - m_currentContent.needsDisplay = false; - -} - -void TextureMapperNode::paintSelf(const TexmapPaintOptions& options) -{ - if (!m_layer || m_size.isEmpty() || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType)) - return; - - RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->m_texture : 0; - RefPtr<BitmapTexture> replicaMaskTexture = 0; - if (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer) - replicaMaskTexture = m_state.replicaLayer->m_state.maskLayer->m_texture; - - const float opacity = options.isSurface ? 1 : options.opacity; - - uploadTextureFromContent(options.textureMapper, options.visibleRect); - if (m_state.replicaLayer && !options.isSurface) - options.textureMapper->drawTexture(*m_texture.get(), replicaRect(), m_transforms.replica, - opacity * m_state.replicaLayer->m_state.opacity, - replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get()); - - const IntRect rect = m_layerType == ClipLayer ? entireRect() : targetRect(); - const TransformationMatrix transform = m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target; - options.textureMapper->drawTexture(*m_texture.get(), rect, transform, opacity, options.isSurface ? 0 : maskTexture.get()); -} - -void TextureMapperNode::paintRecursive(TexmapPaintOptions options) -{ - bool isDirty = m_state.dirty; - m_state.dirty = false; - - if ((m_size.isEmpty() && (m_state.masksToBounds - || m_children.isEmpty())) || !m_state.visible || options.opacity < 0.01 || m_state.opacity < 0.01) - return; - - initializeTextureMapper(options.textureMapper); - computeReplicaTransform(); - - if (m_state.maskLayer) { - m_state.maskLayer->initializeTextureMapper(options.textureMapper); - m_state.maskLayer->m_state.dirty = false; - } - - if (m_state.replicaLayer) { - m_state.replicaLayer->initializeTextureMapper(options.textureMapper); - m_state.replicaLayer->m_state.dirty = false; - if (m_state.replicaLayer->m_state.maskLayer) { - m_state.replicaLayer->m_state.maskLayer->initializeTextureMapper(options.textureMapper); - m_state.replicaLayer->m_state.maskLayer->m_state.dirty = false; - } - } - - TextureMapperNode* replica = m_state.replicaLayer; - const bool isSurface = (m_layerType == ClipLayer - || m_layerType == TransparencyLayer - || (m_layerType == RootLayer - && (options.textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants) - )); - if (isSurface) - uploadTextureFromContent(options.textureMapper, options.visibleRect); - const IntRect boundingRectfromNearestSurface = m_transforms.targetBoundingRect; - - options.opacity *= m_state.opacity; - - TexmapPaintOptions optionsForDescendants(options); - optionsForDescendants.opacity = isSurface ? 1 : options.opacity; - options.isSurface = isSurface; - - if (m_layerType == ClipLayer) { - optionsForDescendants.visibleRect = TransformationMatrix().translate(-boundingRectfromNearestSurface.x(), -boundingRectfromNearestSurface.y()).mapRect(options.visibleRect); - optionsForDescendants.scissorRect = IntRect(0, 0, m_size.width(), m_size.height()); - } - - if (m_layerType == ScissorLayer) - optionsForDescendants.scissorRect.intersect(m_transforms.targetBoundingRect); - options.textureMapper->setClip(optionsForDescendants.scissorRect); - - TextureMapperCacheLock(m_texture.get()); - TextureMapperCacheLock(m_surface.get()); - TextureMapperCacheLock(m_replicaSurface.get()); - - gTextureMapperCache.purge(); - - if (isSurface) { - ASSERT(m_surface); - if (!m_surface->isValid()) - isDirty = true; - if (m_state.tiled) { - m_surface->reset(options.visibleRect.size()); - m_surface->setOffset(options.visibleRect.location()); - } else if (isDirty) - m_surface->reset(m_layerType == TransparencyLayer ? options.surface->size() : m_size); - gTextureMapperCache.mark(m_surface.get()); - options.textureMapper->bindSurface(m_surface.get()); - - optionsForDescendants.surface = m_surface.get(); - } else if (m_surface) - m_surface->destroy(); - - RefPtr<BitmapTexture> maskTexture; - RefPtr<BitmapTexture> replicaMaskTexture; - if (TextureMapperNode* mask = m_state.maskLayer) { - mask->uploadTextureFromContent(options.textureMapper, options.visibleRect); - maskTexture = mask->m_texture; - } - - if (replica && replica->m_state.maskLayer) { - replica->m_state.maskLayer->uploadTextureFromContent(options.textureMapper, options.visibleRect); - replicaMaskTexture = replica->m_state.maskLayer->m_texture; - } - - int childrenSize = m_children.size(); - if (isDirty || !isSurface || m_state.tiled || !m_surface->isValid()) { - bool didPaintSelf = false; - if (!m_state.preserves3D || m_children.isEmpty()) { - paintSelf(options); - didPaintSelf = true; - } - - if (m_children.isEmpty() && !isSurface) - return; - - if (m_layerType == ScissorLayer) - optionsForDescendants.scissorRect.intersect(m_transforms.target.mapRect(IntRect(0, 0, m_size.width(), m_size.height()))); - - for (int i = 0; i < childrenSize; ++i) { - TextureMapperNode* layer = m_children[i]; - if (!layer) - continue; - - if (!didPaintSelf && layer->m_transforms.centerZ >= 0) { - paintSelf(options); - didPaintSelf = true; - } - layer->paintRecursive(optionsForDescendants); - if (isSurface) { - ASSERT(m_surface); - gTextureMapperCache.mark(m_surface.get()); - options.textureMapper->bindSurface(m_surface.get()); - } - } - if (!didPaintSelf) { - paintSelf(options); - didPaintSelf = true; - } - } - - if (m_layerType == RootLayer || m_layerType == DefaultLayer || m_layerType == ScissorLayer) - return; - - ASSERT(m_surface); - BitmapTexture& texture = *m_surface.get(); - if (replica) { - ASSERT(m_replicaSurface); - m_replicaSurface->reset(options.surface->size()); - m_replicaSurface->setOffset(options.surface->offset()); - gTextureMapperCache.mark(m_replicaSurface.get()); - options.textureMapper->bindSurface(m_replicaSurface.get()); - options.textureMapper->drawTexture(texture, replicaRect(), m_transforms.replica, replica->m_state.opacity, replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get()); - options.textureMapper->drawTexture(texture, IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), 1.0f, maskTexture.get()); - options.textureMapper->bindSurface(options.surface); - gTextureMapperCache.mark(options.surface); - options.textureMapper->drawTexture(*m_replicaSurface.get(), IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), options.opacity, 0); - return; - } - - options.textureMapper->bindSurface(options.surface); - options.textureMapper->drawTexture(texture, - m_layerType == TransparencyLayer ? IntRect(IntPoint(0, 0), options.surface->size()) : - targetRect(), - m_layerType == TransparencyLayer ? TransformationMatrix() : m_transforms.target, - options.opacity, maskTexture.get()); - gTextureMapperCache.mark(&texture); -} - -void TextureMapperNode::cleanupTextureMapper() -{ - if (m_texture) - m_texture->destroy(); - if (m_surface) - m_surface->destroy(); - if (m_replicaSurface) - m_replicaSurface->destroy(); - for (int i = 0; i < m_children.size(); ++i) { - if (m_children[i]) - m_children[i]->cleanupTextureMapper(); - } - if (m_lastTextureMapper) - m_lastTextureMapper->cleanup(); -} - -TextureMapperNode::~TextureMapperNode() +GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(GraphicsLayerClient* client) + : GraphicsLayer(client) + , m_node(new TextureMapperNode()) + , m_changeMask(0) { - setNeedsDisplay(); - { - const int childrenSize = m_children.size(); - for (int i = childrenSize-1; i >= 0; --i) { - ASSERT(m_children[i]->m_parent == this); - m_children[i]->m_parent = 0; - } - } - if (m_parent) - m_parent->m_children.remove(m_parent->m_children.find(this)); } -void TextureMapperNode::notifyChange(ChangeMask changeMask) +void GraphicsLayerTextureMapper::notifyChange(TextureMapperNode::ChangeMask changeMask) { m_changeMask |= changeMask; - if (!m_layer->client()) + if (!client()) return; - m_layer->client()->notifySyncRequired(m_layer); -} - -void TextureMapperNode::performPostSyncOperations() -{ - const LayerType prevLayerType = m_layerType; - computeLayerType(); - if (prevLayerType != m_layerType) - m_state.dirty = true; - if (m_transforms.dirty) - setNeedsDisplay(); - - computeTransformations(); - if (m_state.maskLayer && !m_state.dirty) - m_state.dirty = m_state.maskLayer->m_state.dirty; - if (m_state.replicaLayer && !m_state.dirty) - m_state.dirty = m_state.replicaLayer->m_state.dirty; - - const int size = m_children.size(); - - for (int i = size - 1; i >= 0; --i) { - TextureMapperNode* layer = m_children[i]; - - layer->performPostSyncOperations(); - if (!m_state.dirty) - m_state.dirty = layer->m_state.dirty; - } - m_state.hasSurfaceDescendants = hasSurfaceDescendants(); - if (m_state.dirty) - m_state.descendantsWithContent = countDescendantsWithContent(); - - if (m_state.preserves3D) - sortByZOrder(m_children, 0, size); - if (m_state.dirty) - setNeedsDisplay(); + client()->notifySyncRequired(this); } -void TextureMapperNode::syncCompositingState(bool recurse) +void GraphicsLayerTextureMapper::didSynchronize() { - bool needsToInvalidateTransform = false; - - if (!m_layer) - return; - - if (m_changeMask == NoChanges) - goto afterCurrentLayerSync; - - setNeedsDisplay(); - if (m_parent) - m_parent->m_state.dirty = true; - - if (m_currentContent.contentType == HTMLContentType && (m_changeMask & ParentChange)) { - // The WebCore compositor manages item ownership. We have to make sure graphicsview doesn't - // try to snatch that ownership. - - if (!m_layer->parent()) - m_parent = 0; - else - m_parent = toTextureMapperNode(m_layer->parent()); - - if (!m_layer->parent() && m_parent) { - size_t index = m_parent->m_children.find(this); - m_parent->m_children.remove(index); - } - - } - - if (m_changeMask & ChildrenChange) { - m_children.clear(); - for (size_t i = 0; i < m_layer->children().size(); ++i) { - if (TextureMapperNode* child = toTextureMapperNode(m_layer->children()[i])) { - if (!child) - continue; - m_children.append(child); - child->m_parent = this; - } - } - m_state.dirty = true; - } - - if (m_changeMask & (SizeChange | ContentsRectChange)) { - IntSize wantedSize = IntSize(m_layer->size().width(), m_layer->size().height()); - if (wantedSize.isEmpty() && m_pendingContent.contentType == HTMLContentType) - wantedSize = IntSize(m_layer->contentsRect().width(), m_layer->contentsRect().height()); - - if (wantedSize != m_size) { - m_size = IntSize(wantedSize.width(), wantedSize.height()); - if (m_platformClient) - m_platformClient->setSizeChanged(m_size); - const bool needsTiling = m_size.width() > 2000 || m_size.height() > 2000; - if (m_state.tiled != needsTiling) - m_state.tiled = needsTiling; - m_state.dirty = true; - } - } - - if (m_changeMask & MaskLayerChange) { - if (TextureMapperNode* layer = toTextureMapperNode(m_layer->maskLayer())) - layer->m_effectTarget = this; - } - - if (m_changeMask & ReplicaLayerChange) { - if (TextureMapperNode* layer = toTextureMapperNode(m_layer->replicaLayer())) - layer->m_effectTarget = this; - } - - if (m_changeMask & (TransformChange | SizeChange | AnchorPointChange | PositionChange)) - m_transforms.localDirty = true; - - if (m_changeMask & (ChildrenTransformChange | SizeChange)) - m_transforms.perspectiveDirty = true; - - if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | ContentsRectChange | BackfaceVisibilityChange | PositionChange | MaskLayerChange | DrawsContentChange | ContentChange | ReplicaLayerChange)) { - // Due to the differences between the way WebCore handles transforms and the way Qt handles transforms, - // all these elements affect the transforms of all the descendants. - needsToInvalidateTransform = true; - } - - if (m_changeMask & DisplayChange) - m_state.dirty = true; - - m_state.maskLayer = toTextureMapperNode(m_layer->maskLayer()); - m_state.replicaLayer = toTextureMapperNode(m_layer->replicaLayer()); - m_state.pos = m_layer->position(); - m_state.anchorPoint = m_layer->anchorPoint(); - m_state.size = m_layer->size(); - m_state.transform = m_layer->transform(); - m_state.contentsRect = m_layer->contentsRect(); - m_state.opacity = m_layer->opacity(); - m_state.contentsRect = m_layer->contentsRect(); - m_state.preserves3D = m_layer->preserves3D(); - m_state.masksToBounds = m_layer->masksToBounds(); - m_state.drawsContent = m_layer->drawsContent(); - m_state.contentsOpaque = m_layer->contentsOpaque(); - m_state.backfaceVisibility = m_layer->backfaceVisibility(); - m_state.childrenTransform = m_layer->childrenTransform(); - m_currentContent.contentType = m_pendingContent.contentType; - m_currentContent.image = m_pendingContent.image; - m_currentContent.media = m_pendingContent.media; - m_currentContent.backgroundColor = m_pendingContent.backgroundColor; - m_currentContent.needsDisplay = m_currentContent.needsDisplay || m_pendingContent.needsDisplay; - m_currentContent.needsDisplayRect.unite(m_pendingContent.needsDisplayRect); + m_syncQueued = false; + m_changeMask = 0; m_pendingContent.needsDisplay = false; m_pendingContent.needsDisplayRect = IntRect(); - m_changeMask = NoChanges; - afterCurrentLayerSync: - if (needsToInvalidateTransform) - invalidateTransform(); - - if (m_state.maskLayer) { - m_state.maskLayer->syncCompositingState(false); - if (m_state.maskLayer->m_size.isEmpty()) - m_state.maskLayer->m_size = m_size; - } - - if (m_state.replicaLayer) - m_state.replicaLayer->syncCompositingState(false); - -#if 0 - if (m_state.dirty && m_texture && m_texture->allowOfflineTextureUpload()) - uploadTextureFromContent(0); -#endif - - if (!recurse) - return; - - const int childrenSize = m_children.size(); - for (int i = childrenSize-1; i >= 0; --i) - m_children[i]->syncCompositingState(true); -} - -GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(GraphicsLayerClient* client) - : GraphicsLayer(client) - , m_node(new TextureMapperNode(this)) -{ } void GraphicsLayerTextureMapper::setName(const String& name) { - m_node->m_name = name; + GraphicsLayer::setName(name); } GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper() @@ -1101,25 +60,25 @@ GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper() */ void GraphicsLayerTextureMapper::setNeedsDisplay() { - m_node->m_pendingContent.needsDisplay = true; - m_node->notifyChange(TextureMapperNode::DisplayChange); + m_pendingContent.needsDisplay = true; + notifyChange(TextureMapperNode::DisplayChange); } /* \reimp (GraphicsLayer.h) */ void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect) { - if (m_node->m_pendingContent.needsDisplay) + if (m_pendingContent.needsDisplay) return; - m_node->m_pendingContent.needsDisplayRect.unite(IntRect(rect)); - m_node->notifyChange(TextureMapperNode::DisplayChange); + m_pendingContent.needsDisplayRect.unite(IntRect(rect)); + notifyChange(TextureMapperNode::DisplayChange); } /* \reimp (GraphicsLayer.h) */ void GraphicsLayerTextureMapper::setParent(GraphicsLayer* layer) { - m_node->notifyChange(TextureMapperNode::ParentChange); + notifyChange(TextureMapperNode::ParentChange); GraphicsLayer::setParent(layer); } @@ -1127,7 +86,7 @@ void GraphicsLayerTextureMapper::setParent(GraphicsLayer* layer) */ bool GraphicsLayerTextureMapper::setChildren(const Vector<GraphicsLayer*>& children) { - m_node->notifyChange(TextureMapperNode::ChildrenChange); + notifyChange(TextureMapperNode::ChildrenChange); return GraphicsLayer::setChildren(children); } @@ -1135,7 +94,7 @@ bool GraphicsLayerTextureMapper::setChildren(const Vector<GraphicsLayer*>& child */ void GraphicsLayerTextureMapper::addChild(GraphicsLayer* layer) { - m_node->notifyChange(TextureMapperNode::ChildrenChange); + notifyChange(TextureMapperNode::ChildrenChange); GraphicsLayer::addChild(layer); } @@ -1144,7 +103,7 @@ void GraphicsLayerTextureMapper::addChild(GraphicsLayer* layer) void GraphicsLayerTextureMapper::addChildAtIndex(GraphicsLayer* layer, int index) { GraphicsLayer::addChildAtIndex(layer, index); - m_node->notifyChange(TextureMapperNode::ChildrenChange); + notifyChange(TextureMapperNode::ChildrenChange); } /* \reimp (GraphicsLayer.h) @@ -1152,7 +111,7 @@ void GraphicsLayerTextureMapper::addChildAtIndex(GraphicsLayer* layer, int index void GraphicsLayerTextureMapper::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling) { GraphicsLayer::addChildAbove(layer, sibling); - m_node->notifyChange(TextureMapperNode::ChildrenChange); + notifyChange(TextureMapperNode::ChildrenChange); } /* \reimp (GraphicsLayer.h) @@ -1161,7 +120,7 @@ void GraphicsLayerTextureMapper::addChildBelow(GraphicsLayer* layer, GraphicsLay { GraphicsLayer::addChildBelow(layer, sibling); - m_node->notifyChange(TextureMapperNode::ChildrenChange); + notifyChange(TextureMapperNode::ChildrenChange); } /* \reimp (GraphicsLayer.h) @@ -1169,10 +128,9 @@ void GraphicsLayerTextureMapper::addChildBelow(GraphicsLayer* layer, GraphicsLay bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) { if (GraphicsLayer::replaceChild(oldChild, newChild)) { - m_node->notifyChange(TextureMapperNode::ChildrenChange); + notifyChange(TextureMapperNode::ChildrenChange); return true; } - return false; } @@ -1182,7 +140,7 @@ void GraphicsLayerTextureMapper::removeFromParent() { if (!parent()) return; - m_node->notifyChange(TextureMapperNode::ParentChange); + notifyChange(TextureMapperNode::ParentChange); GraphicsLayer::removeFromParent(); } @@ -1193,7 +151,7 @@ void GraphicsLayerTextureMapper::setMaskLayer(GraphicsLayer* value) if (value == maskLayer()) return; GraphicsLayer::setMaskLayer(value); - m_node->notifyChange(TextureMapperNode::MaskLayerChange); + notifyChange(TextureMapperNode::MaskLayerChange); } @@ -1204,7 +162,7 @@ void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value) if (value == replicaLayer()) return; GraphicsLayer::setReplicatedByLayer(value); - m_node->notifyChange(TextureMapperNode::ReplicaLayerChange); + notifyChange(TextureMapperNode::ReplicaLayerChange); } /* \reimp (GraphicsLayer.h) @@ -1214,7 +172,7 @@ void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value) if (value == position()) return; GraphicsLayer::setPosition(value); - m_node->notifyChange(TextureMapperNode::PositionChange); + notifyChange(TextureMapperNode::PositionChange); } /* \reimp (GraphicsLayer.h) @@ -1224,7 +182,7 @@ void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value) if (value == anchorPoint()) return; GraphicsLayer::setAnchorPoint(value); - m_node->notifyChange(TextureMapperNode::AnchorPointChange); + notifyChange(TextureMapperNode::AnchorPointChange); } /* \reimp (GraphicsLayer.h) @@ -1235,7 +193,7 @@ void GraphicsLayerTextureMapper::setSize(const FloatSize& value) return; GraphicsLayer::setSize(value); - m_node->notifyChange(TextureMapperNode::SizeChange); + notifyChange(TextureMapperNode::SizeChange); } /* \reimp (GraphicsLayer.h) @@ -1246,7 +204,7 @@ void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value) return; GraphicsLayer::setTransform(value); - m_node->notifyChange(TextureMapperNode::TransformChange); + notifyChange(TextureMapperNode::TransformChange); } /* \reimp (GraphicsLayer.h) @@ -1256,7 +214,7 @@ void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix if (value == childrenTransform()) return; GraphicsLayer::setChildrenTransform(value); - m_node->notifyChange(TextureMapperNode::ChildrenTransformChange); + notifyChange(TextureMapperNode::ChildrenTransformChange); } /* \reimp (GraphicsLayer.h) @@ -1266,7 +224,7 @@ void GraphicsLayerTextureMapper::setPreserves3D(bool value) if (value == preserves3D()) return; GraphicsLayer::setPreserves3D(value); - m_node->notifyChange(TextureMapperNode::Preserves3DChange); + notifyChange(TextureMapperNode::Preserves3DChange); } /* \reimp (GraphicsLayer.h) @@ -1276,7 +234,7 @@ void GraphicsLayerTextureMapper::setMasksToBounds(bool value) if (value == masksToBounds()) return; GraphicsLayer::setMasksToBounds(value); - m_node->notifyChange(TextureMapperNode::MasksToBoundsChange); + notifyChange(TextureMapperNode::MasksToBoundsChange); } /* \reimp (GraphicsLayer.h) @@ -1285,7 +243,7 @@ void GraphicsLayerTextureMapper::setDrawsContent(bool value) { if (value == drawsContent()) return; - m_node->notifyChange(TextureMapperNode::DrawsContentChange); + notifyChange(TextureMapperNode::DrawsContentChange); GraphicsLayer::setDrawsContent(value); } @@ -1293,22 +251,22 @@ void GraphicsLayerTextureMapper::setDrawsContent(bool value) */ void GraphicsLayerTextureMapper::setBackgroundColor(const Color& value) { - if (value == m_node->m_pendingContent.backgroundColor) + if (value == m_pendingContent.backgroundColor) return; - m_node->m_pendingContent.backgroundColor = value; + m_pendingContent.backgroundColor = value; GraphicsLayer::setBackgroundColor(value); - m_node->notifyChange(TextureMapperNode::BackgroundColorChange); + notifyChange(TextureMapperNode::BackgroundColorChange); } /* \reimp (GraphicsLayer.h) */ void GraphicsLayerTextureMapper::clearBackgroundColor() { - if (!m_node->m_pendingContent.backgroundColor.isValid()) + if (!m_pendingContent.backgroundColor.isValid()) return; - m_node->m_pendingContent.backgroundColor = Color(); + m_pendingContent.backgroundColor = Color(); GraphicsLayer::clearBackgroundColor(); - m_node->notifyChange(TextureMapperNode::BackgroundColorChange); + notifyChange(TextureMapperNode::BackgroundColorChange); } /* \reimp (GraphicsLayer.h) @@ -1317,7 +275,7 @@ void GraphicsLayerTextureMapper::setContentsOpaque(bool value) { if (value == contentsOpaque()) return; - m_node->notifyChange(TextureMapperNode::ContentsOpaqueChange); + notifyChange(TextureMapperNode::ContentsOpaqueChange); GraphicsLayer::setContentsOpaque(value); } @@ -1328,7 +286,7 @@ void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value) if (value == backfaceVisibility()) return; GraphicsLayer::setBackfaceVisibility(value); - m_node->notifyChange(TextureMapperNode::BackfaceVisibilityChange); + notifyChange(TextureMapperNode::BackfaceVisibilityChange); } /* \reimp (GraphicsLayer.h) @@ -1338,7 +296,7 @@ void GraphicsLayerTextureMapper::setOpacity(float value) if (value == opacity()) return; GraphicsLayer::setOpacity(value); - m_node->notifyChange(TextureMapperNode::OpacityChange); + notifyChange(TextureMapperNode::OpacityChange); } /* \reimp (GraphicsLayer.h) @@ -1348,16 +306,16 @@ void GraphicsLayerTextureMapper::setContentsRect(const IntRect& value) if (value == contentsRect()) return; GraphicsLayer::setContentsRect(value); - m_node->notifyChange(TextureMapperNode::ContentsRectChange); + notifyChange(TextureMapperNode::ContentsRectChange); } /* \reimp (GraphicsLayer.h) */ void GraphicsLayerTextureMapper::setContentsToImage(Image* image) { - m_node->notifyChange(TextureMapperNode::ContentChange); - m_node->m_pendingContent.contentType = image ? TextureMapperNode::DirectImageContentType : TextureMapperNode::HTMLContentType; - m_node->m_pendingContent.image = image; + notifyChange(TextureMapperNode::ContentChange); + m_pendingContent.contentType = image ? TextureMapperNode::DirectImageContentType : TextureMapperNode::HTMLContentType; + m_pendingContent.image = image; GraphicsLayer::setContentsToImage(image); } @@ -1365,9 +323,9 @@ void GraphicsLayerTextureMapper::setContentsToImage(Image* image) */ void GraphicsLayerTextureMapper::setContentsBackgroundColor(const Color& color) { - m_node->notifyChange(TextureMapperNode::ContentChange); - m_node->m_pendingContent.contentType = TextureMapperNode::ColorContentType; - m_node->m_pendingContent.backgroundColor = color; + notifyChange(TextureMapperNode::ContentChange); + m_pendingContent.contentType = TextureMapperNode::ColorContentType; + m_pendingContent.backgroundColor = color; GraphicsLayer::setContentsBackgroundColor(color); } @@ -1375,12 +333,12 @@ void GraphicsLayerTextureMapper::setContentsBackgroundColor(const Color& color) void GraphicsLayerTextureMapper::setContentsToMedia(PlatformLayer* media) { GraphicsLayer::setContentsToMedia(media); - m_node->notifyChange(TextureMapperNode::ContentChange); - m_node->m_pendingContent.contentType = media ? TextureMapperNode::MediaContentType : TextureMapperNode::HTMLContentType; + notifyChange(TextureMapperNode::ContentChange); + m_pendingContent.contentType = media ? TextureMapperNode::MediaContentType : TextureMapperNode::HTMLContentType; if (media) - m_node->m_pendingContent.media = static_cast<TextureMapperVideoLayer*>(media); + m_pendingContent.media = static_cast<TextureMapperVideoLayer*>(media); else - m_node->m_pendingContent.media = 0; + m_pendingContent.media = 0; } /* \reimp (GraphicsLayer.h) @@ -1389,7 +347,7 @@ void GraphicsLayerTextureMapper::setContentsOrientation(CompositingCoordinatesOr { if (contentsOrientation() == orientation) return; - m_node->notifyChange(TextureMapperNode::ContentsOrientationChange); + notifyChange(TextureMapperNode::ContentsOrientationChange); GraphicsLayer::setContentsOrientation(orientation); } @@ -1397,17 +355,14 @@ void GraphicsLayerTextureMapper::setContentsOrientation(CompositingCoordinatesOr */ void GraphicsLayerTextureMapper::syncCompositingStateForThisLayerOnly() { - m_node->syncCompositingState(false); - m_node->performPostSyncOperations(); + m_node->syncCompositingState(this, false); } /* \reimp (GraphicsLayer.h) */ void GraphicsLayerTextureMapper::syncCompositingState() { - GraphicsLayer::syncCompositingState(); - m_node->syncCompositingState(true); - m_node->performPostSyncOperations(); + m_node->syncCompositingState(this, true); } /* \reimp (GraphicsLayer.h) diff --git a/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h index 36ebd74..85fa3ee 100644 --- a/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h +++ b/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h @@ -24,13 +24,12 @@ #include "GraphicsLayer.h" #include "GraphicsLayerClient.h" #include "Image.h" +#include "TextureMapperNode.h" #if ENABLE(3D_CANVAS) #include "GraphicsContext3D.h" #endif -#define ENABLE_TEXMAP_ANIMATION 0 - namespace WebCore { class TextureMapperNode; @@ -85,12 +84,24 @@ public: virtual NativeLayer nativeLayer() const; virtual PlatformLayer* platformLayer() const; - virtual bool addAnimation(const KeyframeValueList&, const IntSize& /*boxSize*/, const Animation*, - const String& /*keyframesName*/, double /*timeOffset*/) { return false; } + virtual bool addAnimation(const KeyframeValueList&, const IntSize& /*boxSize*/, const Animation*, const String& /*keyframesName*/, double /*timeOffset*/) { return false; } + + void notifyChange(TextureMapperNode::ChangeMask changeMask); + inline TextureMapperNode::ContentData& pendingContent() { return m_pendingContent; } + inline int changeMask() const { return m_changeMask; } + void didSynchronize(); private: OwnPtr<TextureMapperNode> m_node; + bool m_syncQueued; + int m_changeMask; + TextureMapperNode::ContentData m_pendingContent; }; +inline static GraphicsLayerTextureMapper* toGraphicsLayerTextureMapper(GraphicsLayer* layer) +{ + return static_cast<GraphicsLayerTextureMapper*>(layer); +} + } #endif // GraphicsLayerTextureMapper_h diff --git a/WebCore/platform/graphics/texmap/TextureMapper.h b/WebCore/platform/graphics/texmap/TextureMapper.h index 03c1c6d..250125b 100644 --- a/WebCore/platform/graphics/texmap/TextureMapper.h +++ b/WebCore/platform/graphics/texmap/TextureMapper.h @@ -57,6 +57,10 @@ public: m_contentSize = size; } + virtual void pack() { } + virtual void unpack() { } + virtual bool isPacked() const { return false; } + virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect) = 0; virtual void endPaint() = 0; virtual PlatformGraphicsContext* beginPaintMedia() @@ -72,6 +76,9 @@ public: inline IntSize contentSize() const { return m_contentSize; } inline void setOffset(const IntPoint& o) { m_offset = o; } inline IntPoint offset() const { return m_offset; } + +protected: + private: int m_lockCount; IntSize m_contentSize; @@ -81,11 +88,11 @@ private: // A "context" class used to encapsulate accelerated texture mapping functions: i.e. drawing a texture // onto the screen or into another texture with a specified transform, opacity and mask. -class TextureMapper : public RefCounted<TextureMapper> { +class TextureMapper { friend class BitmapTexture; public: - static PassRefPtr<TextureMapper> create(GraphicsContext*); + static PassOwnPtr<TextureMapper> create(GraphicsContext* graphicsContext = 0); virtual ~TextureMapper() { } virtual void drawTexture(const BitmapTexture& texture, const IntRect& target, const TransformationMatrix& matrix = TransformationMatrix(), float opacity = 1.0f, const BitmapTexture* maskTexture = 0) = 0; @@ -97,20 +104,28 @@ public: drawTexture(texture, IntRect(0, 0, texture.contentSize().width(), texture.contentSize().height()), matrix, opacity, 0); } + virtual void setGraphicsContext(GraphicsContext*) { } virtual void setClip(const IntRect&) = 0; virtual bool allowSurfaceForRoot() const = 0; virtual PassRefPtr<BitmapTexture> createTexture() = 0; - virtual const char* type() const = 0; - virtual void cleanup() {} - GraphicsContext* graphicsContext() const - { - return m_gc; - } + void setImageInterpolationQuality(InterpolationQuality quality) { m_interpolationQuality = quality; } + void setTextDrawingMode(int mode) { m_textDrawingMode = mode; } + + InterpolationQuality imageInterpolationQuality() const { return m_interpolationQuality; } + int textDrawingMode() const { return m_textDrawingMode; } + + void setViewportSize(const IntSize&); protected: - TextureMapper(GraphicsContext* gc) : m_gc(gc) {} - GraphicsContext* m_gc; + TextureMapper() + : m_interpolationQuality(InterpolationDefault) + , m_textDrawingMode(cTextFill) + {} + +private: + InterpolationQuality m_interpolationQuality; + int m_textDrawingMode; }; }; diff --git a/WebCore/platform/graphics/texmap/TextureMapperNode.cpp b/WebCore/platform/graphics/texmap/TextureMapperNode.cpp new file mode 100644 index 0000000..09051f9 --- /dev/null +++ b/WebCore/platform/graphics/texmap/TextureMapperNode.cpp @@ -0,0 +1,877 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "TextureMapperNode.h" + +#include "GraphicsLayerTextureMapper.h" + +namespace WebCore { + +class TextureMapperCache { +public: + void mark(BitmapTexture* texture); + + class Entry { + public: + RefPtr<BitmapTexture> texture; + Entry() : previousCost(0) { } + inline int computeCost() const + { + if (!texture || !texture->isValid() || texture->isPacked()) + return 0; + const IntSize textureSize = texture->size(); + // An image's cost in bytes is width * height * bytes per pixel (4). + return textureSize.width() * textureSize.height() * 4; + } + Entry(BitmapTexture* newTexture) + : texture(newTexture) + { + } + bool operator==(const Entry& other) const { return texture == other.texture; } + int previousCost; + }; + + TextureMapperCache() + : m_totalCost(0) + { + } + + void purge(); + Vector<Entry> m_data; + int m_totalCost; +#ifndef TEXMAP_TEXTURE_CACHE_KBS +#define TEXMAP_TEXTURE_CACHE_KBS 24 * 1024 +#endif + static const int MaxCost = TEXMAP_TEXTURE_CACHE_KBS * 1024; + static const int PurgeAmount = MaxCost / 4; +}; + + +void TextureMapperCache::purge() +{ + const int size = m_data.size(); + + if (m_totalCost <= TextureMapperCache::MaxCost) + return; + + // Ensure that we have the right count. It might be inaccurate if content changed size. + // We only do this when we're actually ready to purge. + m_totalCost = 0; + for (int i = 0; i < size; ++i) + m_totalCost += m_data[i].computeCost(); + + for (int i = size-1; i >= 0 && m_totalCost > TextureMapperCache::MaxCost - TextureMapperCache::PurgeAmount; --i) { + Entry& entry = m_data[i]; + if (entry.texture->isLocked() || !entry.texture->isValid() || entry.texture->isPacked()) + continue; + m_totalCost -= entry.previousCost; + entry.texture->pack(); + m_data.remove(i); + } +} + +void TextureMapperCache::mark(BitmapTexture* texture) +{ + if (!texture || !texture->isValid()) + return; + + Entry entry(texture); + size_t index = m_data.find(entry); + if (!index) + return; + + int previousCost = 0; + + if (index < m_data.size()) { + previousCost = m_data[index].previousCost; + m_data.remove(index); + } + const int cost = entry.computeCost(); + m_totalCost -= previousCost; + m_totalCost += (entry.previousCost = cost); + m_data.prepend(entry); +} + +class TextureMapperCacheLock { +public: + TextureMapperCacheLock(BitmapTexture* texture) : m_texture(texture) + { + if (m_texture) + m_texture->lock(); + } + ~TextureMapperCacheLock() + { + if (m_texture) + m_texture->unlock(); + } + +private: + RefPtr<BitmapTexture> m_texture; +}; + + +TextureMapperCache* TextureMapperNode::cache() +{ + TextureMapperNode* root = rootLayer(); + if (!root) + return 0; + if (!root->m_cache) + root->m_cache = new TextureMapperCache; + return root->m_cache; +} + +void TextureMapperNode::setNeedsDisplayInRect(IntRect rect) +{ + if (m_platformClient) { + if (m_state.hasSurfaceDescendants) { + m_platformClient->setNeedsDisplay(); + return; + } + rect.intersect(IntRect(0, 0, m_size.width(), m_size.height())); + if (rect.isEmpty()) + return; + m_platformClient->setNeedsDisplayInRect(rect); + return; + } + + if (!m_parent) + return; + + m_parent->setNeedsDisplayInRect(rect); +} + +void TextureMapperNode::setNeedsDisplay() +{ + if (m_effectTarget) + m_effectTarget->setNeedsDisplay(); + if (m_transforms.targetBoundingRect.isEmpty()) + return; + if (m_state.drawsContent || m_currentContent.contentType != HTMLContentType) + setNeedsDisplayInRect(m_transforms.targetBoundingRect); +} + +void TextureMapperNode::setPlatformLayerClient(TextureMapperLayerClient* client) +{ + m_platformClient = client; +} + +int TextureMapperNode::compareGraphicsLayersZValue(const void* a, const void* b) +{ + typedef const TextureMapperNode* NodePtr; + const NodePtr* nodeA = static_cast<const NodePtr*>(a); + const NodePtr* nodeB = static_cast<const NodePtr*>(b); + return int(((*nodeA)->m_transforms.centerZ - (*nodeB)->m_transforms.centerZ) * 1000); +} + +void TextureMapperNode::sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last) +{ + qsort(array.data(), array.size(), sizeof(TextureMapperNode*), TextureMapperNode::compareGraphicsLayersZValue); +} + +bool TextureMapperNode::hasSurfaceDescendants() const +{ + if (m_layerType == ClipLayer || m_layerType == TransparencyLayer || m_state.replicaLayer) + return true; + + const int size = m_children.size(); + for (int i = 0; i < size; ++i) { + if (TextureMapperNode* child = m_children[i]) { + if (child->hasSurfaceDescendants()) + return true; + } + } + return false; +} + +int TextureMapperNode::countDescendantsWithContent() const +{ + if (!m_state.visible || m_state.opacity < 0.001) + return 0; + + int descendantsWithContent = (m_state.drawsContent || m_currentContent.contentType != HTMLContentType) ? 1 : 0; + + const int size = m_children.size(); + for (int i = 0; i < size; ++i) { + if (TextureMapperNode* child = m_children[i]) + descendantsWithContent += child->countDescendantsWithContent(); + } + + return descendantsWithContent; +} + +TextureMapperNode* TextureMapperNode::toTextureMapperNode(GraphicsLayer* layer) +{ + return layer ? static_cast<TextureMapperNode*>(layer->platformLayer()) : 0; +} + +void TextureMapperNode::computeLayerType() +{ + const bool selfHasContent = m_state.drawsContent || (m_currentContent.contentType != HTMLContentType); + const bool hasDescendantsWithContent = m_state.descendantsWithContent - (selfHasContent ? 1 : 0); + const bool hasTransparency = m_state.opacity < 0.99 || m_state.maskLayer; + const bool hasReplica = m_state.replicaLayer; + + // DefaultLayer: draws itself and its children directly to the current framebuffer. + // any layer that doesn't conform to the other rules is a DefaultLayer. + m_layerType = DefaultLayer; + + // RootLayer: the top level. Draws to a framebuffer, and the target texture draws into the viewport. + // only one layer is the root layer. + if (!m_parent && !m_effectTarget) { + m_layerType = RootLayer; + return; + } + + // A layer with no contents is always a default layer. + if (!m_state.descendantsWithContent) + return; + + // ClipLayer: creates a new framebuffer, the size of the layer, and then paints it to the enclosing BitmapTexture with the layer's transform/opacity. + // A clip layer is a layer that masks to bounds, doesn't preserve 3D, has children, and has a transparency/mask or a non-rectangular transform. + if (hasDescendantsWithContent && m_state.maskLayer) { + m_layerType = ClipLayer; + return; + } + + // ScissorLayer: draws to the current framebuffer, and applies an extra scissor before drawing its children. + // A scissor layer is a layer with children that masks to bounds, is not a transparency layer, and has a rectangular clip. + if (m_state.masksToBounds && hasDescendantsWithContent) { + if (hasTransparency || !m_state.transform.isIdentityOrTranslation() || m_parent->m_state.preserves3D) + m_layerType = ClipLayer; + else + m_layerType = ScissorLayer; + return; + } + + // TransparencyLayer: creates a new framebuffer idetical in size to the current framebuffer. Then draws the fb's texture to the current framebuffer with identity transform. + // Used for layers with children and transparency/mask that preserve 3D or don't mask to bounds. + if ((hasReplica && hasDescendantsWithContent) || (hasReplica && hasTransparency) || (hasTransparency && m_state.descendantsWithContent > 1)) + m_layerType = TransparencyLayer; +} + +void TextureMapperNode::initializeTextureMapper(TextureMapper* textureMapper) +{ + if (m_texture) + return; + m_surface = textureMapper->createTexture(); + m_replicaSurface = textureMapper->createTexture(); + m_texture = textureMapper->createTexture(); + cache()->mark(m_texture.get()); +} + +TextureMapperNode::TextureMapperNode() + : m_layerType(DefaultLayer) + , m_surface(0) + , m_parent(0) + , m_effectTarget(0) + , m_platformClient(0) + , m_cache(0) +{ +} + +TextureMapperNode* TextureMapperNode::rootLayer() +{ + if (m_effectTarget) + return m_effectTarget->rootLayer(); + if (m_parent) + return m_parent->rootLayer(); + return this; +} + +void TextureMapperNode::invalidateTransform() +{ + m_transforms.dirty = true; + if (m_layerType != ClipLayer) + m_state.dirty = true; + if (m_state.replicaLayer) + m_state.replicaLayer->invalidateTransform(); + const int size = m_children.size(); + for (int i = 0; i < size; ++i) { + if (TextureMapperNode* layer = m_children[i]) + layer->invalidateTransform(); + } +} + +void TextureMapperNode::computeLocalTransform() +{ + if (!m_transforms.localDirty) + return; + const float originX = m_state.anchorPoint.x() * m_size.width(); + const float originY = m_state.anchorPoint.y() * m_size.height(); + m_transforms.local = + TransformationMatrix() + .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z()) + .multLeft(m_state.transform) + .translate3d(-originX, -originY, -m_state.anchorPoint.z()); + m_transforms.localDirty = false; +} + +void TextureMapperNode::flattenTo2DSpaceIfNecessary() +{ + if (m_state.preserves3D) + return; + + m_transforms.forDescendants.setM13(0); + m_transforms.forDescendants.setM23(0); + m_transforms.forDescendants.setM31(0); + m_transforms.forDescendants.setM32(0); + m_transforms.forDescendants.setM33(1); + m_transforms.forDescendants.setM34(0); + m_transforms.forDescendants.setM43(0); +} + +IntSize TextureMapperNode::nearestSurfaceSize() const +{ + if (m_layerType == ClipLayer || m_layerType == RootLayer) + return m_surface && !m_surface->size().isEmpty() ? m_surface->size() : m_size; + return m_parent->nearestSurfaceSize(); +} + +void TextureMapperNode::computeReplicaTransform() +{ + if (!m_state.replicaLayer) + return; + + m_nearestSurfaceSize = nearestSurfaceSize(); + + if (m_layerType != TransparencyLayer) { + m_transforms.replica = TransformationMatrix(m_transforms.target).multLeft(m_state.replicaLayer->m_transforms.local); + return; + } + + const float originX = m_transforms.target.m41(); + const float originY = m_transforms.target.m42(); + m_transforms.replica = + TransformationMatrix() + .translate(originX, originY) + .multLeft(m_state.replicaLayer->m_transforms.local) + .translate(-originX, -originY); +} + +void TextureMapperNode::computeTransformations() +{ + if (!m_transforms.dirty) + return; + + m_transforms.dirty = false; + if ((m_size.isEmpty() && m_state.masksToBounds)) + return; + + TextureMapperNode* parent = m_parent; + computeLocalTransform(); + + m_transforms.target = TransformationMatrix(parent ? parent->m_transforms.forDescendants : TransformationMatrix()).multLeft(m_transforms.local); + m_transforms.forDescendants = (m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target); + + if (m_effectTarget) + return; + + m_transforms.targetBoundingRect = IntRect(m_transforms.target.mapRect(entireRect())); + if (m_state.replicaLayer) + m_state.replicaLayer->computeTransformations(); + + flattenTo2DSpaceIfNecessary(); + + if (!m_state.backfaceVisibility && m_transforms.target.inverse().m33() < 0) { + m_state.visible = false; + return; + } + m_state.visible = true; + + if (parent && parent->m_state.preserves3D) + m_transforms.centerZ = m_transforms.target.mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z(); + + if (!m_children.size()) + return; + + if (m_state.childrenTransform.isIdentity()) + return; + + const FloatPoint centerPoint = FloatPoint(m_size.width() / 2, m_size.height() / 2); + if (m_transforms.perspectiveDirty) + m_transforms.perspective = TransformationMatrix() + .translate(centerPoint.x(), centerPoint.y()) + .multLeft(m_state.childrenTransform) + .translate(-centerPoint.x(), -centerPoint.y()); + m_transforms.perspectiveDirty = false; + m_transforms.forDescendants.multLeft(m_transforms.perspective); +} + +void TextureMapperNode::uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect, GraphicsLayer* layer) +{ + if (m_size.isEmpty() || !layer) { + m_texture->destroy(); + return; + } + + if (m_currentContent.contentType == DirectImageContentType) { + if (m_currentContent.image) + m_texture->setContentsToImage(m_currentContent.image.get()); + return; + } + + if (m_currentContent.contentType == MediaContentType) { + if (!m_currentContent.media) + return; + m_texture->reset(m_size, true); + PlatformGraphicsContext* platformContext = m_texture->beginPaintMedia(); + GraphicsContext context(platformContext); + m_currentContent.media->paint(&context); + m_texture->endPaint(); + return; + } + + const bool needsReset = (m_texture->contentSize() != m_size) || !m_texture->isValid(); + if ((m_currentContent.contentType != HTMLContentType) + || (!m_currentContent.needsDisplay && m_currentContent.needsDisplayRect.isEmpty() && !needsReset)) + return; + + IntRect dirtyRect = IntRect(0, 0, m_size.width(), m_size.height()); + if (!needsReset && !m_currentContent.needsDisplay) + dirtyRect.intersect(m_currentContent.needsDisplayRect); + + if (needsReset) + m_texture->reset(m_size, m_state.contentsOpaque); + + { + GraphicsContext context(m_texture->beginPaint(dirtyRect)); + if (textureMapper) { + context.setImageInterpolationQuality(textureMapper->imageInterpolationQuality()); + context.setTextDrawingMode(textureMapper->textDrawingMode()); + } + layer->paintGraphicsLayerContents(context, dirtyRect); + } + m_texture->endPaint(); + m_currentContent.needsDisplay = false; +} + + +void TextureMapperNode::paint(TextureMapper* textureMapper, const TextureMapperContentLayer::PaintOptions& options) +{ + ASSERT(m_layerType == RootLayer); + if (m_size.isEmpty()) + return; + + TexmapPaintOptions opt; + opt.opacity = 1; + opt.rootLayer = this; + opt.scissorRect = options.targetRect; + opt.visibleRect = options.visibleRect; + opt.textureMapper = textureMapper; + opt.surface = 0; + opt.cache = m_cache; + paintRecursive(opt); + + if (textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants) { + textureMapper->bindSurface(0); + textureMapper->paintToTarget(*m_surface.get(), options.viewportSize, options.transform, options.opacity * m_state.opacity, options.targetRect); + } + m_cache->purge(); +} + +void TextureMapperNode::paintSelf(const TexmapPaintOptions& options) +{ + if (m_size.isEmpty() || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType)) + return; + + RefPtr<BitmapTexture> replicaMaskTexture; + m_texture->unpack(); + + RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->m_texture : 0; + if (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer) + replicaMaskTexture = m_state.replicaLayer->m_state.maskLayer->m_texture; + + if (maskTexture) + maskTexture->unpack(); + + if (replicaMaskTexture) + replicaMaskTexture->unpack(); + + const float opacity = options.isSurface ? 1 : options.opacity; + + if (m_state.replicaLayer && !options.isSurface) + options.textureMapper->drawTexture(*m_texture.get(), replicaRect(), m_transforms.replica, + opacity * m_state.replicaLayer->m_state.opacity, + replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get()); + + const IntRect rect = m_layerType == ClipLayer ? entireRect() : targetRect(); + const TransformationMatrix transform = m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target; + options.textureMapper->drawTexture(*m_texture.get(), rect, transform, opacity, options.isSurface ? 0 : maskTexture.get()); + options.cache->mark(m_texture.get()); +} + +bool TextureMapperNode::paintReplica(const TexmapPaintOptions& options) +{ + BitmapTexture& texture = *m_surface.get(); + TextureMapperNode* replica = m_state.replicaLayer; + RefPtr<BitmapTexture> maskTexture; + if (TextureMapperNode* mask = m_state.maskLayer) + maskTexture = mask->m_texture; + RefPtr<BitmapTexture> replicaMaskTexture; + if (!replica) + return false; + + if (replica && replica->m_state.maskLayer) + replicaMaskTexture = replica->m_state.maskLayer->m_texture; + + if (replicaMaskTexture) + replicaMaskTexture->unpack(); + ASSERT(m_replicaSurface); + m_replicaSurface->reset(options.surface->size()); + m_replicaSurface->setOffset(options.surface->offset()); + options.cache->mark(m_replicaSurface.get()); + options.textureMapper->bindSurface(m_replicaSurface.get()); + options.textureMapper->drawTexture(texture, replicaRect(), m_transforms.replica, replica->m_state.opacity, replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get()); + options.textureMapper->drawTexture(texture, IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), 1.0f, maskTexture.get()); + options.textureMapper->bindSurface(options.surface); + options.cache->mark(options.surface); + options.textureMapper->drawTexture(*m_replicaSurface.get(), IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), options.opacity, 0); + return true; +} + +void TextureMapperNode::paintSurface(const TexmapPaintOptions& options) +{ + if (m_layerType == RootLayer || m_layerType == DefaultLayer || m_layerType == ScissorLayer) + return; + + RefPtr<BitmapTexture> maskTexture; + if (TextureMapperNode* mask = m_state.maskLayer) + maskTexture = mask->m_texture; + + ASSERT(m_surface); + BitmapTexture& texture = *m_surface.get(); + if (maskTexture) + maskTexture->unpack(); + texture.unpack(); + + if (paintReplica(options)) + return; + + options.textureMapper->bindSurface(options.surface); + options.textureMapper->drawTexture(texture, + m_layerType == TransparencyLayer ? IntRect(IntPoint(0, 0), options.surface->size()) : + targetRect(), + m_layerType == TransparencyLayer ? TransformationMatrix() : m_transforms.target, + options.opacity, maskTexture.get()); + options.cache->mark(&texture); +} + +void TextureMapperNode::paintSelfAndChildren(const TexmapPaintOptions& options, TexmapPaintOptions& optionsForDescendants) +{ + bool didPaintSelf = false; + if (!m_state.preserves3D || m_children.isEmpty()) { + paintSelf(options); + didPaintSelf = true; + } + + if (m_children.isEmpty() && !options.isSurface) + return; + + if (m_layerType == ScissorLayer) + optionsForDescendants.scissorRect.intersect(m_transforms.target.mapRect(IntRect(0, 0, m_size.width(), m_size.height()))); + + for (int i = 0; i < m_children.size(); ++i) { + TextureMapperNode* layer = m_children[i]; + if (!layer) + continue; + + if (!didPaintSelf && layer->m_transforms.centerZ >= 0) { + paintSelf(options); + didPaintSelf = true; + } + layer->paintRecursive(optionsForDescendants); + if (options.isSurface) { + ASSERT(m_surface); + options.cache->mark(m_surface.get()); + options.textureMapper->bindSurface(m_surface.get()); + } + } + if (!didPaintSelf) { + paintSelf(options); + didPaintSelf = true; + } +} + +void TextureMapperNode::paintRecursive(TexmapPaintOptions options) +{ + bool isDirty = m_state.dirty; + m_state.dirty = false; + + if ((m_size.isEmpty() && (m_state.masksToBounds + || m_children.isEmpty())) || !m_state.visible || options.opacity < 0.01 || m_state.opacity < 0.01) + return; + + computeReplicaTransform(); + + if (m_state.maskLayer) + m_state.maskLayer->m_state.dirty = false; + + if (m_state.replicaLayer) { + m_state.replicaLayer->m_state.dirty = false; + if (m_state.replicaLayer->m_state.maskLayer) + m_state.replicaLayer->m_state.maskLayer->m_state.dirty = false; + } + + const bool isSurface = (m_layerType == ClipLayer + || m_layerType == TransparencyLayer + || (m_layerType == RootLayer + && (options.textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants) + )); + + const IntRect boundingRectfromNearestSurface = m_transforms.targetBoundingRect; + + options.opacity *= m_state.opacity; + + TexmapPaintOptions optionsForDescendants(options); + optionsForDescendants.opacity = isSurface ? 1 : options.opacity; + options.isSurface = isSurface; + + if (m_layerType == ClipLayer) { + optionsForDescendants.visibleRect = TransformationMatrix().translate(-boundingRectfromNearestSurface.x(), -boundingRectfromNearestSurface.y()).mapRect(options.visibleRect); + optionsForDescendants.scissorRect = IntRect(0, 0, m_size.width(), m_size.height()); + } + + if (m_layerType == ScissorLayer) + optionsForDescendants.scissorRect.intersect(m_transforms.targetBoundingRect); + options.textureMapper->setClip(optionsForDescendants.scissorRect); + + TextureMapperCacheLock(m_texture.get()); + TextureMapperCacheLock(m_surface.get()); + TextureMapperCacheLock(m_replicaSurface.get()); + + options.cache->purge(); + + if (isSurface) { + ASSERT(m_surface); + if (!m_surface->isValid()) + isDirty = true; + if (m_state.tiled) { + m_surface->reset(options.visibleRect.size()); + m_surface->setOffset(options.visibleRect.location()); + } else if (isDirty) + m_surface->reset(m_layerType == TransparencyLayer ? options.surface->size() : m_size); + options.cache->mark(m_surface.get()); + options.textureMapper->bindSurface(m_surface.get()); + optionsForDescendants.surface = m_surface.get(); + } else if (m_surface) + m_surface->destroy(); + + if (isDirty || !isSurface || m_state.tiled || !m_surface->isValid()) + paintSelfAndChildren(options, optionsForDescendants); + + paintSurface(options); +} + +TextureMapperNode::~TextureMapperNode() +{ + setNeedsDisplay(); + { + const int childrenSize = m_children.size(); + for (int i = childrenSize-1; i >= 0; --i) { + ASSERT(m_children[i]->m_parent == this); + m_children[i]->m_parent = 0; + } + } + if (m_parent) + m_parent->m_children.remove(m_parent->m_children.find(this)); + if (m_cache) + delete m_cache; +} + +void TextureMapperNode::performPostSyncOperations() +{ + const LayerType prevLayerType = m_layerType; + computeLayerType(); + if (prevLayerType != m_layerType) + m_state.dirty = true; + if (m_transforms.dirty) + setNeedsDisplay(); + + computeTransformations(); + if (m_state.maskLayer && !m_state.dirty) + m_state.dirty = m_state.maskLayer->m_state.dirty; + if (m_state.replicaLayer && !m_state.dirty) + m_state.dirty = m_state.replicaLayer->m_state.dirty; + + const int size = m_children.size(); + + for (int i = size - 1; i >= 0; --i) { + TextureMapperNode* layer = m_children[i]; + + layer->performPostSyncOperations(); + if (!m_state.dirty) + m_state.dirty = layer->m_state.dirty; + } + m_state.hasSurfaceDescendants = hasSurfaceDescendants(); + if (m_state.dirty) + m_state.descendantsWithContent = countDescendantsWithContent(); + + if (m_state.preserves3D) + sortByZOrder(m_children, 0, size); + if (m_state.dirty) + setNeedsDisplay(); +} + +void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, bool recurse) +{ + TextureMapper* textureMapper = rootLayer()->m_platformClient->textureMapper(); + syncCompositingStateInternal(graphicsLayer, recurse, textureMapper); + performPostSyncOperations(); +} + +void TextureMapperNode::syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper) +{ + const int changeMask = graphicsLayer->changeMask(); + initializeTextureMapper(textureMapper); + const TextureMapperNode::ContentData& pendingContent = graphicsLayer->pendingContent(); + if (changeMask == NoChanges && pendingContent.needsDisplayRect.isEmpty() && !pendingContent.needsDisplay) + return; + + setNeedsDisplay(); + if (m_parent) + m_parent->m_state.dirty = true; + + if (m_currentContent.contentType == HTMLContentType && (changeMask & ParentChange)) { + // The WebCore compositor manages item ownership. We have to make sure graphicsview doesn't + // try to snatch that ownership. + + if (!graphicsLayer->parent()) + m_parent = 0; + else + m_parent = toTextureMapperNode(graphicsLayer->parent()); + + if (!graphicsLayer->parent() && m_parent) { + size_t index = m_parent->m_children.find(this); + m_parent->m_children.remove(index); + } + } + + if (changeMask & ChildrenChange) { + m_children.clear(); + for (size_t i = 0; i < graphicsLayer->children().size(); ++i) { + if (TextureMapperNode* child = toTextureMapperNode(graphicsLayer->children()[i])) { + if (!child) + continue; + m_children.append(child); + child->m_parent = this; + } + } + m_state.dirty = true; + } + + if (changeMask & (SizeChange | ContentsRectChange)) { + IntSize wantedSize = IntSize(graphicsLayer->size().width(), graphicsLayer->size().height()); + if (wantedSize.isEmpty() && pendingContent.contentType == HTMLContentType) + wantedSize = IntSize(graphicsLayer->contentsRect().width(), graphicsLayer->contentsRect().height()); + + if (wantedSize != m_size) { + m_size = IntSize(wantedSize.width(), wantedSize.height()); + if (m_platformClient) + m_platformClient->setSizeChanged(m_size); + const bool needsTiling = m_size.width() > 2000 || m_size.height() > 2000; + if (m_state.tiled != needsTiling) + m_state.tiled = needsTiling; + m_state.dirty = true; + } + } + + if (changeMask & MaskLayerChange) { + if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->maskLayer())) + layer->m_effectTarget = this; + } + + if (changeMask & ReplicaLayerChange) { + if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->replicaLayer())) + layer->m_effectTarget = this; + } + + if (changeMask & (TransformChange | SizeChange | AnchorPointChange | PositionChange)) + m_transforms.localDirty = true; + + if (changeMask & (ChildrenTransformChange | SizeChange)) + m_transforms.perspectiveDirty = true; + + if (changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | ContentsRectChange | BackfaceVisibilityChange | PositionChange | MaskLayerChange | DrawsContentChange | ContentChange | ReplicaLayerChange)) { + // Due to the differences between the way WebCore handles transforms and the way Qt handles transforms, + // all these elements affect the transforms of all the descendants. + invalidateTransform(); + } + + if (changeMask & DisplayChange) + m_state.dirty = true; + + m_state.maskLayer = toTextureMapperNode(graphicsLayer->maskLayer()); + m_state.replicaLayer = toTextureMapperNode(graphicsLayer->replicaLayer()); + m_state.pos = graphicsLayer->position(); + m_state.anchorPoint = graphicsLayer->anchorPoint(); + m_state.size = graphicsLayer->size(); + m_state.transform = graphicsLayer->transform(); + m_state.contentsRect = graphicsLayer->contentsRect(); + m_state.opacity = graphicsLayer->opacity(); + m_state.contentsRect = graphicsLayer->contentsRect(); + m_state.preserves3D = graphicsLayer->preserves3D(); + m_state.masksToBounds = graphicsLayer->masksToBounds(); + m_state.drawsContent = graphicsLayer->drawsContent(); + m_state.contentsOpaque = graphicsLayer->contentsOpaque(); + m_state.backfaceVisibility = graphicsLayer->backfaceVisibility(); + m_state.childrenTransform = graphicsLayer->childrenTransform(); + m_currentContent.contentType = pendingContent.contentType; + m_currentContent.image = pendingContent.image; + m_currentContent.media = pendingContent.media; + m_currentContent.backgroundColor = pendingContent.backgroundColor; + m_currentContent.needsDisplay = m_currentContent.needsDisplay || pendingContent.needsDisplay; + m_currentContent.needsDisplayRect.unite(pendingContent.needsDisplayRect); + +} + +void TextureMapperNode::syncCompositingStateInternal(GraphicsLayerTextureMapper* graphicsLayer, bool recurse, TextureMapper* textureMapper) +{ + syncCompositingStateSelf(graphicsLayer, textureMapper); + + graphicsLayer->didSynchronize(); + + if (m_state.maskLayer) { + m_state.maskLayer->syncCompositingStateInternal(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), false, textureMapper); + if (m_state.maskLayer->m_size.isEmpty()) + m_state.maskLayer->m_size = m_size; + } + + if (m_state.replicaLayer) + m_state.replicaLayer->syncCompositingStateInternal(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), false, textureMapper); + + if (m_state.dirty) + uploadTextureFromContent(textureMapper, m_state.visibleRect, graphicsLayer); + + m_currentContent.needsDisplayRect = IntRect(); + m_currentContent.needsDisplay = false; + + if (!recurse) + return; + + Vector<GraphicsLayer*> children = graphicsLayer->children(); + for (int i = children.size() - 1; i >= 0; --i) { + TextureMapperNode* node = toTextureMapperNode(children[i]); + if (!node) + continue; + node->syncCompositingStateInternal(toGraphicsLayerTextureMapper(children[i]), true, textureMapper); + } +} + +} diff --git a/WebCore/platform/graphics/texmap/TextureMapperNode.h b/WebCore/platform/graphics/texmap/TextureMapperNode.h new file mode 100644 index 0000000..9694043 --- /dev/null +++ b/WebCore/platform/graphics/texmap/TextureMapperNode.h @@ -0,0 +1,252 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef TextureMapperNode_h +#define TextureMapperNode_h + +#include "CurrentTime.h" +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "GraphicsLayer.h" +#include "HashMap.h" +#include "Image.h" +#include "RefCounted.h" +#include "TextureMapper.h" +#include "TextureMapperPlatformLayer.h" +#include "Timer.h" +#include "TransformOperations.h" +#include "TranslateTransformOperation.h" +#include "UnitBezier.h" + +namespace WebCore { + +class TextureMapperNode; +class TextureMapperCache; +class GraphicsLayerTextureMapper; + +struct TexmapPaintOptions { + BitmapTexture* surface; + TextureMapper* textureMapper; + TextureMapperNode* rootLayer; + float opacity; + IntRect scissorRect; + IntRect visibleRect; + bool isSurface; + TextureMapperCache* cache; +}; + +class TextureMapperNode : public TextureMapperContentLayer { + +public: + // This set of flags help us defer which properties of the layer have been + // modified by the compositor, so we can know what to look for in the next flush. + enum ChangeMask { + NoChanges = 0, + + ParentChange = (1L << 0), + ChildrenChange = (1L << 1), + MaskLayerChange = (1L << 2), + PositionChange = (1L << 3), + + AnchorPointChange = (1L << 4), + SizeChange = (1L << 5), + TransformChange = (1L << 6), + ContentChange = (1L << 7), + + ContentsOrientationChange = (1L << 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), + + ReplicaLayerChange = (1L << 20) + }; + // The compositor lets us special-case images and colors, so we try to do so. + enum ContentType { HTMLContentType, DirectImageContentType, ColorContentType, MediaContentType, Canvas3DContentType}; + struct ContentData { + IntRect needsDisplayRect; + bool needsDisplay; + Color backgroundColor; + + ContentType contentType; + RefPtr<Image> image; + TextureMapperVideoLayer* media; + + ContentData() + : needsDisplay(false) + , contentType(HTMLContentType) + , image(0) + , media(0) + { + } + }; + + + TextureMapperNode(); + virtual ~TextureMapperNode(); + + void syncCompositingState(GraphicsLayerTextureMapper*, bool recursive); + +protected: + // Reimps from TextureMapperContentLayer + virtual IntSize size() const { return m_size; } + virtual void setPlatformLayerClient(TextureMapperLayerClient*); + virtual void paint(TextureMapper*, const TextureMapperContentLayer::PaintOptions&); + +private: + TextureMapperNode* rootLayer(); + void clearDirectImage(); + void computeTransformations(); + IntSize nearestSurfaceSize() const; + void computeReplicaTransform(); + void computeLayerType(); + void computeLocalTransform(); + void flattenTo2DSpaceIfNecessary(); + void initializeTextureMapper(TextureMapper*); + void invalidateTransform(); + void notifyChange(ChangeMask); + void setNeedsDisplay(); + void setNeedsDisplayInRect(IntRect); + void performPostSyncOperations(); + void syncCompositingStateInternal(GraphicsLayerTextureMapper*, bool recursive, TextureMapper*); + void syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper); + TextureMapperCache* cache(); + + void paintRecursive(TexmapPaintOptions options); + bool paintReplica(const TexmapPaintOptions& options); + void paintSurface(const TexmapPaintOptions& options); + void paintSelf(const TexmapPaintOptions& options); + void paintSelfAndChildren(const TexmapPaintOptions& options, TexmapPaintOptions& optionsForDescendants); + void uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect, GraphicsLayer* layer); + + int countDescendantsWithContent() const; + bool hasSurfaceDescendants() const; + + TextureMapper* textureMapper(); + + + static TextureMapperNode* toTextureMapperNode(GraphicsLayer*); + static int compareGraphicsLayersZValue(const void* a, const void* b); + static void sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last); + struct TransformData { + TransformationMatrix base, target, replica, forDescendants, perspective, local; + IntRect targetBoundingRect; + float centerZ; + bool dirty, localDirty, perspectiveDirty; + IntRect boundingRectFromRoot; + TransformData() : dirty(true), localDirty(true), perspectiveDirty(true) { } + }; + + TransformData m_transforms; + + enum LayerType { + DefaultLayer, + RootLayer, + ScissorLayer, + ClipLayer, + TransparencyLayer + }; + + LayerType m_layerType; + + inline IntRect targetRect() const + { + return m_currentContent.contentType == HTMLContentType ? entireRect() : m_state.contentsRect; + } + + inline IntRect entireRect() const + { + return IntRect(0, 0, m_size.width(), m_size.height()); + } + + inline IntRect replicaRect() const + { + return m_layerType == TransparencyLayer ? IntRect(0, 0, m_nearestSurfaceSize.width(), m_nearestSurfaceSize.height()) : entireRect(); + } + + RefPtr<BitmapTexture> m_texture; + RefPtr<BitmapTexture> m_surface, m_replicaSurface; + + ContentData m_currentContent; + + Vector<TextureMapperNode*> m_children; + TextureMapperNode* m_parent; + TextureMapperNode* m_effectTarget; + IntSize m_size, m_nearestSurfaceSize; + String m_name; + TextureMapperLayerClient* m_platformClient; + + struct State { + FloatPoint pos; + FloatPoint3D anchorPoint; + FloatSize size; + TransformationMatrix transform; + TransformationMatrix childrenTransform; + Color backgroundColor; + Color currentColor; + GraphicsLayer::CompositingCoordinatesOrientation geoOrientation; + GraphicsLayer::CompositingCoordinatesOrientation contentsOrientation; + float opacity; + IntRect contentsRect; + int descendantsWithContent; + TextureMapperNode* maskLayer; + TextureMapperNode* replicaLayer; + bool preserves3D; + bool masksToBounds; + bool drawsContent; + bool contentsOpaque; + bool backfaceVisibility; + bool visible; + bool dirty; + bool tiled; + bool hasSurfaceDescendants; + IntRect visibleRect; + + State() + : opacity(1.f) + , descendantsWithContent(0) + , maskLayer(0) + , replicaLayer(0) + , preserves3D(false) + , masksToBounds(false) + , drawsContent(false) + , contentsOpaque(false) + , backfaceVisibility(false) + , visible(true) + , dirty(true) + , tiled(false) + , hasSurfaceDescendants(false) + { + } + }; + + State m_state; + TextureMapperCache* m_cache; +}; + +} +#endif // TextureMapperNode_h diff --git a/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h b/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h index 23e9fc9..2a38b90 100644 --- a/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h +++ b/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h @@ -25,6 +25,7 @@ namespace WebCore { class GraphicsContext; class IntRect; class IntSize; +class TextureMapper; class TransformationMatrix; @@ -35,6 +36,7 @@ public: virtual void setNeedsDisplay() = 0; virtual void setNeedsDisplayInRect(const IntRect& rect) = 0; virtual void setSizeChanged(const IntSize&) = 0; + virtual TextureMapper* textureMapper() = 0; }; class TextureMapperPlatformLayer { @@ -50,10 +52,17 @@ public: class TextureMapperContentLayer : public TextureMapperPlatformLayer { public: + struct PaintOptions { + IntRect visibleRect; + IntRect targetRect; + IntSize viewportSize; + TransformationMatrix transform; + float opacity; + }; + virtual void setPlatformLayerClient(TextureMapperLayerClient*) = 0; - virtual void paint(GraphicsContext*, const IntSize&, const IntRect& targetRect, const IntRect& exposedRect, const TransformationMatrix& transform, float opacity) {} + virtual void paint(TextureMapper*, const PaintOptions&) {} virtual IntSize size() const = 0; - virtual void cleanupTextureMapper() {} virtual Type layerType() const { return ContentLayer; } }; diff --git a/WebCore/platform/graphics/win/FontCacheWin.cpp b/WebCore/platform/graphics/win/FontCacheWin.cpp index 2240f80..e800245 100644 --- a/WebCore/platform/graphics/win/FontCacheWin.cpp +++ b/WebCore/platform/graphics/win/FontCacheWin.cpp @@ -330,7 +330,7 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font AtomicString("Arial") }; SimpleFontData* simpleFont; - for (int i = 0; i < ARRAYSIZE(fallbackFonts); ++i) { + for (size_t i = 0; i < WTF_ARRAY_LENGTH(fallbackFonts); ++i) { if (simpleFont = getCachedFontData(fontDescription, fallbackFonts[i])) { fallbackFontName = fallbackFonts[i]; return simpleFont; diff --git a/WebCore/platform/graphics/win/IconWin.cpp b/WebCore/platform/graphics/win/IconWin.cpp index 05959e0..4d4d219 100644 --- a/WebCore/platform/graphics/win/IconWin.cpp +++ b/WebCore/platform/graphics/win/IconWin.cpp @@ -69,7 +69,7 @@ PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames) return 0; #else TCHAR buffer[MAX_PATH]; - UINT length = ::GetSystemDirectory(buffer, ARRAYSIZE(buffer)); + UINT length = ::GetSystemDirectory(buffer, WTF_ARRAY_LENGTH(buffer)); if (!length) return 0; diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp index 5544229..34a8817 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp @@ -1053,6 +1053,16 @@ void MediaPlayerPrivateQuickTimeVisualContext::setPreload(MediaPlayer::Preload p resumeLoad(); } +float MediaPlayerPrivateQuickTimeVisualContext::mediaTimeForTimeValue(float timeValue) const +{ + long timeScale; + if (m_readyState < MediaPlayer::HaveMetadata || !(timeScale = m_movie->timeScale())) + return timeValue; + + long mediaTimeValue = static_cast<long>(timeValue * timeScale); + return static_cast<float>(mediaTimeValue) / timeScale; +} + MediaPlayerPrivateQuickTimeVisualContext::MediaRenderingMode MediaPlayerPrivateQuickTimeVisualContext::currentRenderingMode() const { if (!m_movie) diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h index 109fd0b..43d5bd5 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h @@ -173,6 +173,8 @@ private: void retrieveAndResetMovieTransform(); + virtual float mediaTimeForTimeValue(float) const; + MediaPlayer* m_player; RefPtr<QTMovie> m_movie; #if USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/win/QTMovie.cpp b/WebCore/platform/graphics/win/QTMovie.cpp index 375d8c2..e425bf8 100644 --- a/WebCore/platform/graphics/win/QTMovie.cpp +++ b/WebCore/platform/graphics/win/QTMovie.cpp @@ -738,6 +738,14 @@ void QTMovie::setClosedCaptionsVisible(bool visible) QTSetTrackProperty(ccTrack, closedCaptionTrackType, closedCaptionDisplayPropertyID, sizeof(doDisplay), &doDisplay); } +long QTMovie::timeScale() const +{ + if (!m_private->m_movie) + return 0; + + return GetMovieTimeScale(m_private->m_movie); +} + static void initializeSupportedTypes() { if (gSupportedTypes) diff --git a/WebCore/platform/graphics/win/QTMovie.h b/WebCore/platform/graphics/win/QTMovie.h index e205b68..5e4c4e7 100644 --- a/WebCore/platform/graphics/win/QTMovie.h +++ b/WebCore/platform/graphics/win/QTMovie.h @@ -115,6 +115,8 @@ public: Movie getMovieHandle() const; + long timeScale() const; + private: QTMoviePrivate* m_private; friend class QTMoviePrivate; diff --git a/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp b/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp index a11b8d8..8af6ef7 100644 --- a/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp +++ b/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp @@ -194,11 +194,6 @@ public: restore(); } - IntPoint origin() const - { - return IntPoint(stableRound(-m_transform.e()), stableRound(-m_transform.f())); - } - void translate(float x, float y) { m_transform.translate(x, y); @@ -463,8 +458,7 @@ private: RefPtr<SharedBitmap> m_bitmap; RefPtr<SharedBitmap> m_rotatedBitmap; RECT m_bmpRect; - unsigned m_key1; - unsigned m_key2; + unsigned m_key; RotationTransform m_rotation; float m_oldOpacity; AlphaPaintType m_alphaPaintType; @@ -532,7 +526,7 @@ TransparentLayerDC::TransparentLayerDC(GraphicsContextPlatformPrivate* data, Int } else m_bitmap = m_data->getTransparentLayerBitmap(m_origRect, m_alphaPaintType, m_bmpRect, true, mustCreateLayer); if (m_bitmap) - m_memDc = m_bitmap->getDC(&m_key1, &m_key2); + m_memDc = m_bitmap->getDC(&m_key); else m_memDc = m_data->m_dc; } @@ -540,15 +534,15 @@ TransparentLayerDC::TransparentLayerDC(GraphicsContextPlatformPrivate* data, Int TransparentLayerDC::~TransparentLayerDC() { if (m_rotatedBitmap) { - m_bitmap->releaseDC(m_memDc, m_key1, m_key2); - m_key1 = m_key2 = 0; + m_bitmap->releaseDC(m_memDc, m_key); + m_key = 0; rotateBitmap(m_rotatedBitmap.get(), m_bitmap.get(), m_rotation); - m_memDc = m_rotatedBitmap->getDC(&m_key1, &m_key2); + m_memDc = m_rotatedBitmap->getDC(&m_key); m_data->paintBackTransparentLayerBitmap(m_memDc, m_rotatedBitmap.get(), m_rotatedOrigRect, m_alphaPaintType, m_bmpRect); - m_rotatedBitmap->releaseDC(m_memDc, m_key1, m_key2); + m_rotatedBitmap->releaseDC(m_memDc, m_key); } else if (m_bitmap) { m_data->paintBackTransparentLayerBitmap(m_memDc, m_bitmap.get(), m_origRect, m_alphaPaintType, m_bmpRect); - m_bitmap->releaseDC(m_memDc, m_key1, m_key2); + m_bitmap->releaseDC(m_memDc, m_key); } m_data->m_opacity = m_oldOpacity; } @@ -572,19 +566,18 @@ public: : m_data(data) { if (m_data->m_bitmap) - m_data->m_dc = m_data->m_bitmap->getDC(&m_key1, &m_key2); + m_data->m_dc = m_data->m_bitmap->getDC(&m_key); } ~ScopeDCProvider() { if (m_data->m_bitmap) { - m_data->m_bitmap->releaseDC(m_data->m_dc, m_key1, m_key2); + m_data->m_bitmap->releaseDC(m_data->m_dc, m_key); m_data->m_dc = 0; } } private: GraphicsContextPlatformPrivate* m_data; - unsigned m_key1; - unsigned m_key2; + unsigned m_key; }; @@ -1159,11 +1152,6 @@ void GraphicsContext::rotate(float radians) m_data->rotate(radians); } -IntPoint GraphicsContext::origin() -{ - return m_data->origin(); -} - void GraphicsContext::scale(const FloatSize& size) { m_data->scale(size); @@ -1219,11 +1207,6 @@ void GraphicsContext::clipOut(const Path&) notImplemented(); } -void GraphicsContext::clipOutEllipseInRect(const IntRect&) -{ - notImplemented(); -} - static inline IntPoint rectCenterPoint(const RECT& rect) { return IntPoint(rect.left + (rect.right - rect.left) / 2, rect.top + (rect.bottom - rect.top) / 2); @@ -1539,6 +1522,12 @@ void GraphicsContext::clearPlatformShadow() notImplemented(); } +InterpolationQuality GraphicsContext::imageInterpolationQuality() const +{ + notImplemented(); + return InterpolationDefault; +} + void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) { notImplemented(); @@ -1576,11 +1565,11 @@ void GraphicsContext::drawText(const Font& font, const TextRun& run, const IntPo gc.scale(FloatSize(m_data->m_transform.a(), m_data->m_transform.d())); font.drawText(&gc, run, IntPoint(0, font.ascent()), from, to); } - unsigned key1, key2; - HDC memDC = bmp->getDC(&key1, &key2); + unsigned key1; + HDC memDC = bmp->getDC(&key1); if (memDC) { m_data->paintBackTransparentLayerBitmap(memDC, bmp.get(), trRect, alphaPaintType, bmpRect); - bmp->releaseDC(memDC, key1, key2); + bmp->releaseDC(memDC, key1); } } diff --git a/WebCore/platform/graphics/wince/ImageWinCE.cpp b/WebCore/platform/graphics/wince/ImageWinCE.cpp index ec7403e..c0b2b53 100644 --- a/WebCore/platform/graphics/wince/ImageWinCE.cpp +++ b/WebCore/platform/graphics/wince/ImageWinCE.cpp @@ -43,7 +43,7 @@ namespace WebCore { NativeImagePtr RGBA32Buffer::asNewNativeImage() const { - return SharedBitmap::create(m_bytes, m_size, hasAlpha()); + return SharedBitmap::create(m_backingStore, m_size, hasAlpha()); } bool FrameData::clear(bool clearMetaData) diff --git a/WebCore/platform/graphics/wince/SharedBitmap.cpp b/WebCore/platform/graphics/wince/SharedBitmap.cpp new file mode 100644 index 0000000..05d1535 --- /dev/null +++ b/WebCore/platform/graphics/wince/SharedBitmap.cpp @@ -0,0 +1,615 @@ +/* + * Copyright (C) 2007-2009 Torch Mobile, Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.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 "SharedBitmap.h" + +#include "GDIExtras.h" +#include "GraphicsContext.h" +#include "GraphicsTypes.h" +#include "TransformationMatrix.h" +#include "WinCEGraphicsExtras.h" +#include <wtf/HashSet.h> +#include <wtf/RefCountedLeakCounter.h> +#include <wtf/PassOwnArrayPtr.h> +#include <wtf/OwnPtr.h> + +#include <windows.h> + +namespace WebCore { + +#ifndef NDEBUG +static WTF::RefCountedLeakCounter sharedBitmapLeakCounter("SharedBitmap"); +#endif + + +PassRefPtr<SharedBitmap> SharedBitmap::create(const IntSize& size, BitmapInfo::BitCount bitCount, bool initPixels) +{ + RefPtr<SharedBitmap> resultantBitmap = adoptRef(new SharedBitmap(size, bitCount, initPixels)); + if (resultantBitmap && !resultantBitmap->bytes()) + return 0; + return resultantBitmap.release(); +} + +PassRefPtr<SharedBitmap> SharedBitmap::create(const Vector<unsigned>& data, const IntSize& size, bool hasAlpha) +{ + RefPtr<SharedBitmap> result = create(size, BitmapInfo::BitCount32, false); + if (!result) + return 0; + memcpy(result->bytes(), data.data(), data.size() * sizeof(unsigned)); + result->setHasAlpha(hasAlpha); + return result.release(); +} + +SharedBitmap::SharedBitmap(const IntSize& size, BitmapInfo::BitCount bitCount, bool initPixels) + : m_bmpInfo(BitmapInfo::createBottomUp(size, bitCount)) + , m_locked(false) + , m_usesTransparentColor(false) + , m_transparentColor(RGB(0, 0, 0)) + , m_pixels(0) + , m_hasAlpha(false) + , m_validHeight(abs(size.height())) + , m_hbitmap(0) +{ +#ifndef NDEBUG + sharedBitmapLeakCounter.increment(); +#endif + + unsigned bufferSize = m_bmpInfo.numPixels(); + if (bitCount == BitmapInfo::BitCount16) + bufferSize /= 2; + + m_pixelData = adoptArrayPtr(new unsigned[bufferSize]); + m_pixels = m_pixelData.get(); + + if (initPixels) + resetPixels(); +} + +SharedBitmap::~SharedBitmap() +{ +#ifndef NDEBUG + sharedBitmapLeakCounter.decrement(); +#endif +} + +void SharedBitmap::resetPixels(bool black) +{ + if (!m_pixels) + return; + + unsigned bufferSize = m_bmpInfo.numPixels(); + if (black) { + unsigned bufferSizeInBytes = bufferSize * (is16bit() ? 2 : 4); + memset(m_pixels, 0, bufferSizeInBytes); + return; + } + + if (is16bit()) { + // Fill it with white color + wmemset(static_cast<wchar_t*>(m_pixels), 0xFFFF, bufferSize); + return; + } + + // Make it white but transparent + unsigned* pixel = static_cast<unsigned*>(m_pixels); + const unsigned* bufferEnd = pixel + bufferSize; + while (pixel < bufferEnd) + *pixel++ = 0x00FFFFFF; +} + +static inline unsigned short convert32To16(unsigned pixel) +{ + unsigned short r = static_cast<unsigned short>((pixel & 0x00F80000) >> 8); + unsigned short g = static_cast<unsigned short>((pixel & 0x0000FC00) >> 5); + unsigned short b = static_cast<unsigned short>((pixel & 0x000000F8) >> 3); + return r | g | b; +} + +bool SharedBitmap::to16bit() +{ + if (m_locked) + return false; + if (is16bit()) + return true; + + BitmapInfo newBmpInfo = BitmapInfo::create(m_bmpInfo.size(), BitmapInfo::BitCount16); + + int width = newBmpInfo.width(); + int paddedWidth = newBmpInfo.paddedWidth(); + int bufferSize = paddedWidth * newBmpInfo.height(); + OwnArrayPtr<unsigned> newPixelData(new unsigned[bufferSize / 2]); + void* newPixels = newPixelData.get(); + + if (!newPixels) + return false; + + unsigned short* p16 = static_cast<unsigned short*>(newPixels); + const unsigned* p32 = static_cast<const unsigned*>(m_pixels); + + bool skips = paddedWidth != width; + + const unsigned short* p16end = p16 + bufferSize; + while (p16 < p16end) { + for (unsigned short* p16lineEnd = p16 + width; p16 < p16lineEnd; ) + *p16++ = convert32To16(*p32++); + + if (skips) + *p16++ = 0; + } + + if (m_hbitmap) + m_hbitmap = nullptr; + else + m_pixelData = newPixelData.release(); + + m_pixels = newPixels; + m_bmpInfo = newBmpInfo; + + setHasAlpha(false); + return true; +} + +bool SharedBitmap::freeMemory() +{ + if (m_locked) + return false; + + if (m_hbitmap) { + m_hbitmap = nullptr; + m_pixels = 0; + return true; + } + + if (m_pixels) { + m_pixelData = nullptr; + m_pixels = 0; + return true; + } + + return false; +} + +PassOwnPtr<HBITMAP> SharedBitmap::createHandle(void** pixels, BitmapInfo* bmpInfo, int height, bool use16bit) const +{ + if (!m_pixels) + return 0; + + if (height == -1) + height = this->height(); + *bmpInfo = BitmapInfo::createBottomUp(IntSize(width(), height), (use16bit || is16bit()) ? BitmapInfo::BitCount16 : BitmapInfo::BitCount32); + + OwnPtr<HBITMAP> hbmp = adoptPtr(CreateDIBSection(0, bmpInfo, DIB_RGB_COLORS, pixels, 0, 0)); + + if (!hbmp) + return 0; + + OwnPtr<HDC> bmpDC = adoptPtr(CreateCompatibleDC(0)); + HGDIOBJ hOldBmp = SelectObject(bmpDC.get(), hbmp.get()); + + StretchDIBits(bmpDC.get(), 0, 0, width(), height, 0, 0, width(), height, m_pixels, &m_bmpInfo, DIB_RGB_COLORS, SRCCOPY); + + SelectObject(bmpDC.get(), hOldBmp); + + return hbmp.release(); +} + +bool SharedBitmap::ensureHandle() +{ + if (m_hbitmap) + return true; + + if (!m_pixels) + return false; + + if (m_locked) + return false; + + BitmapInfo bmpInfo; + void* pixels; + m_hbitmap = createHandle(&pixels, &bmpInfo, -1, !hasAlpha()); + + if (!m_hbitmap) + return false; + + m_pixelData = nullptr; + m_pixels = pixels; + m_bmpInfo = bmpInfo; + + return true; +} + +void SharedBitmap::draw(GraphicsContext* ctxt, const IntRect& dstRect, const IntRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp) +{ + if (!m_pixels) + return; + ctxt->drawBitmap(this, dstRect, srcRect, styleColorSpace, compositeOp); +} + +void SharedBitmap::draw(HDC hdc, const IntRect& dstRect, const IntRect& srcRect, CompositeOperator compositeOp) +{ + if (!m_pixels) + return; + + if (dstRect.isEmpty() || srcRect.isEmpty()) + return; + + HBITMAP hbitmap = 0; + OwnPtr<HBITMAP> hTempBitmap; + bool usingHandle = compositeOp == CompositeSourceOver && (hasAlpha() && hasAlphaBlendSupport() || usesTransparentColor()); + + if (usingHandle) { + if (ensureHandle()) + hbitmap = m_hbitmap.get(); + else { + void* pixels; + BitmapInfo bmpInfo; + hTempBitmap = createHandle(&pixels, &bmpInfo, -1, usesTransparentColor()); + hbitmap = hTempBitmap.get(); + } + } + if (!hbitmap) { + // FIXME: handle other composite operation types? + DWORD rop = compositeOp == CompositeCopy ? SRCCOPY + : compositeOp == CompositeXOR ? PATINVERT + : compositeOp == CompositeClear ? WHITENESS + : SRCCOPY; + + StretchDIBits(hdc, dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height(), + srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), m_pixels, &m_bmpInfo, DIB_RGB_COLORS, rop); + return; + } + + OwnPtr<HDC> hmemdc = adoptPtr(CreateCompatibleDC(hdc)); + HGDIOBJ hOldBmp = SelectObject(hmemdc.get(), hbitmap); + + if (!usesTransparentColor() && hasAlphaBlendSupport()) { + static const BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; + bool success = alphaBlendIfSupported(hdc, dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height(), hmemdc.get(), + srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), blend); + ASSERT_UNUSED(success, success); + } else { + TransparentBlt(hdc, dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height(), hmemdc.get(), + srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), transparentColor()); + } + + SelectObject(hmemdc.get(), hOldBmp); +} + +PassOwnPtr<HBITMAP> SharedBitmap::clipBitmap(const IntRect& rect, bool useAlpha, BitmapInfo& bmpInfo, void*& pixels) +{ + if (!bytes()) + return 0; + + int oldWidth = width(); + int oldHeight = height(); + int copyWidth = std::min<int>(rect.width(), oldWidth - rect.x()); + int copyHeight = std::min<int>(rect.height(), oldHeight - rect.y()); + if (!copyWidth || !copyHeight) + return 0; + + bmpInfo = BitmapInfo::createBottomUp(IntSize(copyWidth, copyHeight), (useAlpha && is32bit()) ? BitmapInfo::BitCount32 : BitmapInfo::BitCount16); + OwnPtr<HBITMAP> newBmp = adoptPtr(CreateDIBSection(0, &bmpInfo, DIB_RGB_COLORS, &pixels, 0, 0)); + + if (!newBmp) + return 0; + + OwnPtr<HDC> dcNew = adoptPtr(CreateCompatibleDC(0)); + HGDIOBJ tmpNew = SelectObject(dcNew.get(), newBmp.get()); + + StretchDIBits(dcNew.get(), 0, 0, copyWidth, copyHeight, rect.x(), rect.y(), copyWidth, copyHeight, + bytes(), &bitmapInfo(), DIB_RGB_COLORS, SRCCOPY); + + SelectObject(dcNew.get(), tmpNew); + return newBmp.release(); +} + +PassRefPtr<SharedBitmap> SharedBitmap::clipBitmap(const IntRect& rect, bool useAlpha) +{ + int oldWidth = width(); + int oldHeight = height(); + int copyWidth = std::min<int>(rect.width(), oldWidth - rect.x()); + int copyHeight = std::min<int>(rect.height(), oldHeight - rect.y()); + if (!copyWidth || !copyHeight) + return 0; + + RefPtr<SharedBitmap> newBmp = create(IntSize(copyWidth, copyHeight), useAlpha && is32bit() ? BitmapInfo::BitCount32 : BitmapInfo::BitCount16, false); + + if (!newBmp || !newBmp->bytes()) + return 0; + + DCHolder dcNew(newBmp.get()); + + StretchDIBits(dcNew.get(), 0, 0, copyWidth, copyHeight, rect.x(), rect.y(), copyWidth, copyHeight, + bytes(), &bitmapInfo(), DIB_RGB_COLORS, SRCCOPY); + + return newBmp; +} + +static void drawPatternSimple(HDC hdc, const RECT& destRect, HBITMAP hbmp, const POINT& phase) +{ + OwnPtr<HBRUSH> hBrush = adoptPtr(CreatePatternBrush(hbmp)); + if (!hBrush) + return; + + POINT oldOrg; + SetBrushOrgEx(hdc, destRect.left - phase.x, destRect.top - phase.y, &oldOrg); + FillRect(hdc, &destRect, hBrush.get()); + SetBrushOrgEx(hdc, oldOrg.x, oldOrg.y, 0); +} + +static void drawPatternSimple(HDC hdc, const RECT& destRect, const SharedBitmap* bmp, const SIZE& bmpSize, const POINT& phase) +{ + int dstY = destRect.top; + for (int sourceY = phase.y; dstY < destRect.bottom; ) { + int sourceH = std::min<int>(bmpSize.cy - sourceY, destRect.bottom - dstY); + int dstX = destRect.left; + for (int sourceX = phase.x; dstX < destRect.right; ) { + int sourceW = std::min<int>(bmpSize.cx - sourceX, destRect.right - dstX); + + StretchDIBits(hdc, dstX, dstY, sourceW, sourceH, sourceX, sourceY, sourceW, sourceH, + bmp->bytes(), &bmp->bitmapInfo(), DIB_RGB_COLORS, SRCCOPY); + + dstX += sourceW; + sourceX = 0; + } + + dstY += sourceH; + sourceY = 0; + } +} + +static LONG normalizePhase(LONG phase, int limit) +{ + if (!phase || limit < 2) + return 0; + + if (limit == 2) + return phase & 1; + + if (phase < 0) { + phase = -phase; + if (phase > limit) + phase = static_cast<LONG>(static_cast<unsigned>(phase) % static_cast<unsigned>(limit)); + if (phase) + phase = limit - phase; + return phase; + } + + if (phase < limit) + return phase; + + return static_cast<LONG>(static_cast<unsigned>(phase) % static_cast<unsigned>(limit)); +} + +void SharedBitmap::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, const IntSize& origSourceSize) +{ + if (!m_pixels) + return; + ctxt->drawBitmapPattern(this, tileRectIn, patternTransform, phase, styleColorSpace, op, destRect, origSourceSize); +} + +void SharedBitmap::drawPattern(HDC hdc, const AffineTransform& transform, const FloatRect& tileRectIn, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, const IntSize& origSourceSize) +{ + if (!m_pixels) + return; + + if (tileRectIn.width() <= 0 || tileRectIn.height() <= 0) + return; + + bool useAlpha = op == CompositeSourceOver && hasAlpha() && is32bit(); + + int bmpWidth = width(); + int bmpHeight = height(); + + FloatRect tileRect(tileRectIn); + if (bmpWidth != origSourceSize.width()) { + double rate = static_cast<double>(bmpWidth) / origSourceSize.width(); + double temp = tileRect.width() * rate; + tileRect.setX(tileRect.x() * rate); + tileRect.setWidth(temp); + temp = tileRect.height() * rate; + tileRect.setY(tileRect.y() * rate); + tileRect.setHeight(temp); + } + + OwnPtr<HBITMAP> clippedBmp; + + if (tileRect.x() || tileRect.y() || tileRect.width() != bmpWidth || tileRect.height() != bmpHeight) { + BitmapInfo patternBmpInfo; + void* patternPixels; + clippedBmp = clipBitmap(IntRect(tileRect), useAlpha, patternBmpInfo, patternPixels); + if (!clippedBmp) + return; + + bmpWidth = tileRect.width(); + bmpHeight = tileRect.height(); + } + + AffineTransform tf = transform; + tf *= patternTransform; + + FloatRect trRect = tf.mapRect(destRect); + + RECT clipBox; + int clipType = GetClipBox(hdc, &clipBox); + if (clipType == SIMPLEREGION) + trRect.intersect(FloatRect(clipBox.left, clipBox.top, clipBox.right - clipBox.left, clipBox.bottom - clipBox.top)); + else if (clipType == COMPLEXREGION) { + OwnPtr<HRGN> clipRgn = adoptPtr(CreateRectRgn(0, 0, 0, 0)); + if (GetClipRgn(hdc, clipRgn.get()) > 0) { + DWORD regionDataSize = GetRegionData(clipRgn.get(), sizeof(RGNDATA), 0); + if (regionDataSize) { + Vector<RGNDATA> regionData(regionDataSize); + GetRegionData(clipRgn.get(), regionDataSize, regionData.data()); + RECT* rect = reinterpret_cast<RECT*>(regionData[0].Buffer); + for (DWORD i = 0; i < regionData[0].rdh.nCount; ++i, ++rect) + trRect.intersect(FloatRect(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top)); + } + } + } + + if (trRect.width() <= 0 || trRect.height() <= 0) + return; + + trRect.inflate(1); + IntRect visibleDstRect = enclosingIntRect(tf.inverse().mapRect(trRect)); + visibleDstRect.intersect(IntRect(destRect)); + + if (visibleDstRect.width() <= 0 || visibleDstRect.height() <= 0) + return; + + trRect = tf.mapRect(visibleDstRect); + RECT dstRectWin = { + stableRound(trRect.x()), + stableRound(trRect.y()), + stableRound(trRect.right()), + stableRound(trRect.bottom()), + }; + if (dstRectWin.right <= dstRectWin.left || dstRectWin.bottom <= dstRectWin.top) + return; + + SIZE bmpSize = { bmpWidth, bmpHeight }; + + // Relative to destination, in bitmap pixels + POINT phaseWin = { stableRound(visibleDstRect.x() - phase.x()), stableRound(visibleDstRect.y() - phase.y()) }; + phaseWin.x = normalizePhase(phaseWin.x, bmpSize.cx); + phaseWin.y = normalizePhase(phaseWin.y, bmpSize.cy); + + RECT srcRectWin = { + 0, + 0, + stableRound(visibleDstRect.right()) - stableRound(visibleDstRect.x()), + stableRound(visibleDstRect.bottom()) - stableRound(visibleDstRect.y()) + }; + if (srcRectWin.right <= 0 || srcRectWin.bottom <= 0) + return; + + BitmapInfo bmpInfo = BitmapInfo::createBottomUp(IntSize(srcRectWin.right, srcRectWin.bottom), useAlpha ? BitmapInfo::BitCount32 : BitmapInfo::BitCount16); + void* pixels; + OwnPtr<HBITMAP> hbmpTemp = adoptPtr(CreateDIBSection(0, &bmpInfo, DIB_RGB_COLORS, &pixels, 0, 0)); + + if (!hbmpTemp) + return; + + OwnPtr<HDC> hmemdc = adoptPtr(CreateCompatibleDC(hdc)); + HGDIOBJ oldBmp = SelectObject(hmemdc.get(), hbmpTemp.get()); + if (clippedBmp) + drawPatternSimple(hmemdc.get(), srcRectWin, clippedBmp.get(), phaseWin); + else if ((op != CompositeSourceOver || canUseDIBits()) && srcRectWin.right <= bmpSize.cx * 2 && srcRectWin.bottom <= bmpSize.cy * 2) + drawPatternSimple(hmemdc.get(), srcRectWin, this, bmpSize, phaseWin); + else if (ensureHandle()) + drawPatternSimple(hmemdc.get(), srcRectWin, getHandle(), phaseWin); + else { + void* pixels; + BitmapInfo bmpInfo; + OwnPtr<HBITMAP> hbmp = createHandle(&pixels, &bmpInfo, -1, false); + if (hbmp) + drawPatternSimple(hmemdc.get(), srcRectWin, hbmp.get(), phaseWin); + else { + SelectObject(hmemdc.get(), oldBmp); + return; + } + } + + if (useAlpha && hasAlphaBlendSupport()) { + static const BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; + bool success = alphaBlendIfSupported(hdc, dstRectWin.left, dstRectWin.top, dstRectWin.right - dstRectWin.left, dstRectWin.bottom - dstRectWin.top, + hmemdc.get(), 0, 0, srcRectWin.right, srcRectWin.bottom, blend); + ASSERT_UNUSED(success, success); + } else if (useAlpha && !hasAlphaBlendSupport() || op == CompositeSourceOver && usesTransparentColor()) { + TransparentBlt(hdc, dstRectWin.left, dstRectWin.top, dstRectWin.right - dstRectWin.left, + dstRectWin.bottom - dstRectWin.top, hmemdc.get(), 0, 0, srcRectWin.right, srcRectWin.bottom, transparentColor()); + } else { + DWORD bmpOp = op == CompositeCopy ? SRCCOPY + : op == CompositeSourceOver ? SRCCOPY + : op == CompositeXOR ? PATINVERT + : op == CompositeClear ? WHITENESS + : SRCCOPY; // FIXEME: other types? + + StretchDIBits(hdc, dstRectWin.left, dstRectWin.top, dstRectWin.right - dstRectWin.left, + dstRectWin.bottom - dstRectWin.top, 0, 0, srcRectWin.right, srcRectWin.bottom, + pixels, &bmpInfo, DIB_RGB_COLORS, bmpOp); + } + SelectObject(hmemdc.get(), oldBmp); +} + +SharedBitmap::DCProvider* SharedBitmap::s_dcProvider = new SharedBitmap::DCProvider; + +HDC SharedBitmap::DCProvider::getDC(SharedBitmap* bmp, unsigned* key) +{ + if (!bmp || !bmp->ensureHandle()) + return 0; + + HDC hdc = CreateCompatibleDC(0); + if (!hdc) + return 0; + + *key = reinterpret_cast<unsigned>(SelectObject(hdc, bmp->getHandle())); + RECT rect = { 0, 0, bmp->width(), bmp->height() }; + OwnPtr<HRGN> clipRgn = adoptPtr(CreateRectRgnIndirect(&rect)); + SelectClipRgn(hdc, clipRgn.get()); + + return hdc; +} + +void SharedBitmap::DCProvider::releaseDC(SharedBitmap*, HDC hdc, unsigned key1) +{ + if (!hdc) + return; + + SelectObject(hdc, reinterpret_cast<HGDIOBJ>(key1)); + DeleteDC(hdc); +} + +void SharedBitmap::clearPixels(const IntRect& rect) +{ + if (!m_pixels) + return; + + IntRect bmpRect(0, 0, width(), height()); + bmpRect.intersect(rect); + if (is16bit()) { + unsigned w = m_bmpInfo.paddedWidth(); + unsigned short* dst = static_cast<unsigned short*>(m_pixels); + dst += bmpRect.y() * w + bmpRect.x(); + int wordsToSet = bmpRect.width(); + const unsigned short* dstEnd = dst + bmpRect.height() * w; + while (dst < dstEnd) { + wmemset(reinterpret_cast<wchar_t*>(dst), 0, wordsToSet); + dst += w; + } + return; + } + + unsigned w = width(); + unsigned* dst = static_cast<unsigned*>(m_pixels); + dst += bmpRect.y() * w + bmpRect.x(); + int wordsToSet = bmpRect.width() * 2; + const unsigned* dstEnd = dst + bmpRect.height() * w; + while (dst < dstEnd) { + wmemset(reinterpret_cast<wchar_t*>(dst), 0, wordsToSet); + dst += w; + } +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/wince/SharedBitmap.h b/WebCore/platform/graphics/wince/SharedBitmap.h new file mode 100644 index 0000000..82f5d54 --- /dev/null +++ b/WebCore/platform/graphics/wince/SharedBitmap.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2007-2009 Torch Mobile, Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.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. + */ + +#ifndef SharedBitmap_h +#define SharedBitmap_h + +#include "AffineTransform.h" +#include "BitmapInfo.h" +#include "ColorSpace.h" +#include "GraphicsTypes.h" +#include <wtf/PassOwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/OwnArrayPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> +#include <wingdi.h> + +namespace WebCore { + +class FloatPoint; +class FloatRect; +class GraphicsContext; +class IntRect; +class IntSize; +class TransformationMatrix; + +class SharedBitmap: public RefCounted<SharedBitmap> { +public: + ~SharedBitmap(); + static PassRefPtr<SharedBitmap> create(const IntSize&, BitmapInfo::BitCount = BitmapInfo::BitCount32, bool initPixels = true); + static PassRefPtr<SharedBitmap> create(const Vector<unsigned>&, const IntSize&, bool hasAlpha = true); + + const BitmapInfo& bitmapInfo() const { return m_bmpInfo; } + void* bytes() { return m_pixels; } + const void* bytes() const { return m_pixels; } + unsigned width() const { return m_bmpInfo.width(); } + unsigned height() const { return m_bmpInfo.height(); } + unsigned validHeight() const { return m_validHeight; } + void setValidHeight(unsigned validHeight) { m_validHeight = validHeight; } + void resetPixels(bool black = false); + void clearPixels(const IntRect& r); + bool locked() const { return m_locked; } + void lock() { m_locked = true; } + void unlock() { m_locked = false; } + bool freeMemory(); + bool is16bit() const { return m_bmpInfo.is16bit(); } + bool is32bit() const { return m_bmpInfo.is32bit(); } + bool to16bit(); + bool hasAlpha() const { return m_hasAlpha; } + void setHasAlpha(bool alpha) { m_hasAlpha = alpha; } + bool ensureHandle(); + HBITMAP getHandle() { return m_hbitmap.get(); } + PassOwnPtr<HBITMAP> createHandle(void** pixels, BitmapInfo* bmpInfo, int h = -1, bool use16bit = true) const; + bool usesTransparentColor() const { return m_usesTransparentColor; } + COLORREF transparentColor() const { return m_transparentColor; } + void setTransparentColor(COLORREF c) + { + m_usesTransparentColor = true; + m_transparentColor = c; + } + bool canUseDIBits() const { return !hasAlpha() && !usesTransparentColor(); } + + PassOwnPtr<HBITMAP> clipBitmap(const IntRect& rect, bool useAlpha, BitmapInfo& bmpInfo, void*& pixels); + + PassRefPtr<SharedBitmap> clipBitmap(const IntRect& rect, bool useAlpha); + + void draw(GraphicsContext* ctxt, const IntRect& dstRect, const IntRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp); + void drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, const IntSize& origSourceSize); + void draw(HDC, const IntRect& dstRect, const IntRect& srcRect, CompositeOperator compositeOp); + void drawPattern(HDC, const AffineTransform&, const FloatRect& tileRectIn, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, const IntSize& origSourceSize); + + class DCProvider { + public: + virtual HDC getDC(SharedBitmap*, unsigned*); + virtual void releaseDC(SharedBitmap*, HDC, unsigned); + }; + + static DCProvider* s_dcProvider; + + HDC getDC(unsigned* key1) { return s_dcProvider->getDC(this, key1); } + void releaseDC(HDC hdc, unsigned key1) { s_dcProvider->releaseDC(this, hdc, key1); } + + class DCHolder { + public: + DCHolder(SharedBitmap* bmp = 0) { setInternal(bmp); } + ~DCHolder() { clearInternal(); } + void set(SharedBitmap* bmp = 0) + { + clearInternal(); + setInternal(bmp); + } + HDC get() const { return m_hdc; } + private: + DCHolder& operator=(const DCHolder&); + DCHolder(const DCHolder&); + void clearInternal() + { + if (m_hdc) + m_bitmap->releaseDC(m_hdc, m_key); + } + void setInternal(SharedBitmap* bmp) + { + m_bitmap = bmp; + m_hdc = bmp ? bmp->getDC(&m_key) : 0; + } + SharedBitmap* m_bitmap; + HDC m_hdc; + unsigned m_key; + }; + +private: + SharedBitmap(const IntSize&, BitmapInfo::BitCount, bool initPixels); + BitmapInfo m_bmpInfo; + OwnPtr<HBITMAP> m_hbitmap; + void* m_pixels; + OwnArrayPtr<unsigned> m_pixelData; + COLORREF m_transparentColor; + int m_validHeight; + bool m_locked; + bool m_usesTransparentColor; + bool m_hasAlpha; +}; + +} // namespace WebCore + +#endif // SharedBitmap_h diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp index 30daa67..53a9ccd 100644 --- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp +++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp @@ -337,11 +337,6 @@ void GraphicsContext::clipOut(const IntRect&) notImplemented(); } -void GraphicsContext::clipOutEllipseInRect(const IntRect&) -{ - notImplemented(); -} - void GraphicsContext::clipPath(WindRule) { notImplemented(); diff --git a/WebCore/platform/gtk/CursorGtk.cpp b/WebCore/platform/gtk/CursorGtk.cpp index 9971bfb..39073ae 100644 --- a/WebCore/platform/gtk/CursorGtk.cpp +++ b/WebCore/platform/gtk/CursorGtk.cpp @@ -32,7 +32,7 @@ #include "Image.h" #include "IntPoint.h" -#include "PlatformRefPtrCairo.h" +#include "RefPtrCairo.h" #include <gdk/gdk.h> #include <gtk/gtk.h> #include <wtf/Assertions.h> @@ -47,10 +47,10 @@ static PlatformRefPtr<GdkCursor> createNamedCursor(CustomCursorType cursorType) return c; IntSize cursorSize = IntSize(32, 32); - PlatformRefPtr<cairo_surface_t> source = adoptPlatformRef(cairo_image_surface_create_for_data(const_cast<unsigned char*>(cursor.bits), CAIRO_FORMAT_A1, 32, 32, 4)); - PlatformRefPtr<cairo_surface_t> mask = adoptPlatformRef(cairo_image_surface_create_for_data(const_cast<unsigned char*>(cursor.mask_bits), CAIRO_FORMAT_A1, 32, 32, 4)); - PlatformRefPtr<cairo_surface_t> surface = adoptPlatformRef(cairo_image_surface_create(CAIRO_FORMAT_A1, 32, 32)); - PlatformRefPtr<cairo_t> cr = adoptPlatformRef(cairo_create(surface.get())); + RefPtr<cairo_surface_t> source = adoptRef(cairo_image_surface_create_for_data(const_cast<unsigned char*>(cursor.bits), CAIRO_FORMAT_A1, 32, 32, 4)); + RefPtr<cairo_surface_t> mask = adoptRef(cairo_image_surface_create_for_data(const_cast<unsigned char*>(cursor.mask_bits), CAIRO_FORMAT_A1, 32, 32, 4)); + RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_A1, 32, 32)); + RefPtr<cairo_t> cr = adoptRef(cairo_create(surface.get())); cairo_set_source_surface(cr.get(), source.get(), cursor.hot_x, cursor.hot_y); cairo_mask_surface(cr.get(), mask.get(), cursor.hot_x, cursor.hot_y); diff --git a/WebCore/platform/gtk/DragImageGtk.cpp b/WebCore/platform/gtk/DragImageGtk.cpp index 9d0d838..71a65e1 100644 --- a/WebCore/platform/gtk/DragImageGtk.cpp +++ b/WebCore/platform/gtk/DragImageGtk.cpp @@ -21,7 +21,7 @@ #include "CachedImage.h" #include "Image.h" -#include "PlatformRefPtrCairo.h" +#include "RefPtrCairo.h" #include <cairo.h> namespace WebCore { @@ -49,7 +49,7 @@ DragImageRef scaleDragImage(DragImageRef image, FloatSize scale) int newHeight = scale.height() * cairo_image_surface_get_height(image); cairo_surface_t* scaledSurface = cairo_surface_create_similar(image, CAIRO_CONTENT_COLOR_ALPHA, newWidth, newHeight); - PlatformRefPtr<cairo_t> context = adoptPlatformRef(cairo_create(scaledSurface)); + RefPtr<cairo_t> context = adoptRef(cairo_create(scaledSurface)); cairo_scale(context.get(), scale.width(), scale.height()); cairo_pattern_set_extend(cairo_get_source(context.get()), CAIRO_EXTEND_PAD); cairo_pattern_set_filter(cairo_get_source(context.get()), CAIRO_FILTER_BEST); @@ -66,7 +66,7 @@ DragImageRef dissolveDragImageToFraction(DragImageRef image, float fraction) if (!image) return 0; - PlatformRefPtr<cairo_t> context = adoptPlatformRef(cairo_create(image)); + RefPtr<cairo_t> context = adoptRef(cairo_create(image)); cairo_set_operator(context.get(), CAIRO_OPERATOR_DEST_IN); cairo_set_source_rgba(context.get(), 0, 0, 0, fraction); cairo_paint(context.get()); diff --git a/WebCore/platform/gtk/PasteboardHelper.cpp b/WebCore/platform/gtk/PasteboardHelper.cpp index 9f75728..228d5e9 100644 --- a/WebCore/platform/gtk/PasteboardHelper.cpp +++ b/WebCore/platform/gtk/PasteboardHelper.cpp @@ -38,6 +38,16 @@ static GdkAtom textPlainAtom = gdk_atom_intern("text/plain;charset=utf-8", FALSE static GdkAtom markupAtom = gdk_atom_intern("text/html", FALSE); static GdkAtom netscapeURLAtom = gdk_atom_intern("_NETSCAPE_URL", FALSE); static GdkAtom uriListAtom = gdk_atom_intern("text/uri-list", FALSE); +static String gMarkupPrefix = "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"; + +static void removeMarkupPrefix(String& markup) +{ + + // The markup prefix is not harmful, but we remove it from the string anyway, so that + // we can have consistent results with other ports during the layout tests. + if (markup.startsWith(gMarkupPrefix)) + markup.remove(0, gMarkupPrefix.length()); +} PasteboardHelper::PasteboardHelper() : m_targetList(gtk_target_list_new(0, 0)) @@ -112,7 +122,9 @@ void PasteboardHelper::getClipboardContents(GtkClipboard* clipboard) if (gtk_clipboard_wait_is_target_available(clipboard, markupAtom)) { if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, markupAtom)) { - dataObject->setMarkup(selectionDataToUTF8String(data)); + String markup(selectionDataToUTF8String(data)); + removeMarkupPrefix(markup); + dataObject->setMarkup(markup); gtk_selection_data_free(data); } } @@ -131,9 +143,11 @@ void PasteboardHelper::fillSelectionData(GtkSelectionData* selectionData, guint gtk_selection_data_set_text(selectionData, dataObject->text().utf8().data(), -1); else if (info == getIdForTargetType(TargetTypeMarkup)) { - GOwnPtr<gchar> markup(g_strdup(dataObject->markup().utf8().data())); + // Some Linux applications refuse to accept pasted markup unless it is + // prefixed by a content-type meta tag. + CString markup = (gMarkupPrefix + dataObject->markup()).utf8(); gtk_selection_data_set(selectionData, markupAtom, 8, - reinterpret_cast<const guchar*>(markup.get()), strlen(markup.get()) + 1); + reinterpret_cast<const guchar*>(markup.data()), markup.length() + 1); } else if (info == getIdForTargetType(TargetTypeURIList)) { CString uriList = dataObject->uriList().utf8(); @@ -187,9 +201,11 @@ void PasteboardHelper::fillDataObjectFromDropData(GtkSelectionData* data, guint GdkAtom target = gtk_selection_data_get_target(data); if (target == textPlainAtom) dataObject->setText(selectionDataToUTF8String(data)); - else if (target == markupAtom) - dataObject->setMarkup(selectionDataToUTF8String(data)); - else if (target == uriListAtom) { + else if (target == markupAtom) { + String markup(selectionDataToUTF8String(data)); + removeMarkupPrefix(markup); + dataObject->setMarkup(markup); + } else if (target == uriListAtom) { dataObject->setURIList(selectionDataToUTF8String(data)); } else if (target == netscapeURLAtom) { String urlWithLabel(selectionDataToUTF8String(data)); diff --git a/WebCore/platform/gtk/PopupMenuGtk.cpp b/WebCore/platform/gtk/PopupMenuGtk.cpp index a679734..e7ff78e 100644 --- a/WebCore/platform/gtk/PopupMenuGtk.cpp +++ b/WebCore/platform/gtk/PopupMenuGtk.cpp @@ -97,7 +97,7 @@ void PopupMenuGtk::show(const IntRect& rect, FrameView* view, int index) GList* children = gtk_container_get_children(GTK_CONTAINER(m_popup.get())); GList* p = children; - if (size) + if (size) { for (int i = 0; i < size; i++) { if (i > index) break; @@ -112,9 +112,11 @@ void PopupMenuGtk::show(const IntRect& rect, FrameView* view, int index) m_menuPosition.setY(m_menuPosition.y() - itemRequisition.height); p = g_list_next(p); - } else - // Center vertically the empty popup in the combo box area - m_menuPosition.setY(m_menuPosition.y() - rect.height() / 2); + } + } else { + // Center vertically the empty popup in the combo box area + m_menuPosition.setY(m_menuPosition.y() - rect.height() / 2); + } g_list_free(children); gtk_menu_popup(m_popup.get(), 0, 0, reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this, 0, gtk_get_current_event_time()); diff --git a/WebCore/platform/image-decoders/ImageDecoder.cpp b/WebCore/platform/image-decoders/ImageDecoder.cpp index fa61871..43ff33b 100644 --- a/WebCore/platform/image-decoders/ImageDecoder.cpp +++ b/WebCore/platform/image-decoders/ImageDecoder.cpp @@ -194,6 +194,11 @@ void RGBA32Buffer::setHasAlpha(bool alpha) m_hasAlpha = alpha; } +void RGBA32Buffer::setColorProfile(const ColorProfile& colorProfile) +{ + m_colorProfile = colorProfile; +} + void RGBA32Buffer::setStatus(FrameStatus status) { m_status = status; diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h index 9fe0e6b..81d6dbb 100644 --- a/WebCore/platform/image-decoders/ImageDecoder.h +++ b/WebCore/platform/image-decoders/ImageDecoder.h @@ -47,6 +47,9 @@ namespace WebCore { + // FIXME: Do we want better encapsulation? + typedef Vector<char> ColorProfile; + // The RGBA32Buffer object represents the decoded image data in RGBA32 // format. This buffer is what all decoders write a single frame into. // Frames are then instantiated for drawing by being handed this buffer. @@ -131,6 +134,7 @@ namespace WebCore { bool premultiplyAlpha() const { return m_premultiplyAlpha; } void setHasAlpha(bool alpha); + void setColorProfile(const ColorProfile&); void setRect(const IntRect& r) { m_rect = r; } void setStatus(FrameStatus status); void setDuration(unsigned duration) { m_duration = duration; } @@ -202,6 +206,7 @@ namespace WebCore { // same as ImageDecoder::m_size. bool m_hasAlpha; // Whether or not any of the pixels in the buffer // have transparency. + ColorProfile m_colorProfile; #endif IntRect m_rect; // The rect of the original specified frame within // the overall buffer. This will always just be @@ -354,6 +359,7 @@ namespace WebCore { RefPtr<SharedBuffer> m_data; // The encoded data. Vector<RGBA32Buffer> m_frameBufferCache; + ColorProfile m_colorProfile; bool m_scaled; Vector<int> m_scaledColumns; Vector<int> m_scaledRows; diff --git a/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp b/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp index 2fac7da..0f4dbc8 100644 --- a/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp +++ b/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp @@ -31,11 +31,16 @@ namespace WebCore { +static RGBA32Buffer::PixelData* getPtrAsPixelData(CFMutableDataRef data) +{ + return data ? reinterpret_cast<RGBA32Buffer::PixelData*>(CFDataGetMutableBytePtr(data)) : 0; +} + void RGBA32Buffer::copyReferenceToBitmapData(const RGBA32Buffer& other) { ASSERT(this != &other); m_backingStore = other.m_backingStore; - m_bytes = reinterpret_cast<PixelData*>(CFDataGetMutableBytePtr(m_backingStore.get())); + m_bytes = getPtrAsPixelData(m_backingStore.get()); // FIXME: The rest of this function seems redundant with RGBA32Buffer::copyBitmapData. m_size = other.m_size; setHasAlpha(other.m_hasAlpha); @@ -47,7 +52,7 @@ bool RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other) return true; m_backingStore.adoptCF(CFDataCreateMutableCopy(kCFAllocatorDefault, 0, other.m_backingStore.get())); - m_bytes = reinterpret_cast<PixelData*>(CFDataGetMutableBytePtr(m_backingStore.get())); + m_bytes = getPtrAsPixelData(m_backingStore.get()); m_size = other.m_size; setHasAlpha(other.m_hasAlpha); return true; @@ -64,15 +69,30 @@ bool RGBA32Buffer::setSize(int newWidth, int newHeight) return true; } +static CGColorSpaceRef createColorSpace(const ColorProfile& colorProfile) +{ + if (colorProfile.isEmpty()) + return CGColorSpaceCreateDeviceRGB(); + + RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(colorProfile.data()), colorProfile.size())); +#if !defined(TARGETING_TIGER) && !defined(TARGETING_LEOPARD) + return CGColorSpaceCreateWithICCProfile(data.get()); +#else + RetainPtr<CGColorSpaceRef> deviceColorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); + RetainPtr<CGDataProviderRef> profileDataProvider(AdoptCF, CGDataProviderCreateWithCFData(data.get())); + CGFloat ranges[] = {0.0, 255.0, 0.0, 255.0, 0.0, 255.0}; + return CGColorSpaceCreateICCBased(3, ranges, profileDataProvider.get(), deviceColorSpace.get()); +#endif +} + NativeImagePtr RGBA32Buffer::asNewNativeImage() const { - // FIXME: Figure out the right color space. - DEFINE_STATIC_LOCAL(RetainPtr<CGColorSpaceRef>, deviceColorSpace, (AdoptCF, CGColorSpaceCreateDeviceRGB())); + RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, createColorSpace(m_colorProfile)); RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(m_backingStore.get())); CGImageAlphaInfo alphaInfo = m_premultiplyAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaFirst; - return CGImageCreate(width(), height(), 8, 32, width() * sizeof(PixelData), deviceColorSpace.get(), + return CGImageCreate(width(), height(), 8, 32, width() * sizeof(PixelData), colorSpace.get(), alphaInfo | kCGBitmapByteOrder32Host, dataProvider.get(), 0, false, kCGRenderingIntentDefault); } diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp index 4797495..18cd903 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp @@ -96,21 +96,24 @@ int GIFImageDecoder::repetitionCount() const // This value can arrive at any point in the image data stream. Most GIFs // in the wild declare it near the beginning of the file, so it usually is // set by the time we've decoded the size, but (depending on the GIF and the - // packets sent back by the webserver) not always. Our caller is - // responsible for waiting until image decoding has finished to ask this if - // it needs an authoritative answer. In the meantime, we should default to - // "loop once". - if (m_reader) { - // Added wrinkle: ImageSource::clear() may destroy the reader, making - // the result from the reader _less_ authoritative on future calls. To - // detect this, the reader returns cLoopCountNotSeen (-2) instead of - // cAnimationLoopOnce (0) when its current incarnation hasn't actually - // seen a loop count yet; in this case we return our previously-cached - // value. - const int repetitionCount = m_reader->loop_count; - if (repetitionCount != cLoopCountNotSeen) - m_repetitionCount = repetitionCount; - } + // packets sent back by the webserver) not always. If the reader hasn't + // seen a loop count yet, it will return cLoopCountNotSeen, in which case we + // should default to looping once (the initial value for + // |m_repetitionCount|). + // + // There are two additional wrinkles here. First, ImageSource::clear() may + // destroy the reader, making the result from the reader _less_ + // authoritative on future calls if the recreated reader hasn't seen the + // loop count. We don't need to special-case this because in this case the + // new reader will once again return cLoopCountNotSeen, and we won't + // overwrite the cached correct value. + // + // Second, a GIF might never set a loop count at all, in which case we + // should continue to treat it as a "loop once" animation. We don't need + // special code here either, because in this case we'll never change + // |m_repetitionCount| from its default value. + if (m_reader && (m_reader->loop_count != cLoopCountNotSeen)) + m_repetitionCount = m_reader->loop_count; return m_repetitionCount; } @@ -295,8 +298,10 @@ bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, void GIFImageDecoder::gifComplete() { - if (m_reader) - m_repetitionCount = m_reader->loop_count; + // Cache the repetition count, which is now as authoritative as it's ever + // going to be. + repetitionCount(); + m_reader.clear(); } diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 6c6c782..da35739 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -51,7 +51,13 @@ #endif extern "C" { + #include "jpeglib.h" + +#if USE(ICCJPEG) +#include "iccjpeg.h" +#endif + } #include <setjmp.h> @@ -86,6 +92,24 @@ struct decoder_source_mgr { JPEGImageReader* decoder; }; +static ColorProfile readColorProfile(jpeg_decompress_struct* info) +{ +#if USE(ICCJPEG) + JOCTET* profile; + unsigned int profileLength; + + if (!read_icc_profile(info, &profile, &profileLength)) + return ColorProfile(); + + ColorProfile colorProfile; + colorProfile.append(reinterpret_cast<char*>(profile), profileLength); + free(profile); + return colorProfile; +#else + return ColorProfile(); +#endif +} + class JPEGImageReader { public: @@ -123,6 +147,11 @@ public: src->pub.resync_to_restart = jpeg_resync_to_restart; src->pub.term_source = term_source; src->decoder = this; + + // Enable these markers for the ICC color profile. + // Apparently there are 16 of these markers. I don't see anywhere in the header with this constant. + for (unsigned i = 0; i < 0xF; ++i) + jpeg_save_markers(&m_info, JPEG_APP0 + i, 0xFFFF); } ~JPEGImageReader() @@ -212,6 +241,8 @@ public: if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) return false; + m_decoder->setColorProfile(readColorProfile(info())); + if (m_decodingSizeOnly) { // We can stop here. Reduce our buffer length and available // data. @@ -421,6 +452,7 @@ bool JPEGImageDecoder::outputScanlines() return setFailed(); buffer.setStatus(RGBA32Buffer::FramePartial); buffer.setHasAlpha(false); + buffer.setColorProfile(m_colorProfile); // For JPEGs, the frame always fills the entire image. buffer.setRect(IntRect(IntPoint(), size())); diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h index 5047019..e942b01 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h @@ -54,6 +54,8 @@ namespace WebCore { bool outputScanlines(); void jpegComplete(); + void setColorProfile(const ColorProfile& colorProfile) { m_colorProfile = colorProfile; } + private: // Decodes the image. If |onlySize| is true, stops decoding after // calculating the image size. If decoding fails but there is no more diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp index 940e4c4..e4f7a0c 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp @@ -220,6 +220,22 @@ bool PNGImageDecoder::setFailed() return ImageDecoder::setFailed(); } +static ColorProfile readColorProfile(png_structp png, png_infop info) +{ +#ifdef PNG_iCCP_SUPPORTED + char* profileName; + int compressionType; + char* profile; + png_uint_32 profileLength; + if (png_get_iCCP(png, info, &profileName, &compressionType, &profile, &profileLength)) { + ColorProfile colorProfile; + colorProfile.append(profile, profileLength); + return colorProfile; + } +#endif + return ColorProfile(); +} + void PNGImageDecoder::headerAvailable() { png_structp png = m_reader->pngPtr(); @@ -249,6 +265,16 @@ void PNGImageDecoder::headerAvailable() int bitDepth, colorType, interlaceType, compressionType, filterType, channels; png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType, &interlaceType, &compressionType, &filterType); + if (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_RGB_ALPHA) { + // We currently support color profiles only for RGB and RGBA PNGs. Supporting + // color profiles for gray-scale images is slightly tricky, at least using the + // CoreGraphics ICC library, because we expand gray-scale images to RGB but we + // don't similarly transform the color profile. We'd either need to transform + // the color profile or we'd need to decode into a gray-scale image buffer and + // hand that to CoreGraphics. + m_colorProfile = readColorProfile(png, info); + } + // The options we set here match what Mozilla does. // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA. @@ -311,6 +337,7 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, } buffer.setStatus(RGBA32Buffer::FramePartial); buffer.setHasAlpha(false); + buffer.setColorProfile(m_colorProfile); // For PNGs, the frame always fills the entire image. buffer.setRect(IntRect(IntPoint(), size())); diff --git a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp index a782373..998234f 100644 --- a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp +++ b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp @@ -28,6 +28,8 @@ #include "config.h" #include "ImageDecoder.h" +#include "NotImplemented.h" + #include <QPixmap> #include <stdio.h> @@ -124,6 +126,11 @@ void RGBA32Buffer::setHasAlpha(bool alpha) m_hasAlpha = alpha; } +void RGBA32Buffer::setColorProfile(const ColorProfile& colorProfile) +{ + notImplemented(); +} + void RGBA32Buffer::setStatus(FrameStatus status) { m_status = status; diff --git a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp index 7baca5f..50e2106 100644 --- a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp +++ b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp @@ -30,6 +30,8 @@ #include "SkBitmapRef.h" #endif +#include "NotImplemented.h" + namespace WebCore { RGBA32Buffer::RGBA32Buffer() @@ -116,6 +118,11 @@ void RGBA32Buffer::setHasAlpha(bool alpha) m_bitmap.setIsOpaque(!alpha); } +void RGBA32Buffer::setColorProfile(const ColorProfile& colorProfile) +{ + notImplemented(); +} + void RGBA32Buffer::setStatus(FrameStatus status) { m_status = status; diff --git a/WebCore/platform/mac/ContextMenuItemMac.mm b/WebCore/platform/mac/ContextMenuItemMac.mm index 48da786..ce779ec 100644 --- a/WebCore/platform/mac/ContextMenuItemMac.mm +++ b/WebCore/platform/mac/ContextMenuItemMac.mm @@ -154,6 +154,11 @@ bool ContextMenuItem::enabled() const return [m_platformDescription.get() isEnabled]; } +bool ContextMenuItem::checked() const +{ + return [m_platformDescription.get() state] == NSOnState; +} + } // namespace WebCore #endif // ENABLE(CONTEXT_MENUS) diff --git a/WebCore/platform/mac/ContextMenuMac.mm b/WebCore/platform/mac/ContextMenuMac.mm index 8ced8cb..c427e3c 100644 --- a/WebCore/platform/mac/ContextMenuMac.mm +++ b/WebCore/platform/mac/ContextMenuMac.mm @@ -153,6 +153,19 @@ NSMutableArray* ContextMenu::releasePlatformDescription() return m_platformDescription.releaseRef(); } +Vector<ContextMenuItem> contextMenuItemVector(PlatformMenuDescription menu) +{ + Vector<ContextMenuItem> items; + unsigned count = [menu count]; + if (menu) + items.reserveCapacity(count); + + for (unsigned i = 0; i < count; ++i) + items.append(ContextMenuItem([menu objectAtIndex:i])); + + return items; +} + } // namespace WebCore #endif // ENABLE(CONTEXT_MENUS) diff --git a/WebCore/platform/mac/Language.mm b/WebCore/platform/mac/Language.mm index bb51cb5..c242e9e 100644 --- a/WebCore/platform/mac/Language.mm +++ b/WebCore/platform/mac/Language.mm @@ -69,17 +69,20 @@ static NSString *createHTTPStyleLanguageCode(NSString *languageCode) // Make the string lowercase. NSString *lowercaseLanguageCode = [languageCode lowercaseString]; + NSString *httpStyleLanguageCode; + // Turn a '_' into a '-' if it appears after a 2-letter language code. - if ([lowercaseLanguageCode length] < 3 || [lowercaseLanguageCode characterAtIndex:2] != '_') - return lowercaseLanguageCode; - - NSMutableString *result = [lowercaseLanguageCode mutableCopy]; - [result replaceCharactersInRange:NSMakeRange(2, 1) withString:@"-"]; - + if ([lowercaseLanguageCode length] >= 3 && [lowercaseLanguageCode characterAtIndex:2] == '_') { + NSMutableString *mutableLanguageCode = [lowercaseLanguageCode mutableCopy]; + [mutableLanguageCode replaceCharactersInRange:NSMakeRange(2, 1) withString:@"-"]; + httpStyleLanguageCode = mutableLanguageCode; + } else + httpStyleLanguageCode = [lowercaseLanguageCode retain]; + if (preferredLanguageCode) CFRelease(preferredLanguageCode); - return result; + return httpStyleLanguageCode; } String platformDefaultLanguage() diff --git a/WebCore/platform/mac/PurgeableBufferMac.cpp b/WebCore/platform/mac/PurgeableBufferMac.cpp index 54de4ed..fdbac1f 100644 --- a/WebCore/platform/mac/PurgeableBufferMac.cpp +++ b/WebCore/platform/mac/PurgeableBufferMac.cpp @@ -35,7 +35,9 @@ namespace WebCore { -static const size_t minPurgeableBufferSize = 4096; // one page +// Purgeable buffers are allocated in multiples of the page size (4KB in common CPUs) so +// it does not make sense for very small buffers. Set our minimum size to 16KB. +static const size_t minPurgeableBufferSize = 4 * 4096; PurgeableBuffer::PurgeableBuffer(char* data, size_t size) : m_data(data) @@ -143,17 +145,6 @@ bool PurgeableBuffer::wasPurged() const return false; } -void PurgeableBuffer::setPurgePriority(PurgePriority priority) -{ - if (priority == m_purgePriority) - return; - m_purgePriority = priority; - if (m_state != Volatile) - return; - m_state = NonVolatile; - makePurgeable(true); -} - const char* PurgeableBuffer::data() const { ASSERT(m_state == NonVolatile); diff --git a/WebCore/platform/network/curl/CookieJarCurl.cpp b/WebCore/platform/network/curl/CookieJarCurl.cpp index 6f8a6b7..36495d0 100644 --- a/WebCore/platform/network/curl/CookieJarCurl.cpp +++ b/WebCore/platform/network/curl/CookieJarCurl.cpp @@ -61,9 +61,11 @@ void deleteCookie(const Document*, const KURL&, const String&) // FIXME: Not yet implemented } +#if !PLATFORM(EFL) void setCookieStoragePrivateBrowsingEnabled(bool enabled) { // FIXME: Not yet implemented } +#endif } diff --git a/WebCore/platform/network/soup/SocketStreamHandle.h b/WebCore/platform/network/soup/SocketStreamHandle.h index 2ba4504..08d2d94 100644 --- a/WebCore/platform/network/soup/SocketStreamHandle.h +++ b/WebCore/platform/network/soup/SocketStreamHandle.h @@ -51,6 +51,7 @@ namespace WebCore { void connected(GSocketConnection*, GError*); void readBytes(signed long, GError*); void writeReady(); + void* id() { return m_id; } protected: virtual int platformSend(const char* data, int length); @@ -62,6 +63,7 @@ namespace WebCore { PlatformRefPtr<GOutputStream> m_outputStream; PlatformRefPtr<GSource> m_writeReadySource; char* m_readBuffer; + void* m_id; SocketStreamHandle(const KURL&, SocketStreamHandleClient*); diff --git a/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp b/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp index d73b499..7f62d5a 100644 --- a/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp +++ b/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp @@ -48,25 +48,34 @@ namespace WebCore { // These functions immediately call the similarly named SocketStreamHandle methods. -static void connectedCallback(GSocketClient*, GAsyncResult*, SocketStreamHandle*); -static void readReadyCallback(GInputStream*, GAsyncResult*, SocketStreamHandle*); -static gboolean writeReadyCallback(GSocket*, GIOCondition, SocketStreamHandle*); +static void connectedCallback(GSocketClient*, GAsyncResult*, void*); +static void readReadyCallback(GInputStream*, GAsyncResult*, void*); +static gboolean writeReadyCallback(GSocket*, GIOCondition, void*); // Having a list of active handles means that we do not have to worry about WebCore // reference counting in GLib callbacks. Once the handle is off the active handles list // we just ignore it in the callback. We avoid a lot of extra checks and tricky // situations this way. -static Vector<SocketStreamHandle*> gActiveHandles; -bool isActiveHandle(SocketStreamHandle* handle) +static HashMap<void*, SocketStreamHandle*> gActiveHandles; +static SocketStreamHandle* getHandleFromId(void* id) { - return gActiveHandles.find(handle) != notFound; + if (!gActiveHandles.contains(id)) + return 0; + return gActiveHandles.get(id); } -void deactivateHandle(SocketStreamHandle* handle) +static void deactivateHandle(SocketStreamHandle* handle) { - size_t handleIndex = gActiveHandles.find(handle); - if (handleIndex != notFound) - gActiveHandles.remove(handleIndex); + gActiveHandles.remove(handle->id()); +} + +static void* activateHandle(SocketStreamHandle* handle) +{ + // The first id cannot be 0, because it conflicts with the HashMap emptyValue. + static gint currentHandleId = 1; + void* id = GINT_TO_POINTER(currentHandleId++); + gActiveHandles.set(id, handle); + return id; } SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient* client) @@ -78,10 +87,10 @@ SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient return; unsigned int port = url.hasPort() ? url.port() : 80; - gActiveHandles.append(this); + m_id = activateHandle(this); PlatformRefPtr<GSocketClient> socketClient = adoptPlatformRef(g_socket_client_new()); g_socket_client_connect_to_host_async(socketClient.get(), url.host().utf8().data(), port, 0, - reinterpret_cast<GAsyncReadyCallback>(connectedCallback), this); + reinterpret_cast<GAsyncReadyCallback>(connectedCallback), m_id); } SocketStreamHandle::~SocketStreamHandle() @@ -104,7 +113,7 @@ void SocketStreamHandle::connected(GSocketConnection* socketConnection, GError* m_readBuffer = new char[READ_BUFFER_SIZE]; g_input_stream_read_async(m_inputStream.get(), m_readBuffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT, 0, - reinterpret_cast<GAsyncReadyCallback>(readReadyCallback), this); + reinterpret_cast<GAsyncReadyCallback>(readReadyCallback), m_id); // The client can close the handle, potentially removing the last reference. RefPtr<SocketStreamHandle> protect(this); @@ -131,7 +140,7 @@ void SocketStreamHandle::readBytes(signed long bytesRead, GError* error) m_client->didReceiveData(this, m_readBuffer, bytesRead); if (m_inputStream) // The client may have closed the connection. g_input_stream_read_async(m_inputStream.get(), m_readBuffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT, 0, - reinterpret_cast<GAsyncReadyCallback>(readReadyCallback), this); + reinterpret_cast<GAsyncReadyCallback>(readReadyCallback), m_id); } void SocketStreamHandle::writeReady() @@ -215,7 +224,7 @@ void SocketStreamHandle::beginWaitingForSocketWritability() m_writeReadySource = adoptPlatformRef(g_socket_create_source( g_socket_connection_get_socket(m_socketConnection.get()), static_cast<GIOCondition>(G_IO_OUT), 0)); - g_source_set_callback(m_writeReadySource.get(), reinterpret_cast<GSourceFunc>(writeReadyCallback), this, 0); + g_source_set_callback(m_writeReadySource.get(), reinterpret_cast<GSourceFunc>(writeReadyCallback), m_id, 0); g_source_attach(m_writeReadySource.get(), 0); } @@ -228,14 +237,15 @@ void SocketStreamHandle::stopWaitingForSocketWritability() m_writeReadySource = 0; } -static void connectedCallback(GSocketClient* client, GAsyncResult* result, SocketStreamHandle* handle) +static void connectedCallback(GSocketClient* client, GAsyncResult* result, void* id) { // Always finish the connection, even if this SocketStreamHandle was deactivated earlier. GOwnPtr<GError> error; GSocketConnection* socketConnection = g_socket_client_connect_to_host_finish(client, result, &error.outPtr()); // The SocketStreamHandle has been deactivated, so just close the connection, ignoring errors. - if (!isActiveHandle(handle)) { + SocketStreamHandle* handle = getHandleFromId(id); + if (!handle) { g_io_stream_close(G_IO_STREAM(socketConnection), 0, &error.outPtr()); return; } @@ -243,20 +253,23 @@ static void connectedCallback(GSocketClient* client, GAsyncResult* result, Socke handle->connected(socketConnection, error.get()); } -static void readReadyCallback(GInputStream* stream, GAsyncResult* result, SocketStreamHandle* handle) +static void readReadyCallback(GInputStream* stream, GAsyncResult* result, void* id) { // Always finish the read, even if this SocketStreamHandle was deactivated earlier. GOwnPtr<GError> error; gssize bytesRead = g_input_stream_read_finish(stream, result, &error.outPtr()); - if (!isActiveHandle(handle)) + SocketStreamHandle* handle = getHandleFromId(id); + if (!handle) return; + handle->readBytes(bytesRead, error.get()); } -static gboolean writeReadyCallback(GSocket*, GIOCondition condition, SocketStreamHandle* handle) +static gboolean writeReadyCallback(GSocket*, GIOCondition condition, void* id) { - if (!isActiveHandle(handle)) + SocketStreamHandle* handle = getHandleFromId(id); + if (!handle) return FALSE; // G_IO_HUP and G_IO_ERR are are always active. See: diff --git a/WebCore/platform/qt/ContextMenuItemQt.cpp b/WebCore/platform/qt/ContextMenuItemQt.cpp index b91a2a7..a65e50c 100644 --- a/WebCore/platform/qt/ContextMenuItemQt.cpp +++ b/WebCore/platform/qt/ContextMenuItemQt.cpp @@ -104,6 +104,12 @@ void ContextMenuItem::setChecked(bool on) m_platformDescription.checked = on; } +bool ContextMenuItem::checked() const +{ + // FIXME - Implement + return false; +} + void ContextMenuItem::setEnabled(bool on) { m_platformDescription.enabled = on; diff --git a/WebCore/platform/qt/ContextMenuQt.cpp b/WebCore/platform/qt/ContextMenuQt.cpp index 30c4c2d..2c1a6cb 100644 --- a/WebCore/platform/qt/ContextMenuQt.cpp +++ b/WebCore/platform/qt/ContextMenuQt.cpp @@ -74,6 +74,11 @@ PlatformMenuDescription ContextMenu::releasePlatformDescription() return PlatformMenuDescription(); } +Vector<ContextMenuItem> contextMenuItemVector(PlatformMenuDescription) +{ + // FIXME - Implement + return Vector<ContextMenuItem>(); +} } // vim: ts=4 sw=4 et diff --git a/WebCore/platform/qt/PlatformScreenQt.cpp b/WebCore/platform/qt/PlatformScreenQt.cpp index 8221760..db34e21 100644 --- a/WebCore/platform/qt/PlatformScreenQt.cpp +++ b/WebCore/platform/qt/PlatformScreenQt.cpp @@ -58,16 +58,30 @@ int screenDepth(Widget* w) int screenDepthPerComponent(Widget* w) { + int depth = QApplication::desktop()->screen(0)->depth(); if (w) { QWebPageClient* client = w->root()->hostWindow()->platformPageClient(); if (client) { QWidget* view = client->ownerWidget(); if (view) - return view->depth(); + depth = view->depth(); } } - return QApplication::desktop()->screen(0)->depth(); + // An interface to establish the actual number of bits per color + // doesn't exist in Qt, or probably at all, so use common-sense + // values for each screen depth and assume RGB/RGBA where appropriate. + // Per http://www.w3.org/TR/css3-mediaqueries/#color, 'If different color + // components are represented by different number of bits, the smallest + // number is used.' + switch (depth) { + case 8: + return 2; + case 32: + return 8; + default: + return qRound(depth / 3); + } } bool screenIsMonochrome(Widget* w) diff --git a/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp b/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp index be3f302..990e331 100644 --- a/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp +++ b/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp @@ -300,7 +300,7 @@ int textBreakNext(TextBreakIterator* iterator) if ((iterator->m_type == UBRK_LINE && iterator->m_logAttrs[index].is_line_break) || (iterator->m_type == UBRK_WORD && (iterator->m_logAttrs[index].is_word_start || iterator->m_logAttrs[index].is_word_end)) || (iterator->m_type == UBRK_CHARACTER && iterator->m_logAttrs[index].is_cursor_position) - || (iterator->m_type == UBRK_SENTENCE && (iterator->m_logAttrs[index].is_sentence_start || iterator->m_logAttrs[index].is_sentence_end)) ) { + || (iterator->m_type == UBRK_SENTENCE && iterator->m_logAttrs[index].is_sentence_boundary)) { break; } } @@ -315,7 +315,7 @@ int textBreakPrevious(TextBreakIterator* iterator) if ((iterator->m_type == UBRK_LINE && iterator->m_logAttrs[index].is_line_break) || (iterator->m_type == UBRK_WORD && (iterator->m_logAttrs[index].is_word_start || iterator->m_logAttrs[index].is_word_end)) || (iterator->m_type == UBRK_CHARACTER && iterator->m_logAttrs[index].is_cursor_position) - || (iterator->m_type == UBRK_SENTENCE && (iterator->m_logAttrs[index].is_sentence_start || iterator->m_logAttrs[index].is_sentence_end)) ) { + || (iterator->m_type == UBRK_SENTENCE && iterator->m_logAttrs[index].is_sentence_boundary)) { break; } } diff --git a/WebCore/platform/text/gtk/TextCodecGtk.cpp b/WebCore/platform/text/gtk/TextCodecGtk.cpp index bf6afcd..9308b33 100644 --- a/WebCore/platform/text/gtk/TextCodecGtk.cpp +++ b/WebCore/platform/text/gtk/TextCodecGtk.cpp @@ -543,9 +543,28 @@ CString TextCodecGtk::encode(const UChar* characters, size_t length, Unencodable &error.outPtr()); input += bytesRead; inputLength -= bytesRead; - result.grow(size + bytesWritten); - memcpy(result.data() + size, buffer, bytesWritten); - size += bytesWritten; + if (bytesWritten > 0) { + result.grow(size + bytesWritten); + memcpy(result.data() + size, buffer, bytesWritten); + size += bytesWritten; + } + + if (error && g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_INVALID_DATA)) { + UChar codePoint = reinterpret_cast<const UChar*>(input)[0]; + UnencodableReplacementArray replacement; + int replacementLength = TextCodec::getUnencodableReplacement(codePoint, handling, replacement); + + // Consume the invalid character. + input += sizeof(UChar); + inputLength -= sizeof(UChar); + + // Append replacement string to result buffer. + result.grow(size + replacementLength); + memcpy(result.data() + size, replacement, replacementLength); + size += replacementLength; + + error.clear(); + } } while (inputLength && !error.get()); if (error) { diff --git a/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/WebCore/platform/win/ClipboardUtilitiesWin.cpp index 19888bf..eb1e659 100644 --- a/WebCore/platform/win/ClipboardUtilitiesWin.cpp +++ b/WebCore/platform/win/ClipboardUtilitiesWin.cpp @@ -86,13 +86,13 @@ static bool getWebLocData(IDataObject* dataObject, String& url, String* title) if (!hdrop) return false; - if (!DragQueryFileW(hdrop, 0, filename, ARRAYSIZE(filename))) + if (!DragQueryFileW(hdrop, 0, filename, WTF_ARRAY_LENGTH(filename))) goto exit; if (_wcsicmp(PathFindExtensionW(filename), L".url")) goto exit; - if (!GetPrivateProfileStringW(L"InternetShortcut", L"url", 0, urlBuffer, ARRAYSIZE(urlBuffer), filename)) + if (!GetPrivateProfileStringW(L"InternetShortcut", L"url", 0, urlBuffer, WTF_ARRAY_LENGTH(urlBuffer), filename)) goto exit; if (title) { diff --git a/WebCore/platform/win/ClipboardWin.cpp b/WebCore/platform/win/ClipboardWin.cpp index f467d65..58cfe44 100644 --- a/WebCore/platform/win/ClipboardWin.cpp +++ b/WebCore/platform/win/ClipboardWin.cpp @@ -56,7 +56,7 @@ #include <wininet.h> #include <wtf/RefPtr.h> #include <wtf/text/CString.h> -#include <wtf/text/StringConcatenate.h> +#include <wtf/text/StringConcatenate.h> #include <wtf/text/StringHash.h> using namespace std; @@ -99,6 +99,7 @@ static inline FORMATETC* fileContentFormatZero() return &fileContentFormat; } +#if !OS(WINCE) static inline void pathRemoveBadFSCharacters(PWSTR psz, size_t length) { size_t writeTo = 0; @@ -112,9 +113,14 @@ static inline void pathRemoveBadFSCharacters(PWSTR psz, size_t length) } psz[writeTo] = 0; } +#endif static String filesystemPathFromUrlOrTitle(const String& url, const String& title, TCHAR* extension, bool isLink) { +#if OS(WINCE) + notImplemented(); + return String(); +#else static const size_t fsPathMaxLengthExcludingNullTerminator = MAX_PATH - 1; bool usedURL = false; WCHAR fsPathBuffer[MAX_PATH]; @@ -159,25 +165,7 @@ static String filesystemPathFromUrlOrTitle(const String& url, const String& titl String result(static_cast<UChar*>(fsPathBuffer)); result += String(static_cast<UChar*>(extension)); return result; -} - -static HGLOBAL createGlobalURLContent(const CString& content) -{ - HRESULT hr = S_OK; - HGLOBAL memObj = 0; - - char* fileContents; - - memObj = GlobalAlloc(GPTR, content.length()); - if (!memObj) - return 0; - - fileContents = (PSTR)GlobalLock(memObj); - CopyMemory(fileContents, content.data(), content.length()); - - GlobalUnlock(memObj); - - return memObj; +#endif } static HGLOBAL createGlobalImageFileContent(SharedBuffer* data) @@ -213,9 +201,13 @@ static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, Share else return 0; } else { +#if OS(WINCE) + notImplemented(); + return 0; +#else WCHAR tempPath[MAX_PATH]; WCHAR extension[MAX_PATH]; - if (!::GetTempPath(ARRAYSIZE(tempPath), tempPath)) + if (!::GetTempPath(WTF_ARRAY_LENGTH(tempPath), tempPath)) return 0; if (!::PathAppend(tempPath, fileName.charactersWithNullTermination())) return 0; @@ -242,6 +234,7 @@ static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, Share CloseHandle(tempFileHandle); if (!tempWriteSucceeded) return 0; +#endif } SIZE_T dropFilesSize = sizeof(DROPFILES) + (sizeof(WCHAR) * (wcslen(filePath) + 2)); @@ -258,36 +251,6 @@ static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, Share return memObj; } -static HGLOBAL createGlobalUrlFileDescriptor(const String& url, const String& title, const CString& content) -{ - HRESULT hr = S_OK; - HGLOBAL memObj = 0; - String fsPath; - memObj = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR)); - if (!memObj) - return 0; - - FILEGROUPDESCRIPTOR* fgd = (FILEGROUPDESCRIPTOR*)GlobalLock(memObj); - memset(fgd, 0, sizeof(FILEGROUPDESCRIPTOR)); - fgd->cItems = 1; - fgd->fgd[0].dwFlags = FD_FILESIZE; - fgd->fgd[0].nFileSizeLow = content.length(); - fsPath = filesystemPathFromUrlOrTitle(url, title, L".URL", true); - - if (fsPath.length() <= 0) { - GlobalUnlock(memObj); - GlobalFree(memObj); - return 0; - } - - int maxSize = min(fsPath.length(), ARRAYSIZE(fgd->fgd[0].cFileName)); - CopyMemory(fgd->fgd[0].cFileName, (LPCWSTR)fsPath.characters(), maxSize * sizeof(UChar)); - GlobalUnlock(memObj); - - return memObj; -} - - static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String& title, CachedImage* image) { ASSERT_ARG(image, image); @@ -322,7 +285,7 @@ static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String& return 0; } - int maxSize = min(fsPath.length(), ARRAYSIZE(fgd->fgd[0].cFileName)); + int maxSize = min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName)); CopyMemory(fgd->fgd[0].cFileName, (LPCWSTR)fsPath.characters(), maxSize * sizeof(UChar)); GlobalUnlock(memObj); @@ -355,11 +318,13 @@ static HRESULT writeFileToDataObject(IDataObject* dataObject, HGLOBAL fileDescri if (FAILED(hr = dataObject->SetData(fe, &medium, TRUE))) goto exit; +#if PLATFORM(CF) // HDROP if (hDropContent) { medium.hGlobal = hDropContent; hr = dataObject->SetData(cfHDropFormat(), &medium, TRUE); } +#endif exit: if (FAILED(hr)) { @@ -567,6 +532,10 @@ HashSet<String> ClipboardWin::types() const PassRefPtr<FileList> ClipboardWin::files() const { +#if OS(WINCE) + notImplemented(); + return 0; +#else RefPtr<FileList> files = FileList::create(); if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable) return files.release(); @@ -585,7 +554,7 @@ PassRefPtr<FileList> ClipboardWin::files() const WCHAR filename[MAX_PATH]; UINT fileCount = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0); for (UINT i = 0; i < fileCount; i++) { - if (!DragQueryFileW(hdrop, i, filename, ARRAYSIZE(filename))) + if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename))) continue; files->append(File::create(reinterpret_cast<UChar*>(filename))); } @@ -593,6 +562,7 @@ PassRefPtr<FileList> ClipboardWin::files() const GlobalUnlock(medium.hGlobal); ReleaseStgMedium(&medium); return files.release(); +#endif } void ClipboardWin::setDragImage(CachedImage* image, Node *node, const IntPoint &loc) @@ -725,16 +695,36 @@ void ClipboardWin::writeURL(const KURL& kurl, const String& titleStr, Frame*) String url = kurl.string(); ASSERT(url.containsOnlyASCII()); // KURL::string() is URL encoded. + String fsPath = filesystemPathFromUrlOrTitle(url, titleStr, L".URL", true); CString content = makeString("[InternetShortcut]\r\nURL=", url, "\r\n").ascii(); - HGLOBAL urlFileDescriptor = createGlobalUrlFileDescriptor(url, titleStr, content); + if (fsPath.length() <= 0) + return; + + HGLOBAL urlFileDescriptor = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR)); if (!urlFileDescriptor) return; - HGLOBAL urlFileContent = createGlobalURLContent(content); + + HGLOBAL urlFileContent = GlobalAlloc(GPTR, content.length()); if (!urlFileContent) { GlobalFree(urlFileDescriptor); return; } + + FILEGROUPDESCRIPTOR* fgd = static_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(urlFileDescriptor)); + ZeroMemory(fgd, sizeof(FILEGROUPDESCRIPTOR)); + fgd->cItems = 1; + fgd->fgd[0].dwFlags = FD_FILESIZE; + fgd->fgd[0].nFileSizeLow = content.length(); + + unsigned maxSize = min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName)); + CopyMemory(fgd->fgd[0].cFileName, fsPath.characters(), maxSize * sizeof(UChar)); + GlobalUnlock(urlFileDescriptor); + + char* fileContents = static_cast<char*>(GlobalLock(urlFileContent)); + CopyMemory(fileContents, content.data(), content.length()); + GlobalUnlock(urlFileContent); + writeFileToDataObject(m_writableDataObject.get(), urlFileDescriptor, urlFileContent, 0); } diff --git a/WebCore/platform/win/ContextMenuItemWin.cpp b/WebCore/platform/win/ContextMenuItemWin.cpp index ade0db0..d2ce76d 100644 --- a/WebCore/platform/win/ContextMenuItemWin.cpp +++ b/WebCore/platform/win/ContextMenuItemWin.cpp @@ -184,6 +184,12 @@ void ContextMenuItem::setChecked(bool checked) } } +bool ContextMenuItem::checked() const +{ + // FIXME - Implement + return false; +} + void ContextMenuItem::setEnabled(bool enabled) { m_platformDescription->fMask |= MIIM_STATE; diff --git a/WebCore/platform/win/ContextMenuWin.cpp b/WebCore/platform/win/ContextMenuWin.cpp index 5260866..82511e4 100644 --- a/WebCore/platform/win/ContextMenuWin.cpp +++ b/WebCore/platform/win/ContextMenuWin.cpp @@ -155,4 +155,10 @@ HMENU ContextMenu::releasePlatformDescription() return description; } +Vector<ContextMenuItem> contextMenuItemVector(PlatformMenuDescription) +{ + // FIXME - Implement + return Vector<ContextMenuItem>(); +} + } diff --git a/WebCore/platform/win/DragDataWin.cpp b/WebCore/platform/win/DragDataWin.cpp index 05f9103..56345e2 100644 --- a/WebCore/platform/win/DragDataWin.cpp +++ b/WebCore/platform/win/DragDataWin.cpp @@ -72,7 +72,7 @@ void DragData::asFilenames(Vector<String>& result) const const unsigned numFiles = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0); for (unsigned i = 0; i < numFiles; i++) { - if (!DragQueryFileW(hdrop, 0, filename, ARRAYSIZE(filename))) + if (!DragQueryFileW(hdrop, 0, filename, WTF_ARRAY_LENGTH(filename))) continue; result.append((UChar*)filename); } diff --git a/WebCore/platform/win/FileSystemWin.cpp b/WebCore/platform/win/FileSystemWin.cpp index 2cca08c..cef7196 100644 --- a/WebCore/platform/win/FileSystemWin.cpp +++ b/WebCore/platform/win/FileSystemWin.cpp @@ -274,7 +274,7 @@ bool safeCreateFile(const String& path, CFDataRef data) { // Create a temporary file. WCHAR tempDirPath[MAX_PATH]; - if (!GetTempPathW(ARRAYSIZE(tempDirPath), tempDirPath)) + if (!GetTempPathW(WTF_ARRAY_LENGTH(tempDirPath), tempDirPath)) return false; WCHAR tempPath[MAX_PATH]; diff --git a/WebCore/platform/win/WCDataObject.cpp b/WebCore/platform/win/WCDataObject.cpp index aaa41cf..6b4c859 100644 --- a/WebCore/platform/win/WCDataObject.cpp +++ b/WebCore/platform/win/WCDataObject.cpp @@ -285,6 +285,7 @@ void WCDataObject::CopyMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC { switch(pMedSrc->tymed) { +#if !OS(WINCE) case TYMED_HGLOBAL: pMedDest->hGlobal = (HGLOBAL)OleDuplicateData(pMedSrc->hGlobal,pFmtSrc->cfFormat, 0); break; @@ -300,6 +301,7 @@ void WCDataObject::CopyMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC case TYMED_FILE: pMedSrc->lpszFileName = (LPOLESTR)OleDuplicateData(pMedSrc->lpszFileName,pFmtSrc->cfFormat, 0); break; +#endif case TYMED_ISTREAM: pMedDest->pstm = pMedSrc->pstm; pMedSrc->pstm->AddRef(); |