summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/graphics/texmap
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/texmap')
-rw-r--r--Source/WebCore/platform/graphics/texmap/BitmapTexture.cpp64
-rw-r--r--Source/WebCore/platform/graphics/texmap/BitmapTexture.h98
-rw-r--r--Source/WebCore/platform/graphics/texmap/BitmapTextureGL.cpp347
-rw-r--r--Source/WebCore/platform/graphics/texmap/BitmapTextureGL.h114
-rw-r--r--Source/WebCore/platform/graphics/texmap/BitmapTexturePool.cpp114
-rw-r--r--Source/WebCore/platform/graphics/texmap/BitmapTexturePool.h80
-rw-r--r--Source/WebCore/platform/graphics/texmap/ClipStack.cpp90
-rw-r--r--Source/WebCore/platform/graphics/texmap/ClipStack.h74
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp274
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h136
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.cpp135
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.h101
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp393
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h104
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp7
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h13
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.cpp8
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.h7
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperGC3DPlatformLayer.cpp131
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperGC3DPlatformLayer.h64
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp742
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperGL.h164
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp162
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h82
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp225
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h59
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h18
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerBuffer.cpp67
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerBuffer.h80
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerProxy.cpp197
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerProxy.h111
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp193
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h32
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.cpp54
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.h55
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperTile.cpp17
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperTile.h11
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.cpp92
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.h31
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp1182
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.h246
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsState.h195
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.cpp182
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.h95
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.cpp54
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.h76
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/SurfaceUpdateInfo.h48
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/Tile.cpp116
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/Tile.h72
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStore.cpp425
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStore.h109
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStoreClient.h49
52 files changed, 5735 insertions, 1860 deletions
diff --git a/Source/WebCore/platform/graphics/texmap/BitmapTexture.cpp b/Source/WebCore/platform/graphics/texmap/BitmapTexture.cpp
new file mode 100644
index 000000000..487077be9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/BitmapTexture.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "BitmapTexture.h"
+
+#include "GraphicsLayer.h"
+#include "ImageBuffer.h"
+#include "TextureMapper.h"
+
+namespace WebCore {
+
+void BitmapTexture::updateContents(TextureMapper&, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag, float scale)
+{
+ // Making an unconditionally unaccelerated buffer here is OK because this code
+ // isn't used by any platforms that respect the accelerated bit.
+ std::unique_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(targetRect.size(), Unaccelerated);
+
+ if (!imageBuffer)
+ return;
+
+ GraphicsContext& context = imageBuffer->context();
+ context.setImageInterpolationQuality(InterpolationDefault);
+ context.setTextDrawingMode(TextModeFill);
+
+ IntRect sourceRect(targetRect);
+ sourceRect.setLocation(offset);
+ sourceRect.scale(1 / scale);
+ context.applyDeviceScaleFactor(scale);
+ context.translate(-sourceRect.x(), -sourceRect.y());
+
+ sourceLayer->paintGraphicsLayerContents(context, sourceRect);
+
+ RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
+ if (!image)
+ return;
+
+ updateContents(image.get(), targetRect, IntPoint(), updateContentsFlag);
+}
+
+} // namespace
diff --git a/Source/WebCore/platform/graphics/texmap/BitmapTexture.h b/Source/WebCore/platform/graphics/texmap/BitmapTexture.h
new file mode 100644
index 000000000..3245638a8
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/BitmapTexture.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 BitmapTexture_h
+#define BitmapTexture_h
+
+#include "IntPoint.h"
+#include "IntRect.h"
+#include "IntSize.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class FilterOperations;
+class GraphicsLayer;
+class Image;
+class TextureMapper;
+
+// A 2D texture that can be the target of software or GL rendering.
+class BitmapTexture : public RefCounted<BitmapTexture> {
+public:
+ enum Flag {
+ NoFlag = 0,
+ SupportsAlpha = 0x01,
+ FBOAttachment = 0x02
+ };
+
+ enum UpdateContentsFlag {
+ UpdateCanModifyOriginalImageData,
+ UpdateCannotModifyOriginalImageData
+ };
+
+ typedef unsigned Flags;
+
+ BitmapTexture()
+ : m_flags(0)
+ {
+ }
+
+ virtual ~BitmapTexture() { }
+ virtual bool isBackedByOpenGL() const { return false; }
+
+ virtual IntSize size() const = 0;
+ virtual void updateContents(Image*, const IntRect&, const IntPoint& offset, UpdateContentsFlag) = 0;
+ virtual void updateContents(TextureMapper&, GraphicsLayer*, const IntRect& target, const IntPoint& offset, UpdateContentsFlag, float scale = 1);
+ virtual void updateContents(const void*, const IntRect& target, const IntPoint& offset, int bytesPerLine, UpdateContentsFlag) = 0;
+ virtual bool isValid() const = 0;
+ inline Flags flags() const { return m_flags; }
+
+ virtual int bpp() const { return 32; }
+ void reset(const IntSize& size, Flags flags = 0)
+ {
+ m_flags = flags;
+ m_contentSize = size;
+ didReset();
+ }
+ virtual void didReset() { }
+
+ inline IntSize contentSize() const { return m_contentSize; }
+ inline int numberOfBytes() const { return size().width() * size().height() * bpp() >> 3; }
+ inline bool isOpaque() const { return !(m_flags & SupportsAlpha); }
+
+ virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper&, const FilterOperations&) { return this; }
+
+protected:
+ IntSize m_contentSize;
+
+private:
+ Flags m_flags;
+};
+
+}
+
+#endif // BitmapTexture_h
diff --git a/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.cpp b/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.cpp
new file mode 100644
index 000000000..589060224
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.cpp
@@ -0,0 +1,347 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012 Igalia S.L.
+ Copyright (C) 2012 Adobe Systems Incorporated
+
+ 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 "BitmapTextureGL.h"
+
+#if USE(TEXTURE_MAPPER_GL)
+
+#include "Extensions3D.h"
+#include "FilterOperations.h"
+#include "GraphicsContext.h"
+#include "Image.h"
+#include "LengthFunctions.h"
+#include "NotImplemented.h"
+#include "TextureMapperShaderProgram.h"
+#include "Timer.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+#if USE(CAIRO)
+#include "CairoUtilities.h"
+#include "RefPtrCairo.h"
+#include <cairo.h>
+#include <wtf/text/CString.h>
+#endif
+
+#if OS(DARWIN)
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#endif
+
+namespace WebCore {
+
+BitmapTextureGL* toBitmapTextureGL(BitmapTexture* texture)
+{
+ if (!texture || !texture->isBackedByOpenGL())
+ return 0;
+
+ return static_cast<BitmapTextureGL*>(texture);
+}
+
+BitmapTextureGL::BitmapTextureGL(RefPtr<GraphicsContext3D>&& context3D, const Flags flags)
+ : m_context3D(WTFMove(context3D))
+{
+ if (flags & FBOAttachment)
+ m_internalFormat = m_format = GraphicsContext3D::RGBA;
+ else {
+ // If GL_EXT_texture_format_BGRA8888 is supported in the OpenGLES
+ // internal and external formats need to be BGRA
+ m_internalFormat = GraphicsContext3D::RGBA;
+ m_format = GraphicsContext3D::BGRA;
+ if (m_context3D->isGLES2Compliant()) {
+ if (m_context3D->getExtensions().supports("GL_EXT_texture_format_BGRA8888"))
+ m_internalFormat = GraphicsContext3D::BGRA;
+ else
+ m_format = GraphicsContext3D::RGBA;
+ }
+ }
+}
+
+static void swizzleBGRAToRGBA(uint32_t* data, const IntRect& rect, int stride = 0)
+{
+ stride = stride ? stride : rect.width();
+ for (int y = rect.y(); y < rect.maxY(); ++y) {
+ uint32_t* p = data + y * stride;
+ for (int x = rect.x(); x < rect.maxX(); ++x)
+ p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
+ }
+}
+
+static bool driverSupportsSubImage(GraphicsContext3D* context)
+{
+ if (context->isGLES2Compliant()) {
+ static bool supportsSubImage = context->getExtensions().supports("GL_EXT_unpack_subimage");
+ return supportsSubImage;
+ }
+
+ return true;
+}
+
+void BitmapTextureGL::didReset()
+{
+ if (!m_id)
+ m_id = m_context3D->createTexture();
+
+ m_shouldClear = true;
+ if (m_textureSize == contentSize())
+ return;
+
+ m_textureSize = contentSize();
+ m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id);
+ m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
+ m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
+ m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+ m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
+
+ m_context3D->texImage2DDirect(GraphicsContext3D::TEXTURE_2D, 0, m_internalFormat, m_textureSize.width(), m_textureSize.height(), 0, m_format, m_type, 0);
+}
+
+void BitmapTextureGL::updateContentsNoSwizzle(const void* srcData, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine, unsigned bytesPerPixel, Platform3DObject glFormat)
+{
+ m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id);
+ // For ES drivers that don't support sub-images.
+ if (driverSupportsSubImage(m_context3D.get())) {
+ // Use the OpenGL sub-image extension, now that we know it's available.
+ m_context3D->pixelStorei(GraphicsContext3D::UNPACK_ROW_LENGTH, bytesPerLine / bytesPerPixel);
+ m_context3D->pixelStorei(GraphicsContext3D::UNPACK_SKIP_ROWS, sourceOffset.y());
+ m_context3D->pixelStorei(GraphicsContext3D::UNPACK_SKIP_PIXELS, sourceOffset.x());
+ }
+
+ m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, m_type, srcData);
+
+ // For ES drivers that don't support sub-images.
+ if (driverSupportsSubImage(m_context3D.get())) {
+ m_context3D->pixelStorei(GraphicsContext3D::UNPACK_ROW_LENGTH, 0);
+ m_context3D->pixelStorei(GraphicsContext3D::UNPACK_SKIP_ROWS, 0);
+ m_context3D->pixelStorei(GraphicsContext3D::UNPACK_SKIP_PIXELS, 0);
+ }
+}
+
+void BitmapTextureGL::updateContents(const void* srcData, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag updateContentsFlag)
+{
+ m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id);
+
+ const unsigned bytesPerPixel = 4;
+ char* data = reinterpret_cast<char*>(const_cast<void*>(srcData));
+ Vector<char> temporaryData;
+ IntPoint adjustedSourceOffset = sourceOffset;
+
+ // Texture upload requires subimage buffer if driver doesn't support subimage and we don't have full image upload.
+ bool requireSubImageBuffer = !driverSupportsSubImage(m_context3D.get())
+ && !(bytesPerLine == static_cast<int>(targetRect.width() * bytesPerPixel) && adjustedSourceOffset == IntPoint::zero());
+
+ // prepare temporaryData if necessary
+ if ((m_format == GraphicsContext3D::RGBA && updateContentsFlag == UpdateCannotModifyOriginalImageData) || requireSubImageBuffer) {
+ temporaryData.resize(targetRect.width() * targetRect.height() * bytesPerPixel);
+ data = temporaryData.data();
+ const char* bits = static_cast<const char*>(srcData);
+ const char* src = bits + sourceOffset.y() * bytesPerLine + sourceOffset.x() * bytesPerPixel;
+ char* dst = data;
+ const int targetBytesPerLine = targetRect.width() * bytesPerPixel;
+ for (int y = 0; y < targetRect.height(); ++y) {
+ memcpy(dst, src, targetBytesPerLine);
+ src += bytesPerLine;
+ dst += targetBytesPerLine;
+ }
+
+ bytesPerLine = targetBytesPerLine;
+ adjustedSourceOffset = IntPoint(0, 0);
+ }
+
+ if (m_format == GraphicsContext3D::RGBA)
+ swizzleBGRAToRGBA(reinterpret_cast_ptr<uint32_t*>(data), IntRect(adjustedSourceOffset, targetRect.size()), bytesPerLine / bytesPerPixel);
+
+ updateContentsNoSwizzle(data, targetRect, adjustedSourceOffset, bytesPerLine, bytesPerPixel, m_format);
+}
+
+void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag)
+{
+ if (!image)
+ return;
+ NativeImagePtr frameImage = image->nativeImageForCurrentFrame();
+ if (!frameImage)
+ return;
+
+ int bytesPerLine;
+ const char* imageData;
+
+#if USE(CAIRO)
+ cairo_surface_t* surface = frameImage.get();
+ imageData = reinterpret_cast<const char*>(cairo_image_surface_get_data(surface));
+ bytesPerLine = cairo_image_surface_get_stride(surface);
+#endif
+
+ updateContents(imageData, targetRect, offset, bytesPerLine, updateContentsFlag);
+}
+
+static unsigned getPassesRequiredForFilter(FilterOperation::OperationType type)
+{
+ switch (type) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::SEPIA:
+ case FilterOperation::SATURATE:
+ case FilterOperation::HUE_ROTATE:
+ case FilterOperation::INVERT:
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::OPACITY:
+ return 1;
+ case FilterOperation::BLUR:
+ case FilterOperation::DROP_SHADOW:
+ // We use two-passes (vertical+horizontal) for blur and drop-shadow.
+ return 2;
+ default:
+ return 0;
+ }
+}
+
+PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(TextureMapper& textureMapper, const FilterOperations& filters)
+{
+ if (filters.isEmpty())
+ return this;
+
+ TextureMapperGL& texmapGL = static_cast<TextureMapperGL&>(textureMapper);
+ RefPtr<BitmapTexture> previousSurface = texmapGL.currentSurface();
+ RefPtr<BitmapTexture> resultSurface = this;
+ RefPtr<BitmapTexture> intermediateSurface;
+ RefPtr<BitmapTexture> spareSurface;
+
+ m_filterInfo = FilterInfo();
+
+ for (size_t i = 0; i < filters.size(); ++i) {
+ RefPtr<FilterOperation> filter = filters.operations()[i];
+ ASSERT(filter);
+
+ int numPasses = getPassesRequiredForFilter(filter->type());
+ for (int j = 0; j < numPasses; ++j) {
+ bool last = (i == filters.size() - 1) && (j == numPasses - 1);
+ if (!last) {
+ if (!intermediateSurface)
+ intermediateSurface = texmapGL.acquireTextureFromPool(contentSize(), BitmapTexture::SupportsAlpha | BitmapTexture::FBOAttachment);
+ texmapGL.bindSurface(intermediateSurface.get());
+ }
+
+ if (last) {
+ toBitmapTextureGL(resultSurface.get())->m_filterInfo = BitmapTextureGL::FilterInfo(filter, j, spareSurface);
+ break;
+ }
+
+ texmapGL.drawFiltered(*resultSurface.get(), spareSurface.get(), *filter, j);
+ if (!j && filter->type() == FilterOperation::DROP_SHADOW) {
+ spareSurface = resultSurface;
+ resultSurface = nullptr;
+ }
+ std::swap(resultSurface, intermediateSurface);
+ }
+ }
+
+ texmapGL.bindSurface(previousSurface.get());
+ return resultSurface;
+}
+
+void BitmapTextureGL::initializeStencil()
+{
+ if (m_rbo)
+ return;
+
+ m_rbo = m_context3D->createRenderbuffer();
+ m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_rbo);
+ m_context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, m_textureSize.width(), m_textureSize.height());
+ m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
+ m_context3D->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_rbo);
+ m_context3D->clearStencil(0);
+ m_context3D->clear(GraphicsContext3D::STENCIL_BUFFER_BIT);
+}
+
+void BitmapTextureGL::initializeDepthBuffer()
+{
+ if (m_depthBufferObject)
+ return;
+
+ m_depthBufferObject = m_context3D->createRenderbuffer();
+ m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBufferObject);
+ m_context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, m_textureSize.width(), m_textureSize.height());
+ m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
+ m_context3D->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBufferObject);
+}
+
+void BitmapTextureGL::clearIfNeeded()
+{
+ if (!m_shouldClear)
+ return;
+
+ m_clipStack.reset(IntRect(IntPoint::zero(), m_textureSize), ClipStack::YAxisMode::Default);
+ m_clipStack.applyIfNeeded(*m_context3D);
+ m_context3D->clearColor(0, 0, 0, 0);
+ m_context3D->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
+ m_shouldClear = false;
+}
+
+void BitmapTextureGL::createFboIfNeeded()
+{
+ if (m_fbo)
+ return;
+
+ m_fbo = m_context3D->createFramebuffer();
+ m_context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
+ m_context3D->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, id(), 0);
+ m_shouldClear = true;
+}
+
+void BitmapTextureGL::bindAsSurface(GraphicsContext3D* context3D)
+{
+ context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
+ createFboIfNeeded();
+ context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
+ context3D->viewport(0, 0, m_textureSize.width(), m_textureSize.height());
+ clearIfNeeded();
+ m_clipStack.apply(*m_context3D);
+}
+
+BitmapTextureGL::~BitmapTextureGL()
+{
+ if (m_id)
+ m_context3D->deleteTexture(m_id);
+
+ if (m_fbo)
+ m_context3D->deleteFramebuffer(m_fbo);
+
+ if (m_rbo)
+ m_context3D->deleteRenderbuffer(m_rbo);
+
+ if (m_depthBufferObject)
+ m_context3D->deleteRenderbuffer(m_depthBufferObject);
+}
+
+bool BitmapTextureGL::isValid() const
+{
+ return m_id;
+}
+
+IntSize BitmapTextureGL::size() const
+{
+ return m_textureSize;
+}
+
+}; // namespace WebCore
+
+#endif // USE(TEXTURE_MAPPER_GL)
diff --git a/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.h b/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.h
new file mode 100644
index 000000000..c4a80224a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.h
@@ -0,0 +1,114 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2014 Igalia S.L.
+
+ 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 BitmapTextureGL_h
+#define BitmapTextureGL_h
+
+#if USE(TEXTURE_MAPPER_GL)
+
+#include "BitmapTexture.h"
+#include "ClipStack.h"
+#include "FilterOperation.h"
+#include "GraphicsContext3D.h"
+#include "IntSize.h"
+#include "TextureMapperGL.h"
+
+namespace WebCore {
+
+class TextureMapper;
+class TextureMapperGL;
+class FilterOperation;
+
+class BitmapTextureGL : public BitmapTexture {
+public:
+ static Ref<BitmapTexture> create(Ref<GraphicsContext3D>&& context3D, const Flags flags = NoFlag)
+ {
+ return adoptRef(*new BitmapTextureGL(WTFMove(context3D), flags));
+ }
+
+ virtual ~BitmapTextureGL();
+
+ IntSize size() const override;
+ bool isValid() const override;
+ void didReset() override;
+ void bindAsSurface(GraphicsContext3D*);
+ void initializeStencil();
+ void initializeDepthBuffer();
+ virtual uint32_t id() const { return m_id; }
+ uint32_t textureTarget() const { return GraphicsContext3D::TEXTURE_2D; }
+ IntSize textureSize() const { return m_textureSize; }
+ void updateContents(Image*, const IntRect&, const IntPoint&, UpdateContentsFlag) override;
+ void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag) override;
+ void updateContentsNoSwizzle(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine, unsigned bytesPerPixel = 4, Platform3DObject glFormat = GraphicsContext3D::RGBA);
+ bool isBackedByOpenGL() const override { return true; }
+
+ PassRefPtr<BitmapTexture> applyFilters(TextureMapper&, const FilterOperations&) override;
+ struct FilterInfo {
+ RefPtr<FilterOperation> filter;
+ unsigned pass;
+ RefPtr<BitmapTexture> contentTexture;
+
+ FilterInfo(PassRefPtr<FilterOperation> f = 0, unsigned p = 0, PassRefPtr<BitmapTexture> t = 0)
+ : filter(f)
+ , pass(p)
+ , contentTexture(t)
+ { }
+ };
+ const FilterInfo* filterInfo() const { return &m_filterInfo; }
+ ClipStack& clipStack() { return m_clipStack; }
+
+ GC3Dint internalFormat() const { return m_internalFormat; }
+
+private:
+ BitmapTextureGL(RefPtr<GraphicsContext3D>&&, const Flags);
+
+ Platform3DObject m_id { 0 };
+ IntSize m_textureSize;
+ IntRect m_dirtyRect;
+ Platform3DObject m_fbo { 0 };
+ Platform3DObject m_rbo { 0 };
+ Platform3DObject m_depthBufferObject { 0 };
+ bool m_shouldClear { true };
+ ClipStack m_clipStack;
+ RefPtr<GraphicsContext3D> m_context3D;
+
+ void clearIfNeeded();
+ void createFboIfNeeded();
+
+ FilterInfo m_filterInfo;
+
+ GC3Dint m_internalFormat;
+ GC3Denum m_format;
+ GC3Denum m_type {
+#if OS(DARWIN)
+ GL_UNSIGNED_INT_8_8_8_8_REV
+#else
+ GraphicsContext3D::UNSIGNED_BYTE
+#endif
+ };
+};
+
+BitmapTextureGL* toBitmapTextureGL(BitmapTexture*);
+
+}
+
+#endif // USE(TEXTURE_MAPPER_GL)
+
+#endif // BitmapTextureGL_h
diff --git a/Source/WebCore/platform/graphics/texmap/BitmapTexturePool.cpp b/Source/WebCore/platform/graphics/texmap/BitmapTexturePool.cpp
new file mode 100644
index 000000000..00cc8ee36
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/BitmapTexturePool.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "BitmapTexturePool.h"
+
+#if USE(TEXTURE_MAPPER_GL)
+#include "BitmapTextureGL.h"
+#endif
+
+namespace WebCore {
+
+static const double s_releaseUnusedSecondsTolerance = 3;
+static const double s_releaseUnusedTexturesTimerInterval = 0.5;
+
+#if USE(TEXTURE_MAPPER_GL)
+BitmapTexturePool::BitmapTexturePool(RefPtr<GraphicsContext3D>&& context3D)
+ : m_context3D(WTFMove(context3D))
+ , m_releaseUnusedTexturesTimer(*this, &BitmapTexturePool::releaseUnusedTexturesTimerFired)
+{
+}
+#endif
+
+RefPtr<BitmapTexture> BitmapTexturePool::acquireTexture(const IntSize& size, const BitmapTexture::Flags flags)
+{
+ Vector<Entry>& list = flags & BitmapTexture::FBOAttachment ? m_attachmentTextures : m_textures;
+
+ Entry* selectedEntry = std::find_if(list.begin(), list.end(),
+ [&size](Entry& entry) { return entry.m_texture->refCount() == 1 && entry.m_texture->size() == size; });
+
+ if (selectedEntry == list.end()) {
+ list.append(Entry(createTexture(flags)));
+ selectedEntry = &list.last();
+ }
+
+ scheduleReleaseUnusedTextures();
+ selectedEntry->markIsInUse();
+ return selectedEntry->m_texture.copyRef();
+}
+
+void BitmapTexturePool::scheduleReleaseUnusedTextures()
+{
+ if (m_releaseUnusedTexturesTimer.isActive())
+ return;
+
+ m_releaseUnusedTexturesTimer.startOneShot(s_releaseUnusedTexturesTimerInterval);
+}
+
+void BitmapTexturePool::releaseUnusedTexturesTimerFired()
+{
+ // Delete entries, which have been unused in s_releaseUnusedSecondsTolerance.
+ double minUsedTime = monotonicallyIncreasingTime() - s_releaseUnusedSecondsTolerance;
+
+ if (!m_textures.isEmpty()) {
+ std::sort(m_textures.begin(), m_textures.end(),
+ [](const Entry& a, const Entry& b) { return a.m_lastUsedTime > b.m_lastUsedTime; });
+
+ for (size_t i = 0; i < m_textures.size(); ++i) {
+ if (m_textures[i].m_lastUsedTime < minUsedTime) {
+ m_textures.remove(i, m_textures.size() - i);
+ break;
+ }
+ }
+ }
+
+ if (!m_attachmentTextures.isEmpty()) {
+ std::sort(m_attachmentTextures.begin(), m_attachmentTextures.end(),
+ [](const Entry& a, const Entry& b) { return a.m_lastUsedTime > b.m_lastUsedTime; });
+
+ for (size_t i = 0; i < m_attachmentTextures.size(); ++i) {
+ if (m_attachmentTextures[i].m_lastUsedTime < minUsedTime) {
+ m_attachmentTextures.remove(i, m_attachmentTextures.size() - i);
+ break;
+ }
+ }
+ }
+
+ if (!m_textures.isEmpty() || !m_attachmentTextures.isEmpty())
+ scheduleReleaseUnusedTextures();
+}
+
+RefPtr<BitmapTexture> BitmapTexturePool::createTexture(const BitmapTexture::Flags flags)
+{
+#if USE(TEXTURE_MAPPER_GL)
+ return BitmapTextureGL::create(*m_context3D, flags);
+#else
+ return nullptr;
+#endif
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/texmap/BitmapTexturePool.h b/Source/WebCore/platform/graphics/texmap/BitmapTexturePool.h
new file mode 100644
index 000000000..5c740fc10
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/BitmapTexturePool.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 BitmapTexturePool_h
+#define BitmapTexturePool_h
+
+#include "BitmapTexture.h"
+#include "Timer.h"
+#include <wtf/CurrentTime.h>
+
+#if USE(TEXTURE_MAPPER_GL)
+#include "GraphicsContext3D.h"
+#endif
+
+namespace WebCore {
+
+class GraphicsContext3D;
+class IntSize;
+
+class BitmapTexturePool {
+ WTF_MAKE_NONCOPYABLE(BitmapTexturePool);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+#if USE(TEXTURE_MAPPER_GL)
+ explicit BitmapTexturePool(RefPtr<GraphicsContext3D>&&);
+#endif
+
+ RefPtr<BitmapTexture> acquireTexture(const IntSize&, const BitmapTexture::Flags);
+
+private:
+ struct Entry {
+ explicit Entry(RefPtr<BitmapTexture>&& texture)
+ : m_texture(WTFMove(texture))
+ { }
+
+ void markIsInUse() { m_lastUsedTime = monotonicallyIncreasingTime(); }
+
+ RefPtr<BitmapTexture> m_texture;
+ double m_lastUsedTime { 0.0 };
+ };
+
+ void scheduleReleaseUnusedTextures();
+ void releaseUnusedTexturesTimerFired();
+ RefPtr<BitmapTexture> createTexture(const BitmapTexture::Flags);
+
+#if USE(TEXTURE_MAPPER_GL)
+ RefPtr<GraphicsContext3D> m_context3D;
+#endif
+
+ Vector<Entry> m_textures;
+ Vector<Entry> m_attachmentTextures;
+ Timer m_releaseUnusedTexturesTimer;
+};
+
+} // namespace WebCore
+
+#endif // BitmapTexturePool_h
diff --git a/Source/WebCore/platform/graphics/texmap/ClipStack.cpp b/Source/WebCore/platform/graphics/texmap/ClipStack.cpp
new file mode 100644
index 000000000..11a00bc8a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/ClipStack.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2012 Adobe Systems Incorporated
+ * Copyright (C) 2012, 2016 Igalia S.L.
+ *
+ * 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 "ClipStack.h"
+
+#include "GraphicsContext3D.h"
+
+namespace WebCore {
+
+void ClipStack::push()
+{
+ clipStack.append(clipState);
+ clipStateDirty = true;
+}
+
+void ClipStack::pop()
+{
+ if (clipStack.isEmpty())
+ return;
+ clipState = clipStack.last();
+ clipStack.removeLast();
+ clipStateDirty = true;
+}
+
+void ClipStack::reset(const IntRect& rect, ClipStack::YAxisMode mode)
+{
+ clipStack.clear();
+ size = rect.size();
+ yAxisMode = mode;
+ clipState = State(rect);
+ clipStateDirty = true;
+}
+
+void ClipStack::intersect(const IntRect& rect)
+{
+ clipState.scissorBox.intersect(rect);
+ clipStateDirty = true;
+}
+
+void ClipStack::setStencilIndex(int stencilIndex)
+{
+ clipState.stencilIndex = stencilIndex;
+ clipStateDirty = true;
+}
+
+void ClipStack::apply(GraphicsContext3D& context)
+{
+ if (clipState.scissorBox.isEmpty())
+ return;
+
+ context.scissor(clipState.scissorBox.x(),
+ (yAxisMode == YAxisMode::Inverted) ? size.height() - clipState.scissorBox.maxY() : clipState.scissorBox.y(),
+ clipState.scissorBox.width(), clipState.scissorBox.height());
+ context.stencilOp(GraphicsContext3D::KEEP, GraphicsContext3D::KEEP, GraphicsContext3D::KEEP);
+ context.stencilFunc(GraphicsContext3D::EQUAL, clipState.stencilIndex - 1, clipState.stencilIndex - 1);
+ if (clipState.stencilIndex == 1)
+ context.disable(GraphicsContext3D::STENCIL_TEST);
+ else
+ context.enable(GraphicsContext3D::STENCIL_TEST);
+}
+
+void ClipStack::applyIfNeeded(GraphicsContext3D& context)
+{
+ if (!clipStateDirty)
+ return;
+
+ clipStateDirty = false;
+ apply(context);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/texmap/ClipStack.h b/Source/WebCore/platform/graphics/texmap/ClipStack.h
new file mode 100644
index 000000000..2fc40475b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/ClipStack.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2015, 2016 Igalia S.L.
+ *
+ * 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 ClipStack_h
+#define ClipStack_h
+
+#include "IntRect.h"
+#include "IntSize.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class GraphicsContext3D;
+
+class ClipStack {
+public:
+ struct State {
+ State(const IntRect& scissors = IntRect(), int stencil = 1)
+ : scissorBox(scissors)
+ , stencilIndex(stencil)
+ { }
+
+ IntRect scissorBox;
+ int stencilIndex;
+ };
+
+ // Y-axis should be inverted only when painting into the window.
+ enum class YAxisMode {
+ Default,
+ Inverted,
+ };
+
+ void push();
+ void pop();
+ State& current() { return clipState; }
+
+ void reset(const IntRect&, YAxisMode);
+ void intersect(const IntRect&);
+ void setStencilIndex(int);
+ int getStencilIndex() const { return clipState.stencilIndex; }
+
+ void apply(GraphicsContext3D&);
+ void applyIfNeeded(GraphicsContext3D&);
+
+ bool isCurrentScissorBoxEmpty() const { return clipState.scissorBox.isEmpty(); }
+
+private:
+ Vector<State> clipStack;
+ State clipState;
+ IntSize size;
+ bool clipStateDirty { false };
+ YAxisMode yAxisMode { YAxisMode::Default };
+};
+
+} // namespace WebCore
+
+#endif // ClipStack_h
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
index 1b87ee626..78a0246f7 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
@@ -21,31 +21,25 @@
#include "GraphicsLayerTextureMapper.h"
#include "GraphicsContext.h"
-#include "GraphicsLayerAnimation.h"
#include "GraphicsLayerFactory.h"
#include "ImageBuffer.h"
+#include "TextureMapperAnimation.h"
#include <wtf/CurrentTime.h>
-#if USE(TEXTURE_MAPPER)
+#if !USE(COORDINATED_GRAPHICS)
namespace WebCore {
-TextureMapperLayer* toTextureMapperLayer(GraphicsLayer* layer)
-{
- return layer ? toGraphicsLayerTextureMapper(layer)->layer() : 0;
-}
-
-std::unique_ptr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client)
+std::unique_ptr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client, Type layerType)
{
if (!factory)
- return std::make_unique<GraphicsLayerTextureMapper>(client);
+ return std::make_unique<GraphicsLayerTextureMapper>(layerType, client);
- return factory->createGraphicsLayer(client);
+ return factory->createGraphicsLayer(layerType, client);
}
-GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(GraphicsLayerClient* client)
- : GraphicsLayer(client)
- , m_layer(adoptPtr(new TextureMapperLayer()))
+GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(Type layerType, GraphicsLayerClient& client)
+ : GraphicsLayer(layerType, client)
, m_compositedNativeImagePtr(0)
, m_changeMask(NoChanges)
, m_needsDisplay(false)
@@ -59,15 +53,11 @@ GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(GraphicsLayerClient* clie
void GraphicsLayerTextureMapper::notifyChange(ChangeMask changeMask)
{
+ bool flushRequired = m_changeMask == NoChanges;
m_changeMask |= changeMask;
- if (!client())
- return;
- client()->notifyFlushRequired(this);
-}
-void GraphicsLayerTextureMapper::setName(const String& name)
-{
- GraphicsLayer::setName(name);
+ if (flushRequired)
+ client().notifyFlushRequired(this);
}
GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper()
@@ -78,33 +68,23 @@ GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper()
willBeDestroyed();
}
-void GraphicsLayerTextureMapper::willBeDestroyed()
-{
- GraphicsLayer::willBeDestroyed();
-}
-
-/* \reimp (GraphicsLayer.h): The current size might change, thus we need to update the whole display.
-*/
void GraphicsLayerTextureMapper::setNeedsDisplay()
{
if (!drawsContent())
return;
+ // The current size might change, thus we need to update the whole display.
m_needsDisplay = true;
notifyChange(DisplayChange);
addRepaintRect(FloatRect(FloatPoint(), m_size));
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setContentsNeedsDisplay()
{
notifyChange(DisplayChange);
addRepaintRect(contentsRect());
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect, ShouldClipToLayer)
{
if (!drawsContent())
@@ -117,8 +97,6 @@ void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect, Sh
addRepaintRect(rect);
}
-/* \reimp (GraphicsLayer.h)
-*/
bool GraphicsLayerTextureMapper::setChildren(const Vector<GraphicsLayer*>& children)
{
if (GraphicsLayer::setChildren(children)) {
@@ -128,40 +106,30 @@ bool GraphicsLayerTextureMapper::setChildren(const Vector<GraphicsLayer*>& child
return false;
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::addChild(GraphicsLayer* layer)
{
notifyChange(ChildrenChange);
GraphicsLayer::addChild(layer);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::addChildAtIndex(GraphicsLayer* layer, int index)
{
GraphicsLayer::addChildAtIndex(layer, index);
notifyChange(ChildrenChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
{
GraphicsLayer::addChildAbove(layer, sibling);
notifyChange(ChildrenChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
{
GraphicsLayer::addChildBelow(layer, sibling);
notifyChange(ChildrenChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
{
if (GraphicsLayer::replaceChild(oldChild, newChild)) {
@@ -171,8 +139,6 @@ bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, GraphicsL
return false;
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setMaskLayer(GraphicsLayer* value)
{
if (value == maskLayer())
@@ -187,8 +153,6 @@ void GraphicsLayerTextureMapper::setMaskLayer(GraphicsLayer* value)
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value)
{
if (value == replicaLayer())
@@ -197,8 +161,6 @@ void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value)
notifyChange(ReplicaLayerChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value)
{
if (value == position())
@@ -207,8 +169,6 @@ void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value)
notifyChange(PositionChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value)
{
if (value == anchorPoint())
@@ -217,8 +177,6 @@ void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value)
notifyChange(AnchorPointChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setSize(const FloatSize& value)
{
if (value == size())
@@ -230,8 +188,6 @@ void GraphicsLayerTextureMapper::setSize(const FloatSize& value)
notifyChange(SizeChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value)
{
if (value == transform())
@@ -241,8 +197,6 @@ void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value)
notifyChange(TransformChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix& value)
{
if (value == childrenTransform())
@@ -251,8 +205,6 @@ void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix
notifyChange(ChildrenTransformChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setPreserves3D(bool value)
{
if (value == preserves3D())
@@ -261,8 +213,6 @@ void GraphicsLayerTextureMapper::setPreserves3D(bool value)
notifyChange(Preserves3DChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setMasksToBounds(bool value)
{
if (value == masksToBounds())
@@ -271,8 +221,6 @@ void GraphicsLayerTextureMapper::setMasksToBounds(bool value)
notifyChange(MasksToBoundsChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setDrawsContent(bool value)
{
if (value == drawsContent())
@@ -284,8 +232,6 @@ void GraphicsLayerTextureMapper::setDrawsContent(bool value)
setNeedsDisplay();
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setContentsVisible(bool value)
{
if (value == contentsAreVisible())
@@ -296,8 +242,6 @@ void GraphicsLayerTextureMapper::setContentsVisible(bool value)
maskLayer()->setContentsVisible(value);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setContentsOpaque(bool value)
{
if (value == contentsOpaque())
@@ -306,8 +250,6 @@ void GraphicsLayerTextureMapper::setContentsOpaque(bool value)
GraphicsLayer::setContentsOpaque(value);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value)
{
if (value == backfaceVisibility())
@@ -316,8 +258,6 @@ void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value)
notifyChange(BackfaceVisibilityChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setOpacity(float value)
{
if (value == opacity())
@@ -326,9 +266,7 @@ void GraphicsLayerTextureMapper::setOpacity(float value)
notifyChange(OpacityChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
-void GraphicsLayerTextureMapper::setContentsRect(const IntRect& value)
+void GraphicsLayerTextureMapper::setContentsRect(const FloatRect& value)
{
if (value == contentsRect())
return;
@@ -345,15 +283,12 @@ void GraphicsLayerTextureMapper::setContentsToSolidColor(const Color& color)
notifyChange(BackgroundColorChange);
}
-
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
{
if (image) {
// Make the decision about whether the image has changed.
// This code makes the assumption that pointer equality on a NativeImagePtr is a valid way to tell if the image is changed.
- // This assumption is true in Qt, GTK and EFL.
+ // This assumption is true for the GTK+ port.
NativeImagePtr newNativeImagePtr = image->nativeImageForCurrentFrame();
if (!newNativeImagePtr)
return;
@@ -365,28 +300,29 @@ void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
if (!m_compositedImage)
m_compositedImage = TextureMapperTiledBackingStore::create();
m_compositedImage->setContentsToImage(image);
+ m_compositedImage->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
} else {
- m_compositedNativeImagePtr = 0;
- m_compositedImage = 0;
+ m_compositedNativeImagePtr = nullptr;
+ m_compositedImage = nullptr;
}
- setContentsToMedia(m_compositedImage.get());
+ setContentsToPlatformLayer(m_compositedImage.get(), ContentsLayerForImage);
notifyChange(ContentChange);
GraphicsLayer::setContentsToImage(image);
}
-void GraphicsLayerTextureMapper::setContentsToMedia(TextureMapperPlatformLayer* media)
+void GraphicsLayerTextureMapper::setContentsToPlatformLayer(TextureMapperPlatformLayer* platformLayer, ContentsLayerPurpose purpose)
{
- if (media == m_contentsLayer)
+ if (platformLayer == m_contentsLayer)
return;
- GraphicsLayer::setContentsToMedia(media);
+ GraphicsLayer::setContentsToPlatformLayer(platformLayer, purpose);
notifyChange(ContentChange);
if (m_contentsLayer)
m_contentsLayer->setClient(0);
- m_contentsLayer = media;
+ m_contentsLayer = platformLayer;
if (m_contentsLayer)
m_contentsLayer->setClient(this);
@@ -428,26 +364,25 @@ void GraphicsLayerTextureMapper::setIsScrollable(bool isScrollable)
notifyChange(IsScrollableChange);
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::flushCompositingStateForThisLayerOnly()
{
prepareBackingStoreIfNeeded();
commitLayerChanges();
- m_layer->syncAnimations();
- updateBackingStoreIfNeeded();
+ m_layer.syncAnimations();
}
void GraphicsLayerTextureMapper::prepareBackingStoreIfNeeded()
{
- if (!shouldHaveBackingStore()) {
- m_backingStore.clear();
- m_changeMask |= BackingStoreChange;
- } else {
+ if (shouldHaveBackingStore()) {
if (!m_backingStore) {
m_backingStore = TextureMapperTiledBackingStore::create();
m_changeMask |= BackingStoreChange;
}
+ } else {
+ if (m_backingStore) {
+ m_backingStore = nullptr;
+ m_changeMask |= BackingStoreChange;
+ }
}
updateDebugBorderAndRepaintCount();
@@ -473,112 +408,98 @@ void GraphicsLayerTextureMapper::setDebugBorder(const Color& color, float width)
m_changeMask |= DebugVisualsChange;
}
-static void toTextureMapperLayerVector(const Vector<GraphicsLayer*>& layers, Vector<TextureMapperLayer*>& texmapLayers)
-{
- texmapLayers.reserveCapacity(layers.size());
- for (size_t i = 0; i < layers.size(); ++i)
- texmapLayers.append(toTextureMapperLayer(layers[i]));
-}
-
void GraphicsLayerTextureMapper::commitLayerChanges()
{
if (m_changeMask == NoChanges)
return;
- if (m_changeMask & ChildrenChange) {
- Vector<TextureMapperLayer*> textureMapperLayerChildren;
- toTextureMapperLayerVector(children(), textureMapperLayerChildren);
- m_layer->setChildren(textureMapperLayerChildren);
- }
+ if (m_changeMask & ChildrenChange)
+ m_layer.setChildren(children());
if (m_changeMask & MaskLayerChange)
- m_layer->setMaskLayer(toTextureMapperLayer(maskLayer()));
+ m_layer.setMaskLayer(&downcast<GraphicsLayerTextureMapper>(maskLayer())->layer());
if (m_changeMask & ReplicaLayerChange)
- m_layer->setReplicaLayer(toTextureMapperLayer(replicaLayer()));
+ m_layer.setReplicaLayer(&downcast<GraphicsLayerTextureMapper>(replicaLayer())->layer());
if (m_changeMask & PositionChange)
- m_layer->setPosition(position());
+ m_layer.setPosition(position());
if (m_changeMask & AnchorPointChange)
- m_layer->setAnchorPoint(anchorPoint());
+ m_layer.setAnchorPoint(anchorPoint());
if (m_changeMask & SizeChange)
- m_layer->setSize(size());
+ m_layer.setSize(size());
if (m_changeMask & TransformChange)
- m_layer->setTransform(transform());
+ m_layer.setTransform(transform());
if (m_changeMask & ChildrenTransformChange)
- m_layer->setChildrenTransform(childrenTransform());
+ m_layer.setChildrenTransform(childrenTransform());
if (m_changeMask & Preserves3DChange)
- m_layer->setPreserves3D(preserves3D());
+ m_layer.setPreserves3D(preserves3D());
if (m_changeMask & ContentsRectChange)
- m_layer->setContentsRect(contentsRect());
+ m_layer.setContentsRect(contentsRect());
if (m_changeMask & MasksToBoundsChange)
- m_layer->setMasksToBounds(masksToBounds());
+ m_layer.setMasksToBounds(masksToBounds());
if (m_changeMask & DrawsContentChange)
- m_layer->setDrawsContent(drawsContent());
+ m_layer.setDrawsContent(drawsContent());
if (m_changeMask & ContentsVisibleChange)
- m_layer->setContentsVisible(contentsAreVisible());
+ m_layer.setContentsVisible(contentsAreVisible());
if (m_changeMask & ContentsOpaqueChange)
- m_layer->setContentsOpaque(contentsOpaque());
+ m_layer.setContentsOpaque(contentsOpaque());
if (m_changeMask & BackfaceVisibilityChange)
- m_layer->setBackfaceVisibility(backfaceVisibility());
+ m_layer.setBackfaceVisibility(backfaceVisibility());
if (m_changeMask & OpacityChange)
- m_layer->setOpacity(opacity());
+ m_layer.setOpacity(opacity());
if (m_changeMask & BackgroundColorChange)
- m_layer->setSolidColor(solidColor());
+ m_layer.setSolidColor(m_solidColor);
-#if ENABLE(CSS_FILTERS)
if (m_changeMask & FilterChange)
- m_layer->setFilters(filters());
-#endif
+ m_layer.setFilters(filters());
if (m_changeMask & BackingStoreChange)
- m_layer->setBackingStore(m_backingStore);
+ m_layer.setBackingStore(m_backingStore);
if (m_changeMask & DebugVisualsChange)
- m_layer->setDebugVisuals(isShowingDebugBorder(), debugBorderColor(), debugBorderWidth(), isShowingRepaintCounter());
+ m_layer.setDebugVisuals(isShowingDebugBorder(), debugBorderColor(), debugBorderWidth(), isShowingRepaintCounter());
if (m_changeMask & RepaintCountChange)
- m_layer->setRepaintCount(repaintCount());
+ m_layer.setRepaintCount(repaintCount());
if (m_changeMask & ContentChange)
- m_layer->setContentsLayer(platformLayer());
+ m_layer.setContentsLayer(platformLayer());
if (m_changeMask & AnimationChange)
- m_layer->setAnimations(m_animations);
+ m_layer.setAnimations(m_animations);
if (m_changeMask & AnimationStarted)
- client()->notifyAnimationStarted(this, m_animationStartTime);
+ client().notifyAnimationStarted(this, "", m_animationStartTime);
if (m_changeMask & FixedToViewporChange)
- m_layer->setFixedToViewport(fixedToViewport());
+ m_layer.setFixedToViewport(fixedToViewport());
if (m_changeMask & IsScrollableChange)
- m_layer->setIsScrollable(isScrollable());
+ m_layer.setIsScrollable(isScrollable());
if (m_changeMask & CommittedScrollOffsetChange)
- m_layer->didCommitScrollOffset(m_committedScrollOffset);
+ m_layer.didCommitScrollOffset(m_committedScrollOffset);
m_changeMask = NoChanges;
}
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect& rect)
{
- if (!m_layer->textureMapper())
+ if (!m_layer.textureMapper())
return;
flushCompositingStateForThisLayerOnly();
@@ -587,13 +508,28 @@ void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect& rect)
maskLayer()->flushCompositingState(rect);
if (replicaLayer())
replicaLayer()->flushCompositingState(rect);
- for (size_t i = 0; i < children().size(); ++i)
- children()[i]->flushCompositingState(rect);
+ for (auto* child : children())
+ child->flushCompositingState(rect);
+}
+
+void GraphicsLayerTextureMapper::updateBackingStoreIncludingSubLayers()
+{
+ if (!m_layer.textureMapper())
+ return;
+
+ updateBackingStoreIfNeeded();
+
+ if (maskLayer())
+ downcast<GraphicsLayerTextureMapper>(*maskLayer()).updateBackingStoreIfNeeded();
+ if (replicaLayer())
+ downcast<GraphicsLayerTextureMapper>(*replicaLayer()).updateBackingStoreIfNeeded();
+ for (auto* child : children())
+ downcast<GraphicsLayerTextureMapper>(*child).updateBackingStoreIncludingSubLayers();
}
void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded()
{
- TextureMapper* textureMapper = m_layer->textureMapper();
+ TextureMapper* textureMapper = m_layer.textureMapper();
if (!textureMapper)
return;
@@ -610,8 +546,10 @@ void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded()
return;
TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());
+ backingStore->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
- backingStore->updateContents(textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
+ dirtyRect.scale(pageScaleFactor() * deviceScaleFactor());
+ backingStore->updateContents(*textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
m_needsDisplay = false;
m_needsDisplayRect = IntRect();
@@ -622,21 +560,44 @@ bool GraphicsLayerTextureMapper::shouldHaveBackingStore() const
return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
}
-bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
+bool GraphicsLayerTextureMapper::filtersCanBeComposited(const FilterOperations& filters) const
+{
+ if (!filters.size())
+ return false;
+
+ for (const auto& filterOperation : filters.operations()) {
+ if (filterOperation->type() == FilterOperation::REFERENCE)
+ return false;
+ }
+
+ return true;
+}
+
+bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
{
ASSERT(!keyframesName.isEmpty());
- if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity))
+ if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity))
return false;
+ if (valueList.property() == AnimatedPropertyFilter) {
+ int listIndex = validateFilterOperations(valueList);
+ if (listIndex < 0)
+ return false;
+
+ const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
+ if (!filtersCanBeComposited(filters))
+ return false;
+ }
+
bool listsMatch = false;
bool hasBigRotation;
- if (valueList.property() == AnimatedPropertyWebkitTransform)
+ if (valueList.property() == AnimatedPropertyTransform)
listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0;
const double currentTime = monotonicallyIncreasingTime();
- m_animations.add(GraphicsLayerAnimation(keyframesName, valueList, boxSize, anim, currentTime - timeOffset, listsMatch));
+ m_animations.add(TextureMapperAnimation(keyframesName, valueList, boxSize, *anim, listsMatch, currentTime - timeOffset, 0, TextureMapperAnimation::AnimationState::Playing));
// m_animationStartTime is the time of the first real frame of animation, now or delayed by a negative offset.
if (timeOffset > 0)
m_animationStartTime = currentTime;
@@ -647,7 +608,7 @@ bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList
return true;
}
-void GraphicsLayerTextureMapper::setAnimations(const GraphicsLayerAnimations& animations)
+void GraphicsLayerTextureMapper::setAnimations(const TextureMapperAnimations& animations)
{
m_animations = animations;
notifyChange(AnimationChange);
@@ -664,17 +625,26 @@ void GraphicsLayerTextureMapper::removeAnimation(const String& animationName)
m_animations.remove(animationName);
}
-#if ENABLE(CSS_FILTERS)
bool GraphicsLayerTextureMapper::setFilters(const FilterOperations& filters)
{
- TextureMapper* textureMapper = m_layer->textureMapper();
- // TextureMapperImageBuffer does not support CSS filters.
- if (!textureMapper || textureMapper->accelerationMode() == TextureMapper::SoftwareMode)
+ if (!m_layer.textureMapper())
return false;
- notifyChange(FilterChange);
- return GraphicsLayer::setFilters(filters);
+
+ bool canCompositeFilters = filtersCanBeComposited(filters);
+ if (GraphicsLayer::filters() == filters)
+ return canCompositeFilters;
+
+ if (canCompositeFilters) {
+ if (!GraphicsLayer::setFilters(filters))
+ return false;
+ notifyChange(FilterChange);
+ } else if (GraphicsLayer::filters().size()) {
+ clearFilters();
+ notifyChange(FilterChange);
+ }
+
+ return canCompositeFilters;
}
-#endif
void GraphicsLayerTextureMapper::setFixedToViewport(bool fixed)
{
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
index e3340d346..42ed713d3 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
@@ -20,7 +20,7 @@
#ifndef GraphicsLayerTextureMapper_h
#define GraphicsLayerTextureMapper_h
-#if USE(TEXTURE_MAPPER)
+#if !USE(COORDINATED_GRAPHICS)
#include "GraphicsLayer.h"
#include "GraphicsLayerClient.h"
@@ -32,70 +32,68 @@
namespace WebCore {
-class GraphicsLayerTextureMapper : public GraphicsLayer, public TextureMapperPlatformLayer::Client {
+class GraphicsLayerTextureMapper final : public GraphicsLayer, TextureMapperPlatformLayer::Client {
public:
- explicit GraphicsLayerTextureMapper(GraphicsLayerClient*);
+ explicit GraphicsLayerTextureMapper(Type, GraphicsLayerClient&);
virtual ~GraphicsLayerTextureMapper();
- void setScrollClient(TextureMapperLayer::ScrollingClient* client) { m_layer->setScrollClient(client); }
- void setID(uint32_t id) { m_layer->setID(id); }
-
- // reimps from GraphicsLayer.h
- virtual void setNeedsDisplay();
- virtual void setContentsNeedsDisplay();
- virtual void setNeedsDisplayInRect(const FloatRect&, ShouldClipToLayer = ClipToLayer);
- virtual bool setChildren(const Vector<GraphicsLayer*>&);
- virtual void addChild(GraphicsLayer*);
- virtual void addChildAtIndex(GraphicsLayer*, int index);
- virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling);
- virtual void addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling);
- virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild);
- virtual void setMaskLayer(GraphicsLayer* layer);
- virtual void setPosition(const FloatPoint& p);
- virtual void setAnchorPoint(const FloatPoint3D& p);
- virtual void setSize(const FloatSize& size);
- virtual void setTransform(const TransformationMatrix& t);
- virtual void setChildrenTransform(const TransformationMatrix& t);
- virtual void setPreserves3D(bool b);
- virtual void setMasksToBounds(bool b);
- virtual void setDrawsContent(bool b);
- virtual void setContentsVisible(bool);
- virtual void setContentsOpaque(bool b);
- virtual void setBackfaceVisibility(bool b);
- virtual void setOpacity(float opacity);
- virtual void setContentsRect(const IntRect& r);
- virtual void setReplicatedByLayer(GraphicsLayer*);
- virtual void setContentsToImage(Image*);
- virtual void setContentsToSolidColor(const Color&);
- Color solidColor() const { return m_solidColor; }
- virtual void setContentsToMedia(PlatformLayer*);
- virtual void setContentsToCanvas(PlatformLayer* canvas) { setContentsToMedia(canvas); }
- virtual void setShowDebugBorder(bool) override;
- virtual void setDebugBorder(const Color&, float width) override;
- virtual void setShowRepaintCounter(bool) override;
- virtual void flushCompositingState(const FloatRect&);
- virtual void flushCompositingStateForThisLayerOnly();
- virtual void setName(const String& name);
- virtual bool hasContentsLayer() const { return m_contentsLayer; }
- virtual PlatformLayer* platformLayer() const { return m_contentsLayer; }
-
- inline int changeMask() const { return m_changeMask; }
-
- virtual bool addAnimation(const KeyframeValueList&, const IntSize&, const Animation*, const String&, double);
- virtual void pauseAnimation(const String&, double);
- virtual void removeAnimation(const String&);
- void setAnimations(const GraphicsLayerAnimations&);
-
- TextureMapperLayer* layer() const { return m_layer.get(); }
+ void setScrollClient(TextureMapperLayer::ScrollingClient* client) { m_layer.setScrollClient(client); }
+ void setID(uint32_t id) { m_layer.setID(id); }
+
+ // GraphicsLayer
+ bool setChildren(const Vector<GraphicsLayer*>&) override;
+ void addChild(GraphicsLayer*) override;
+ void addChildAtIndex(GraphicsLayer*, int index) override;
+ void addChildAbove(GraphicsLayer*, GraphicsLayer* sibling) override;
+ void addChildBelow(GraphicsLayer*, GraphicsLayer* sibling) override;
+ bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) override;
+
+ void setMaskLayer(GraphicsLayer*) override;
+ void setReplicatedByLayer(GraphicsLayer*) override;
+ void setPosition(const FloatPoint&) override;
+ void setAnchorPoint(const FloatPoint3D&) override;
+ void setSize(const FloatSize&) override;
+ void setTransform(const TransformationMatrix&) override;
+ void setChildrenTransform(const TransformationMatrix&) override;
+ void setPreserves3D(bool) override;
+ void setMasksToBounds(bool) override;
+ void setDrawsContent(bool) override;
+ void setContentsVisible(bool) override;
+ void setContentsOpaque(bool) override;
+ void setBackfaceVisibility(bool) override;
+ void setOpacity(float) override;
+ bool setFilters(const FilterOperations&) override;
+
+ void setNeedsDisplay() override;
+ void setNeedsDisplayInRect(const FloatRect&, ShouldClipToLayer = ClipToLayer) override;
+ void setContentsNeedsDisplay() override;
+ void setContentsRect(const FloatRect&) override;
+
+ bool addAnimation(const KeyframeValueList&, const FloatSize&, const Animation*, const String&, double) override;
+ void pauseAnimation(const String&, double) override;
+ void removeAnimation(const String&) override;
+
+ void setContentsToImage(Image*) override;
+ void setContentsToSolidColor(const Color&) override;
+ void setContentsToPlatformLayer(PlatformLayer*, ContentsLayerPurpose) override;
+ bool usesContentsLayer() const override { return m_contentsLayer; }
+ PlatformLayer* platformLayer() const override { return m_contentsLayer; }
+
+ void setShowDebugBorder(bool) override;
+ void setDebugBorder(const Color&, float width) override;
+ void setShowRepaintCounter(bool) override;
+
+ void flushCompositingState(const FloatRect&) override;
+ void flushCompositingStateForThisLayerOnly() override;
+
+ void updateBackingStoreIncludingSubLayers();
+
+ TextureMapperLayer& layer() { return m_layer; }
void didCommitScrollOffset(const IntSize&);
void setIsScrollable(bool);
bool isScrollable() const { return m_isScrollable; }
-#if ENABLE(CSS_FILTERS)
- virtual bool setFilters(const FilterOperations&);
-#endif
-
void setFixedToViewport(bool);
bool fixedToViewport() const { return m_fixedToViewport; }
@@ -103,8 +101,15 @@ public:
float debugBorderWidth() const { return m_debugBorderWidth; }
void setRepaintCount(int);
+ void setAnimations(const TextureMapperAnimations&);
+
private:
- virtual void willBeDestroyed();
+ // GraphicsLayer
+ bool isGraphicsLayerTextureMapper() const override { return true; }
+
+ // TextureMapperPlatformLayer::Client
+ void platformLayerWillBeDestroyed() override { setContentsToPlatformLayer(0, NoContentsLayer); }
+ void setPlatformLayerNeedsDisplay() override { setContentsNeedsDisplay(); }
void commitLayerChanges();
void updateDebugBorderAndRepaintCount();
@@ -112,8 +117,7 @@ private:
void prepareBackingStoreIfNeeded();
bool shouldHaveBackingStore() const;
- virtual void platformLayerWillBeDestroyed() override { setContentsToMedia(0); }
- virtual void setPlatformLayerNeedsDisplay() override { setContentsNeedsDisplay(); }
+ bool filtersCanBeComposited(const FilterOperations&) const;
// 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.
@@ -160,7 +164,7 @@ private:
};
void notifyChange(ChangeMask);
- OwnPtr<TextureMapperLayer> m_layer;
+ TextureMapperLayer m_layer;
RefPtr<TextureMapperTiledBackingStore> m_compositedImage;
NativeImagePtr m_compositedNativeImagePtr;
RefPtr<TextureMapperBackingStore> m_backingStore;
@@ -175,21 +179,17 @@ private:
TextureMapperPlatformLayer* m_contentsLayer;
FloatRect m_needsDisplayRect;
- GraphicsLayerAnimations m_animations;
+ TextureMapperAnimations m_animations;
double m_animationStartTime;
IntSize m_committedScrollOffset;
bool m_isScrollable;
};
-inline static GraphicsLayerTextureMapper* toGraphicsLayerTextureMapper(GraphicsLayer* layer)
-{
- return static_cast<GraphicsLayerTextureMapper*>(layer);
-}
+} // namespace WebCore
-TextureMapperLayer* toTextureMapperLayer(GraphicsLayer*);
+SPECIALIZE_TYPE_TRAITS_GRAPHICSLAYER(WebCore::GraphicsLayerTextureMapper, isGraphicsLayerTextureMapper())
-}
#endif
#endif // GraphicsLayerTextureMapper_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
index b863e79e5..973047f49 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
@@ -20,151 +20,28 @@
#include "config.h"
#include "TextureMapper.h"
+#include "BitmapTexturePool.h"
#include "FilterOperations.h"
#include "GraphicsLayer.h"
-#include "TextureMapperImageBuffer.h"
#include "Timer.h"
#include <wtf/CurrentTime.h>
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-
namespace WebCore {
-struct BitmapTexturePoolEntry {
- explicit BitmapTexturePoolEntry(PassRefPtr<BitmapTexture> texture)
- : m_texture(texture)
- { }
- inline void markUsed() { m_timeLastUsed = monotonicallyIncreasingTime(); }
- static bool compareTimeLastUsed(const BitmapTexturePoolEntry& a, const BitmapTexturePoolEntry& b)
- {
- return a.m_timeLastUsed - b.m_timeLastUsed > 0;
- }
-
- RefPtr<BitmapTexture> m_texture;
- double m_timeLastUsed;
-};
-
-class BitmapTexturePool {
- WTF_MAKE_NONCOPYABLE(BitmapTexturePool);
- WTF_MAKE_FAST_ALLOCATED;
-public:
- BitmapTexturePool();
-
- PassRefPtr<BitmapTexture> acquireTexture(const IntSize&, TextureMapper*);
-
-private:
- void scheduleReleaseUnusedTextures();
- void releaseUnusedTexturesTimerFired(Timer<BitmapTexturePool>*);
-
- Vector<BitmapTexturePoolEntry> m_textures;
- Timer<BitmapTexturePool> m_releaseUnusedTexturesTimer;
-
- static const double s_releaseUnusedSecondsTolerance;
- static const double s_releaseUnusedTexturesTimerInterval;
-};
-
-const double BitmapTexturePool::s_releaseUnusedSecondsTolerance = 3;
-const double BitmapTexturePool::s_releaseUnusedTexturesTimerInterval = 0.5;
-
-BitmapTexturePool::BitmapTexturePool()
- : m_releaseUnusedTexturesTimer(this, &BitmapTexturePool::releaseUnusedTexturesTimerFired)
-{ }
+TextureMapper::TextureMapper() = default;
-void BitmapTexturePool::scheduleReleaseUnusedTextures()
-{
- if (m_releaseUnusedTexturesTimer.isActive())
- m_releaseUnusedTexturesTimer.stop();
-
- m_releaseUnusedTexturesTimer.startOneShot(s_releaseUnusedTexturesTimerInterval);
-}
-
-void BitmapTexturePool::releaseUnusedTexturesTimerFired(Timer<BitmapTexturePool>*)
-{
- if (m_textures.isEmpty())
- return;
-
- // Delete entries, which have been unused in s_releaseUnusedSecondsTolerance.
- std::sort(m_textures.begin(), m_textures.end(), BitmapTexturePoolEntry::compareTimeLastUsed);
-
- double minUsedTime = monotonicallyIncreasingTime() - s_releaseUnusedSecondsTolerance;
- for (size_t i = 0; i < m_textures.size(); ++i) {
- if (m_textures[i].m_timeLastUsed < minUsedTime) {
- m_textures.remove(i, m_textures.size() - i);
- break;
- }
- }
-}
-
-PassRefPtr<BitmapTexture> BitmapTexturePool::acquireTexture(const IntSize& size, TextureMapper* textureMapper)
-{
- BitmapTexturePoolEntry* selectedEntry = 0;
- for (size_t i = 0; i < m_textures.size(); ++i) {
- BitmapTexturePoolEntry* entry = &m_textures[i];
-
- // If the surface has only one reference (the one in m_textures), we can safely reuse it.
- if (entry->m_texture->refCount() > 1)
- continue;
-
- if (entry->m_texture->canReuseWith(size)) {
- selectedEntry = entry;
- break;
- }
- }
-
- if (!selectedEntry) {
- m_textures.append(BitmapTexturePoolEntry(textureMapper->createTexture()));
- selectedEntry = &m_textures.last();
- }
-
- scheduleReleaseUnusedTextures();
- selectedEntry->markUsed();
- return selectedEntry->m_texture;
-}
+TextureMapper::~TextureMapper() = default;
PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& size, const BitmapTexture::Flags flags)
{
- RefPtr<BitmapTexture> selectedTexture = m_texturePool->acquireTexture(size, this);
+ RefPtr<BitmapTexture> selectedTexture = m_texturePool->acquireTexture(size, flags);
selectedTexture->reset(size, flags);
- return selectedTexture;
+ return selectedTexture.release();
}
-PassOwnPtr<TextureMapper> TextureMapper::create(AccelerationMode mode)
+std::unique_ptr<TextureMapper> TextureMapper::create()
{
- if (mode == SoftwareMode)
- return TextureMapperImageBuffer::create();
return platformCreateAccelerated();
}
-TextureMapper::TextureMapper(AccelerationMode accelerationMode)
- : m_context(0)
- , m_interpolationQuality(InterpolationDefault)
- , m_textDrawingMode(TextModeFill)
- , m_texturePool(adoptPtr(new BitmapTexturePool()))
- , m_accelerationMode(accelerationMode)
- , m_isMaskMode(false)
- , m_wrapMode(StretchWrap)
-{ }
-
-TextureMapper::~TextureMapper()
-{ }
-
-void BitmapTexture::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag)
-{
- std::unique_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(targetRect.size());
- GraphicsContext* context = imageBuffer->context();
- context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
- context->setTextDrawingMode(textureMapper->textDrawingMode());
-
- IntRect sourceRect(targetRect);
- sourceRect.setLocation(offset);
- context->translate(-offset.x(), -offset.y());
- sourceLayer->paintGraphicsLayerContents(*context, sourceRect);
-
- RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
-
- updateContents(image.get(), targetRect, IntPoint(), updateContentsFlag);
-}
-
} // namespace
-
-#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
index 681b24ea1..7233d0dcc 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
@@ -20,13 +20,8 @@
#ifndef TextureMapper_h
#define TextureMapper_h
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-
-#if (PLATFORM(GTK) || PLATFORM(EFL)) && USE(OPENGL_ES_2)
-#define TEXMAP_OPENGL_ES_2
-#endif
-
-#include "GraphicsContext.h"
+#include "BitmapTexture.h"
+#include "Color.h"
#include "IntRect.h"
#include "IntSize.h"
#include "TransformationMatrix.h"
@@ -43,68 +38,9 @@ class GraphicsLayer;
class TextureMapper;
class FilterOperations;
-// A 2D texture that can be the target of software or GL rendering.
-class BitmapTexture : public RefCounted<BitmapTexture> {
-public:
- enum Flag {
- NoFlag = 0,
- SupportsAlpha = 0x01
- };
-
- enum UpdateContentsFlag {
- UpdateCanModifyOriginalImageData,
- UpdateCannotModifyOriginalImageData
- };
-
- typedef unsigned Flags;
-
- BitmapTexture()
- : m_flags(0)
- {
- }
-
- virtual ~BitmapTexture() { }
- virtual bool isBackedByOpenGL() const { return false; }
-
- virtual IntSize size() const = 0;
- virtual void updateContents(Image*, const IntRect&, const IntPoint& offset, UpdateContentsFlag) = 0;
- virtual void updateContents(TextureMapper*, GraphicsLayer*, const IntRect& target, const IntPoint& offset, UpdateContentsFlag);
- virtual void updateContents(const void*, const IntRect& target, const IntPoint& offset, int bytesPerLine, UpdateContentsFlag) = 0;
- virtual bool isValid() const = 0;
- inline Flags flags() const { return m_flags; }
-
- virtual int bpp() const { return 32; }
- virtual bool canReuseWith(const IntSize& /* contentsSize */, Flags = 0) { return false; }
- void reset(const IntSize& size, Flags flags = 0)
- {
- m_flags = flags;
- m_contentSize = size;
- didReset();
- }
- virtual void didReset() { }
-
- inline IntSize contentSize() const { return m_contentSize; }
- inline int numberOfBytes() const { return size().width() * size().height() * bpp() >> 3; }
- inline bool isOpaque() const { return !(m_flags & SupportsAlpha); }
-
-#if ENABLE(CSS_FILTERS)
- virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const FilterOperations&) { return this; }
-#endif
-
-protected:
- IntSize m_contentSize;
-
-private:
- Flags m_flags;
-};
-
-// 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 {
WTF_MAKE_FAST_ALLOCATED;
- friend class BitmapTexture;
public:
- enum AccelerationMode { SoftwareMode, OpenGLMode };
enum PaintFlag {
PaintingMirrored = 1 << 0,
};
@@ -116,7 +52,9 @@ public:
typedef unsigned PaintFlags;
- static PassOwnPtr<TextureMapper> create(AccelerationMode newMode = SoftwareMode);
+ static std::unique_ptr<TextureMapper> create();
+
+ explicit TextureMapper();
virtual ~TextureMapper();
enum ExposedEdges {
@@ -136,20 +74,11 @@ public:
// makes a surface the target for the following drawTexture calls.
virtual void bindSurface(BitmapTexture* surface) = 0;
- void setGraphicsContext(GraphicsContext* context) { m_context = context; }
- GraphicsContext* graphicsContext() { return m_context; }
virtual void beginClip(const TransformationMatrix&, const FloatRect&) = 0;
virtual void endClip() = 0;
virtual IntRect clipBounds() = 0;
virtual PassRefPtr<BitmapTexture> createTexture() = 0;
- void setImageInterpolationQuality(InterpolationQuality quality) { m_interpolationQuality = quality; }
- void setTextDrawingMode(TextDrawingModeFlags mode) { m_textDrawingMode = mode; }
-
- InterpolationQuality imageInterpolationQuality() const { return m_interpolationQuality; }
- TextDrawingModeFlags textDrawingMode() const { return m_textDrawingMode; }
- AccelerationMode accelerationMode() const { return m_accelerationMode; }
-
virtual void beginPainting(PaintFlags = 0) { }
virtual void endPainting() { }
@@ -163,9 +92,7 @@ public:
void setWrapMode(WrapMode m) { m_wrapMode = m; }
protected:
- explicit TextureMapper(AccelerationMode);
-
- GraphicsContext* m_context;
+ std::unique_ptr<BitmapTexturePool> m_texturePool;
bool isInMaskMode() const { return m_isMaskMode; }
WrapMode wrapMode() const { return m_wrapMode; }
@@ -173,24 +100,18 @@ protected:
private:
#if USE(TEXTURE_MAPPER_GL)
- static PassOwnPtr<TextureMapper> platformCreateAccelerated();
+ static std::unique_ptr<TextureMapper> platformCreateAccelerated();
#else
- static PassOwnPtr<TextureMapper> platformCreateAccelerated()
+ static std::unique_ptr<TextureMapper> platformCreateAccelerated()
{
- return PassOwnPtr<TextureMapper>();
+ return nullptr;
}
#endif
- InterpolationQuality m_interpolationQuality;
- TextDrawingModeFlags m_textDrawingMode;
- OwnPtr<BitmapTexturePool> m_texturePool;
- AccelerationMode m_accelerationMode;
- bool m_isMaskMode;
+ bool m_isMaskMode { false };
TransformationMatrix m_patternTransform;
- WrapMode m_wrapMode;
+ WrapMode m_wrapMode { StretchWrap };
};
}
#endif
-
-#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp
new file mode 100644
index 000000000..9cc1df6ad
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp
@@ -0,0 +1,393 @@
+/*
+ Copyright (C) 2012 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 "TextureMapperAnimation.h"
+
+#include "LayoutSize.h"
+#include "UnitBezier.h"
+#include <wtf/CurrentTime.h>
+
+namespace WebCore {
+
+static RefPtr<FilterOperation> blendFunc(FilterOperation* fromOp, FilterOperation& toOp, double progress, const FloatSize& size, bool blendToPassthrough = false)
+{
+ if (toOp.blendingNeedsRendererSize())
+ return toOp.blend(fromOp, progress, LayoutSize(size), blendToPassthrough);
+ return toOp.blend(fromOp, progress, blendToPassthrough);
+}
+
+static FilterOperations applyFilterAnimation(const FilterOperations& from, const FilterOperations& to, double progress, const FloatSize& boxSize)
+{
+ // First frame of an animation.
+ if (!progress)
+ return from;
+
+ // Last frame of an animation.
+ if (progress == 1)
+ return to;
+
+ if (!from.isEmpty() && !to.isEmpty() && !from.operationsMatch(to))
+ return to;
+
+ FilterOperations result;
+
+ size_t fromSize = from.operations().size();
+ size_t toSize = to.operations().size();
+ size_t size = std::max(fromSize, toSize);
+ for (size_t i = 0; i < size; i++) {
+ RefPtr<FilterOperation> fromOp = (i < fromSize) ? from.operations()[i].get() : nullptr;
+ RefPtr<FilterOperation> toOp = (i < toSize) ? to.operations()[i].get() : nullptr;
+ RefPtr<FilterOperation> blendedOp = toOp ? blendFunc(fromOp.get(), *toOp, progress, boxSize) : (fromOp ? blendFunc(nullptr, *fromOp, progress, boxSize, true) : nullptr);
+ if (blendedOp)
+ result.operations().append(blendedOp);
+ else {
+ RefPtr<FilterOperation> identityOp = PassthroughFilterOperation::create();
+ if (progress > 0.5)
+ result.operations().append(toOp ? toOp : identityOp);
+ else
+ result.operations().append(fromOp ? fromOp : identityOp);
+ }
+ }
+
+ return result;
+}
+
+static bool shouldReverseAnimationValue(Animation::AnimationDirection direction, int loopCount)
+{
+ return (direction == Animation::AnimationDirectionAlternate && loopCount & 1)
+ || (direction == Animation::AnimationDirectionAlternateReverse && !(loopCount & 1))
+ || direction == Animation::AnimationDirectionReverse;
+}
+
+static double normalizedAnimationValue(double runningTime, double duration, Animation::AnimationDirection direction, double iterationCount)
+{
+ if (!duration)
+ return 0;
+
+ const int loopCount = runningTime / duration;
+ const double lastFullLoop = duration * double(loopCount);
+ const double remainder = runningTime - lastFullLoop;
+ // Ignore remainder when we've reached the end of animation.
+ const double normalized = (loopCount == iterationCount) ? 1.0 : (remainder / duration);
+
+ return shouldReverseAnimationValue(direction, loopCount) ? 1 - normalized : normalized;
+}
+
+static double normalizedAnimationValueForFillsForwards(double iterationCount, Animation::AnimationDirection direction)
+{
+ if (direction == Animation::AnimationDirectionNormal)
+ return 1;
+ if (direction == Animation::AnimationDirectionReverse)
+ return 0;
+ return shouldReverseAnimationValue(direction, iterationCount) ? 1 : 0;
+}
+
+static float applyOpacityAnimation(float fromOpacity, float toOpacity, double progress)
+{
+ // Optimization: special case the edge values (0 and 1).
+ if (progress == 1.0)
+ return toOpacity;
+
+ if (!progress)
+ return fromOpacity;
+
+ return fromOpacity + progress * (toOpacity - fromOpacity);
+}
+
+static inline double solveEpsilon(double duration)
+{
+ return 1.0 / (200.0 * duration);
+}
+
+static inline double solveCubicBezierFunction(double p1x, double p1y, double p2x, double p2y, double t, double duration)
+{
+ return UnitBezier(p1x, p1y, p2x, p2y).solve(t, solveEpsilon(duration));
+}
+
+static inline double solveStepsFunction(int numSteps, bool stepAtStart, double t)
+{
+ if (stepAtStart)
+ return std::min(1.0, (floor(numSteps * t) + 1) / numSteps);
+ return floor(numSteps * t) / numSteps;
+}
+
+static inline float applyTimingFunction(const TimingFunction& timingFunction, float progress, double duration)
+{
+ if (timingFunction.isCubicBezierTimingFunction()) {
+ auto& ctf = static_cast<const CubicBezierTimingFunction&>(timingFunction);
+ return solveCubicBezierFunction(ctf.x1(), ctf.y1(), ctf.x2(), ctf.y2(), progress, duration);
+ }
+
+ if (timingFunction.isStepsTimingFunction()) {
+ auto& stf = static_cast<const StepsTimingFunction&>(timingFunction);
+ return solveStepsFunction(stf.numberOfSteps(), stf.stepAtStart(), double(progress));
+ }
+
+ return progress;
+}
+
+static TransformationMatrix applyTransformAnimation(const TransformOperations& from, const TransformOperations& to, double progress, const FloatSize& boxSize, bool listsMatch)
+{
+ TransformationMatrix matrix;
+
+ // First frame of an animation.
+ if (!progress) {
+ from.apply(boxSize, matrix);
+ return matrix;
+ }
+
+ // Last frame of an animation.
+ if (progress == 1) {
+ to.apply(boxSize, matrix);
+ return matrix;
+ }
+
+ // If we have incompatible operation lists, we blend the resulting matrices.
+ if (!listsMatch) {
+ TransformationMatrix fromMatrix;
+ to.apply(boxSize, matrix);
+ from.apply(boxSize, fromMatrix);
+ matrix.blend(fromMatrix, progress);
+ return matrix;
+ }
+
+ // Animation to "-webkit-transform: none".
+ if (!to.size()) {
+ TransformOperations blended(from);
+ for (auto& operation : blended.operations())
+ operation->blend(nullptr, progress, true)->apply(matrix, boxSize);
+ return matrix;
+ }
+
+ // Animation from "-webkit-transform: none".
+ if (!from.size()) {
+ TransformOperations blended(to);
+ for (auto& operation : blended.operations())
+ operation->blend(nullptr, 1 - progress, true)->apply(matrix, boxSize);
+ return matrix;
+ }
+
+ // Normal animation with a matching operation list.
+ TransformOperations blended(to);
+ for (size_t i = 0; i < blended.operations().size(); ++i)
+ blended.operations()[i]->blend(from.at(i), progress, !from.at(i))->apply(matrix, boxSize);
+ return matrix;
+}
+
+static const TimingFunction& timingFunctionForAnimationValue(const AnimationValue& animationValue, const Animation& animation)
+{
+ if (animationValue.timingFunction())
+ return *animationValue.timingFunction();
+ if (animation.timingFunction())
+ return *animation.timingFunction();
+ return CubicBezierTimingFunction::defaultTimingFunction();
+}
+
+TextureMapperAnimation::TextureMapperAnimation(const String& name, const KeyframeValueList& keyframes, const FloatSize& boxSize, const Animation& animation, bool listsMatch, double startTime, double pauseTime, AnimationState state)
+ : m_name(name.isSafeToSendToAnotherThread() ? name : name.isolatedCopy())
+ , m_keyframes(keyframes)
+ , m_boxSize(boxSize)
+ , m_animation(Animation::create(animation))
+ , m_listsMatch(listsMatch)
+ , m_startTime(startTime)
+ , m_pauseTime(pauseTime)
+ , m_totalRunningTime(0)
+ , m_lastRefreshedTime(m_startTime)
+ , m_state(state)
+{
+}
+
+TextureMapperAnimation::TextureMapperAnimation(const TextureMapperAnimation& other)
+ : m_name(other.m_name.isSafeToSendToAnotherThread() ? other.m_name : other.m_name.isolatedCopy())
+ , m_keyframes(other.m_keyframes)
+ , m_boxSize(other.m_boxSize)
+ , m_animation(Animation::create(*other.m_animation))
+ , m_listsMatch(other.m_listsMatch)
+ , m_startTime(other.m_startTime)
+ , m_pauseTime(other.m_pauseTime)
+ , m_totalRunningTime(other.m_totalRunningTime)
+ , m_lastRefreshedTime(other.m_lastRefreshedTime)
+ , m_state(other.m_state)
+{
+}
+
+void TextureMapperAnimation::apply(Client& client)
+{
+ if (!isActive())
+ return;
+
+ double totalRunningTime = computeTotalRunningTime();
+ double normalizedValue = normalizedAnimationValue(totalRunningTime, m_animation->duration(), m_animation->direction(), m_animation->iterationCount());
+
+ if (m_animation->iterationCount() != Animation::IterationCountInfinite && totalRunningTime >= m_animation->duration() * m_animation->iterationCount()) {
+ m_state = AnimationState::Stopped;
+ m_pauseTime = 0;
+ if (m_animation->fillsForwards())
+ normalizedValue = normalizedAnimationValueForFillsForwards(m_animation->iterationCount(), m_animation->direction());
+ }
+
+ if (!normalizedValue) {
+ applyInternal(client, m_keyframes.at(0), m_keyframes.at(1), 0);
+ return;
+ }
+
+ if (normalizedValue == 1.0) {
+ applyInternal(client, m_keyframes.at(m_keyframes.size() - 2), m_keyframes.at(m_keyframes.size() - 1), 1);
+ return;
+ }
+ if (m_keyframes.size() == 2) {
+ auto& timingFunction = timingFunctionForAnimationValue(m_keyframes.at(0), *m_animation);
+ normalizedValue = applyTimingFunction(timingFunction, normalizedValue, m_animation->duration());
+ applyInternal(client, m_keyframes.at(0), m_keyframes.at(1), normalizedValue);
+ return;
+ }
+
+ for (size_t i = 0; i < m_keyframes.size() - 1; ++i) {
+ const AnimationValue& from = m_keyframes.at(i);
+ const AnimationValue& to = m_keyframes.at(i + 1);
+ if (from.keyTime() > normalizedValue || to.keyTime() < normalizedValue)
+ continue;
+
+ normalizedValue = (normalizedValue - from.keyTime()) / (to.keyTime() - from.keyTime());
+ auto& timingFunction = timingFunctionForAnimationValue(from, *m_animation);
+ normalizedValue = applyTimingFunction(timingFunction, normalizedValue, m_animation->duration());
+ applyInternal(client, from, to, normalizedValue);
+ break;
+ }
+}
+
+void TextureMapperAnimation::pause(double time)
+{
+ m_state = AnimationState::Paused;
+ m_pauseTime = time;
+}
+
+void TextureMapperAnimation::resume()
+{
+ m_state = AnimationState::Playing;
+ m_pauseTime = 0;
+ m_totalRunningTime = m_pauseTime;
+ m_lastRefreshedTime = monotonicallyIncreasingTime();
+}
+
+double TextureMapperAnimation::computeTotalRunningTime()
+{
+ if (m_state == AnimationState::Paused)
+ return m_pauseTime;
+
+ double oldLastRefreshedTime = m_lastRefreshedTime;
+ m_lastRefreshedTime = monotonicallyIncreasingTime();
+ m_totalRunningTime += m_lastRefreshedTime - oldLastRefreshedTime;
+ return m_totalRunningTime;
+}
+
+bool TextureMapperAnimation::isActive() const
+{
+ return m_state != AnimationState::Stopped || m_animation->fillsForwards();
+}
+
+void TextureMapperAnimation::applyInternal(Client& client, const AnimationValue& from, const AnimationValue& to, float progress)
+{
+ switch (m_keyframes.property()) {
+ case AnimatedPropertyOpacity:
+ client.setAnimatedOpacity(applyOpacityAnimation((static_cast<const FloatAnimationValue&>(from).value()), (static_cast<const FloatAnimationValue&>(to).value()), progress));
+ return;
+ case AnimatedPropertyTransform:
+ client.setAnimatedTransform(applyTransformAnimation(static_cast<const TransformAnimationValue&>(from).value(), static_cast<const TransformAnimationValue&>(to).value(), progress, m_boxSize, m_listsMatch));
+ return;
+ case AnimatedPropertyFilter:
+ client.setAnimatedFilters(applyFilterAnimation(static_cast<const FilterAnimationValue&>(from).value(), static_cast<const FilterAnimationValue&>(to).value(), progress, m_boxSize));
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+void TextureMapperAnimations::add(const TextureMapperAnimation& animation)
+{
+ // Remove the old state if we are resuming a paused animation.
+ remove(animation.name(), animation.keyframes().property());
+
+ m_animations.append(animation);
+}
+
+void TextureMapperAnimations::remove(const String& name)
+{
+ m_animations.removeAllMatching([&name] (const TextureMapperAnimation& animation) {
+ return animation.name() == name;
+ });
+}
+
+void TextureMapperAnimations::remove(const String& name, AnimatedPropertyID property)
+{
+ m_animations.removeAllMatching([&name, property] (const TextureMapperAnimation& animation) {
+ return animation.name() == name && animation.keyframes().property() == property;
+ });
+}
+
+void TextureMapperAnimations::pause(const String& name, double offset)
+{
+ for (auto& animation : m_animations) {
+ if (animation.name() == name)
+ animation.pause(offset);
+ }
+}
+
+void TextureMapperAnimations::suspend(double offset)
+{
+ for (auto& animation : m_animations)
+ animation.pause(offset);
+}
+
+void TextureMapperAnimations::resume()
+{
+ for (auto& animation : m_animations)
+ animation.resume();
+}
+
+void TextureMapperAnimations::apply(TextureMapperAnimation::Client& client)
+{
+ for (auto& animation : m_animations)
+ animation.apply(client);
+}
+
+bool TextureMapperAnimations::hasActiveAnimationsOfType(AnimatedPropertyID type) const
+{
+ return std::any_of(m_animations.begin(), m_animations.end(),
+ [&type](const TextureMapperAnimation& animation) { return animation.isActive() && animation.keyframes().property() == type; });
+}
+
+bool TextureMapperAnimations::hasRunningAnimations() const
+{
+ return std::any_of(m_animations.begin(), m_animations.end(),
+ [](const TextureMapperAnimation& animation) { return animation.state() == TextureMapperAnimation::AnimationState::Playing; });
+}
+
+TextureMapperAnimations TextureMapperAnimations::getActiveAnimations() const
+{
+ TextureMapperAnimations active;
+ for (auto& animation : m_animations) {
+ if (animation.isActive())
+ active.add(animation);
+ }
+ return active;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h
new file mode 100644
index 000000000..6a447d76e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.h
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 2012 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 TextureMapperAnimation_h
+#define TextureMapperAnimation_h
+
+#include "GraphicsLayer.h"
+
+namespace WebCore {
+
+class TransformationMatrix;
+
+class TextureMapperAnimation {
+public:
+ enum class AnimationState { Playing, Paused, Stopped };
+
+ class Client {
+ public:
+ virtual void setAnimatedTransform(const TransformationMatrix&) = 0;
+ virtual void setAnimatedOpacity(float) = 0;
+ virtual void setAnimatedFilters(const FilterOperations&) = 0;
+ };
+
+ TextureMapperAnimation()
+ : m_keyframes(AnimatedPropertyInvalid)
+ { }
+ TextureMapperAnimation(const String&, const KeyframeValueList&, const FloatSize&, const Animation&, bool, double, double, AnimationState);
+ TextureMapperAnimation(const TextureMapperAnimation&);
+
+ void apply(Client&);
+ void pause(double);
+ void resume();
+ bool isActive() const;
+
+ const String& name() const { return m_name; }
+ const KeyframeValueList& keyframes() const { return m_keyframes; }
+ const FloatSize& boxSize() const { return m_boxSize; }
+ const RefPtr<Animation> animation() const { return m_animation; }
+ bool listsMatch() const { return m_listsMatch; }
+ double startTime() const { return m_startTime; }
+ double pauseTime() const { return m_pauseTime; }
+ AnimationState state() const { return m_state; }
+
+private:
+ void applyInternal(Client&, const AnimationValue& from, const AnimationValue& to, float progress);
+ double computeTotalRunningTime();
+
+ String m_name;
+ KeyframeValueList m_keyframes;
+ FloatSize m_boxSize;
+ RefPtr<Animation> m_animation;
+ bool m_listsMatch;
+ double m_startTime;
+ double m_pauseTime;
+ double m_totalRunningTime;
+ double m_lastRefreshedTime;
+ AnimationState m_state;
+};
+
+class TextureMapperAnimations {
+public:
+ TextureMapperAnimations() = default;
+
+ void add(const TextureMapperAnimation&);
+ void remove(const String& name);
+ void remove(const String& name, AnimatedPropertyID);
+ void pause(const String&, double);
+ void suspend(double);
+ void resume();
+
+ void apply(TextureMapperAnimation::Client&);
+
+ bool isEmpty() const { return m_animations.isEmpty(); }
+ size_t size() const { return m_animations.size(); }
+ const Vector<TextureMapperAnimation>& animations() const { return m_animations; }
+ Vector<TextureMapperAnimation>& animations() { return m_animations; }
+
+ bool hasRunningAnimations() const;
+ bool hasActiveAnimationsOfType(AnimatedPropertyID type) const;
+ TextureMapperAnimations getActiveAnimations() const;
+
+private:
+ Vector<TextureMapperAnimation> m_animations;
+};
+
+}
+
+#endif // TextureMapperAnimation_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp
index e68bc0914..ebed19a89 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp
@@ -19,18 +19,12 @@
#include "config.h"
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
#include "TextureMapperBackingStore.h"
#include "GraphicsLayer.h"
#include "ImageBuffer.h"
#include "TextureMapper.h"
-#if USE(GRAPHICS_SURFACE)
-#include "GraphicsSurface.h"
-#include "TextureMapperGL.h"
-#endif
-
namespace WebCore {
unsigned TextureMapperBackingStore::calculateExposedTileEdges(const FloatRect& totalRect, const FloatRect& tileRect)
@@ -48,4 +42,3 @@ unsigned TextureMapperBackingStore::calculateExposedTileEdges(const FloatRect& t
}
}
-#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h
index 4bae45b4f..914604171 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h
@@ -20,27 +20,21 @@
#ifndef TextureMapperBackingStore_h
#define TextureMapperBackingStore_h
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-
#include "FloatRect.h"
#include "Image.h"
#include "TextureMapper.h"
#include "TextureMapperPlatformLayer.h"
#include <wtf/RefPtr.h>
-#if USE(GRAPHICS_SURFACE)
-#include "GraphicsSurface.h"
-#endif
-
namespace WebCore {
class GraphicsLayer;
class TextureMapperBackingStore : public TextureMapperPlatformLayer, public RefCounted<TextureMapperBackingStore> {
public:
- virtual PassRefPtr<BitmapTexture> texture() const = 0;
- virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float) = 0;
- virtual void drawRepaintCounter(TextureMapper*, int /* repaintCount */, const Color&, const FloatRect&, const TransformationMatrix&) { }
+ virtual RefPtr<BitmapTexture> texture() const = 0;
+ void paintToTextureMapper(TextureMapper&, const FloatRect&, const TransformationMatrix&, float) override = 0;
+ virtual void drawRepaintCounter(TextureMapper&, int /* repaintCount */, const Color&, const FloatRect&, const TransformationMatrix&) { }
virtual ~TextureMapperBackingStore() { }
protected:
@@ -48,6 +42,5 @@ protected:
};
}
-#endif
#endif // TextureMapperBackingStore_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.cpp
index d74477010..db6a7a0d3 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.cpp
@@ -21,8 +21,6 @@
#include "config.h"
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-
#include "TextureMapperFPSCounter.h"
#include "TextureMapper.h"
@@ -46,7 +44,7 @@ TextureMapperFPSCounter::TextureMapperFPSCounter()
}
}
-void TextureMapperFPSCounter::updateFPSAndDisplay(TextureMapper* textureMapper, const FloatPoint& location, const TransformationMatrix& matrix)
+void TextureMapperFPSCounter::updateFPSAndDisplay(TextureMapper& textureMapper, const FloatPoint& location, const TransformationMatrix& matrix)
{
if (!m_isShowingFPS)
return;
@@ -59,9 +57,7 @@ void TextureMapperFPSCounter::updateFPSAndDisplay(TextureMapper* textureMapper,
m_fpsTimestamp += delta;
}
- textureMapper->drawNumber(m_lastFPS, Color::black, location, matrix);
+ textureMapper.drawNumber(m_lastFPS, Color::black, location, matrix);
}
} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.h b/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.h
index 006237383..8aa4a9425 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.h
@@ -22,7 +22,6 @@
#ifndef TextureMapperFPSCounter_h
#define TextureMapperFPSCounter_h
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
#include "FloatPoint.h"
#include "TransformationMatrix.h"
#include <wtf/Noncopyable.h>
@@ -35,7 +34,7 @@ class TextureMapperFPSCounter {
WTF_MAKE_FAST_ALLOCATED;
public:
TextureMapperFPSCounter();
- void updateFPSAndDisplay(TextureMapper*, const FloatPoint& = FloatPoint::zero(), const TransformationMatrix& = TransformationMatrix());
+ void updateFPSAndDisplay(TextureMapper&, const FloatPoint& = FloatPoint::zero(), const TransformationMatrix& = TransformationMatrix());
private:
bool m_isShowingFPS;
@@ -47,8 +46,4 @@ private:
} // namespace WebCore
-#endif // USE(ACCELERATED_COMPOSITING)
-
#endif // TextureMapperFPSCounter_h
-
-
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGC3DPlatformLayer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperGC3DPlatformLayer.cpp
new file mode 100644
index 000000000..9a9f4fb06
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGC3DPlatformLayer.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2011, 2012, 2017 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "TextureMapperGC3DPlatformLayer.h"
+
+#if ENABLE(GRAPHICS_CONTEXT_3D) && USE(TEXTURE_MAPPER)
+
+#if USE(OPENGL_ES_2)
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#endif
+
+#include "BitmapTextureGL.h"
+#include "GLContext.h"
+#include "TextureMapperPlatformLayerBuffer.h"
+
+namespace WebCore {
+
+TextureMapperGC3DPlatformLayer::TextureMapperGC3DPlatformLayer(GraphicsContext3D& context, GraphicsContext3D::RenderStyle renderStyle)
+ : m_context(context)
+ , m_renderStyle(renderStyle)
+{
+ switch (renderStyle) {
+ case GraphicsContext3D::RenderOffscreen:
+ m_glContext = GLContext::createOffscreenContext(&PlatformDisplay::sharedDisplayForCompositing());
+ break;
+ case GraphicsContext3D::RenderToCurrentGLContext:
+ break;
+ case GraphicsContext3D::RenderDirectlyToHostWindow:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ if (m_renderStyle == GraphicsContext3D::RenderOffscreen)
+ m_platformLayerProxy = adoptRef(new TextureMapperPlatformLayerProxy());
+#endif
+}
+
+TextureMapperGC3DPlatformLayer::~TextureMapperGC3DPlatformLayer()
+{
+#if !USE(COORDINATED_GRAPHICS_THREADED)
+ if (client())
+ client()->platformLayerWillBeDestroyed();
+#endif
+}
+
+bool TextureMapperGC3DPlatformLayer::makeContextCurrent()
+{
+ return m_glContext ? m_glContext->makeContextCurrent() : false;
+}
+
+PlatformGraphicsContext3D TextureMapperGC3DPlatformLayer::platformContext()
+{
+ return m_glContext ? m_glContext->platformContext() : GLContext::current()->platformContext();
+}
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+RefPtr<TextureMapperPlatformLayerProxy> TextureMapperGC3DPlatformLayer::proxy() const
+{
+ return m_platformLayerProxy.copyRef();
+}
+
+void TextureMapperGC3DPlatformLayer::swapBuffersIfNeeded()
+{
+ ASSERT(m_renderStyle == GraphicsContext3D::RenderOffscreen);
+ if (m_context.layerComposited())
+ return;
+
+ m_context.prepareTexture();
+ IntSize textureSize(m_context.m_currentWidth, m_context.m_currentHeight);
+ TextureMapperGL::Flags flags = TextureMapperGL::ShouldFlipTexture | (m_context.m_attrs.alpha ? TextureMapperGL::ShouldBlend : 0);
+
+ {
+ LockHolder holder(m_platformLayerProxy->lock());
+ m_platformLayerProxy->pushNextBuffer(std::make_unique<TextureMapperPlatformLayerBuffer>(m_context.m_compositorTexture, textureSize, flags));
+ }
+
+ m_context.markLayerComposited();
+}
+#else
+void TextureMapperGC3DPlatformLayer::paintToTextureMapper(TextureMapper& textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity)
+{
+ if (!m_glContext)
+ return;
+
+ ASSERT(m_renderStyle == GraphicsContext3D::RenderOffscreen);
+
+ m_context.markLayerComposited();
+
+#if USE(TEXTURE_MAPPER_GL)
+ if (m_context.m_attrs.antialias && m_context.m_state.boundFBO == m_context.m_multisampleFBO) {
+ GLContext* previousActiveContext = GLContext::current();
+ if (previousActiveContext != m_glContext.get())
+ m_context.makeContextCurrent();
+
+ m_context.resolveMultisamplingIfNecessary();
+ ::glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_context.m_state.boundFBO);
+
+ if (previousActiveContext && previousActiveContext != m_glContext.get())
+ previousActiveContext->makeContextCurrent();
+ }
+
+ TextureMapperGL& texmapGL = static_cast<TextureMapperGL&>(textureMapper);
+ TextureMapperGL::Flags flags = TextureMapperGL::ShouldFlipTexture | (m_context.m_attrs.alpha ? TextureMapperGL::ShouldBlend : 0);
+ IntSize textureSize(m_context.m_currentWidth, m_context.m_currentHeight);
+ texmapGL.drawTexture(m_context.m_texture, flags, textureSize, targetRect, matrix, opacity);
+#endif // USE(TEXTURE_MAPPER_GL)
+}
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
+
+} // namespace WebCore
+
+#endif // ENABLE(GRAPHICS_CONTEXT_3D) && USE(TEXTURE_MAPPER)
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGC3DPlatformLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperGC3DPlatformLayer.h
new file mode 100644
index 000000000..dd3f74fce
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGC3DPlatformLayer.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011, 2012, 2017 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#if ENABLE(GRAPHICS_CONTEXT_3D) && USE(TEXTURE_MAPPER)
+
+#include "GraphicsContext3D.h"
+#include "PlatformLayer.h"
+#include "TextureMapperPlatformLayer.h"
+#include "TextureMapperPlatformLayerProxy.h"
+
+namespace WebCore {
+
+class BitmapTextureGL;
+class GLContext;
+class TextureMapperPlatformLayerProxy;
+
+class TextureMapperGC3DPlatformLayer : public PlatformLayer {
+public:
+ TextureMapperGC3DPlatformLayer(GraphicsContext3D&, GraphicsContext3D::RenderStyle);
+ virtual ~TextureMapperGC3DPlatformLayer();
+
+ bool makeContextCurrent();
+ PlatformGraphicsContext3D platformContext();
+ GraphicsContext3D::RenderStyle renderStyle() { return m_renderStyle; }
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ RefPtr<TextureMapperPlatformLayerProxy> proxy() const override;
+ void swapBuffersIfNeeded() override;
+#else
+ virtual void paintToTextureMapper(TextureMapper&, const FloatRect& target, const TransformationMatrix&, float opacity);
+#endif
+
+private:
+ GraphicsContext3D& m_context;
+ std::unique_ptr<GLContext> m_glContext;
+ GraphicsContext3D::RenderStyle m_renderStyle;
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ RefPtr<TextureMapperPlatformLayerProxy> m_platformLayerProxy;
+ RefPtr<BitmapTextureGL> m_compositorTexture;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(GRAPHICS_CONTEXT_3D) && USE(TEXTURE_MAPPER)
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
index 05b884bd5..7464d047e 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
@@ -22,6 +22,10 @@
#include "config.h"
#include "TextureMapperGL.h"
+#if USE(TEXTURE_MAPPER_GL)
+
+#include "BitmapTextureGL.h"
+#include "BitmapTexturePool.h"
#include "Extensions3D.h"
#include "FilterOperations.h"
#include "GraphicsContext.h"
@@ -31,9 +35,10 @@
#include "TextureMapperShaderProgram.h"
#include "Timer.h"
#include <wtf/HashMap.h>
+#include <wtf/NeverDestroyed.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
-#include <wtf/TemporaryChange.h>
+#include <wtf/SetForScope.h>
#if USE(CAIRO)
#include "CairoUtilities.h"
@@ -42,191 +47,84 @@
#include <wtf/text/CString.h>
#endif
-#if !USE(TEXMAP_OPENGL_ES_2)
-// FIXME: Move to Extensions3D.h.
-#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
-#define GL_UNPACK_ROW_LENGTH 0x0CF2
-#define GL_UNPACK_SKIP_PIXELS 0x0CF4
-#define GL_UNPACK_SKIP_ROWS 0x0CF3
-#endif
-
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-
namespace WebCore {
-struct TextureMapperGLData {
+
+class TextureMapperGLData {
WTF_MAKE_FAST_ALLOCATED;
public:
- struct SharedGLData : public RefCounted<SharedGLData> {
+ explicit TextureMapperGLData(GraphicsContext3D&);
+ ~TextureMapperGLData();
- typedef HashMap<PlatformGraphicsContext3D, SharedGLData*> GLContextDataMap;
- static GLContextDataMap& glContextDataMap()
- {
- static GLContextDataMap map;
- return map;
- }
+ void initializeStencil();
+ Platform3DObject getStaticVBO(GC3Denum target, GC3Dsizeiptr, const void* data);
+ Ref<TextureMapperShaderProgram> getShaderProgram(TextureMapperShaderProgram::Options);
+
+ TransformationMatrix projectionMatrix;
+ TextureMapper::PaintFlags PaintFlags { 0 };
+ GC3Dint previousProgram { 0 };
+ GC3Dint targetFrameBuffer { 0 };
+ bool didModifyStencil { false };
+ GC3Dint previousScissorState { 0 };
+ GC3Dint previousDepthState { 0 };
+ GC3Dint viewport[4] { 0, };
+ GC3Dint previousScissor[4] { 0, };
+ RefPtr<BitmapTexture> currentSurface;
+ const BitmapTextureGL::FilterInfo* filterInfo { nullptr };
- static PassRefPtr<SharedGLData> currentSharedGLData(GraphicsContext3D* context)
+private:
+ class SharedGLData : public RefCounted<SharedGLData> {
+ public:
+ static Ref<SharedGLData> currentSharedGLData(GraphicsContext3D& context)
{
- GLContextDataMap::iterator it = glContextDataMap().find(context->platformGraphicsContext3D());
- if (it != glContextDataMap().end())
- return it->value;
+ auto it = contextDataMap().find(context.platformGraphicsContext3D());
+ if (it != contextDataMap().end())
+ return *it->value;
- return adoptRef(new SharedGLData(context));
+ Ref<SharedGLData> data = adoptRef(*new SharedGLData(context));
+ contextDataMap().add(context.platformGraphicsContext3D(), data.ptr());
+ return data;
}
- PassRefPtr<TextureMapperShaderProgram> getShaderProgram(TextureMapperShaderProgram::Options options)
+ ~SharedGLData()
{
- HashMap<TextureMapperShaderProgram::Options, RefPtr<TextureMapperShaderProgram> >::AddResult result = m_programs.add(options, nullptr);
- if (result.isNewEntry)
- result.iterator->value = TextureMapperShaderProgram::create(m_context, options);
-
- return result.iterator->value;
+ ASSERT(std::any_of(contextDataMap().begin(), contextDataMap().end(),
+ [this](auto& entry) { return entry.value == this; }));
+ contextDataMap().removeIf([this](auto& entry) { return entry.value == this; });
}
- HashMap<TextureMapperShaderProgram::Options, RefPtr<TextureMapperShaderProgram> > m_programs;
- RefPtr<GraphicsContext3D> m_context;
+ private:
+ friend class TextureMapperGLData;
- explicit SharedGLData(GraphicsContext3D* context)
- : m_context(context)
+ using GLContextDataMap = HashMap<PlatformGraphicsContext3D, SharedGLData*>;
+ static GLContextDataMap& contextDataMap()
{
- glContextDataMap().add(context->platformGraphicsContext3D(), this);
+ static NeverDestroyed<GLContextDataMap> map;
+ return map;
}
- ~SharedGLData()
+ explicit SharedGLData(GraphicsContext3D& context)
{
- GLContextDataMap::const_iterator end = glContextDataMap().end();
- GLContextDataMap::iterator it;
- for (it = glContextDataMap().begin(); it != end; ++it) {
- if (it->value == this)
- break;
- }
-
- ASSERT(it != end);
- glContextDataMap().remove(it);
+ contextDataMap().add(context.platformGraphicsContext3D(), this);
}
- };
-
- SharedGLData& sharedGLData() const
- {
- return *sharedData;
- }
- void initializeStencil();
-
- explicit TextureMapperGLData(GraphicsContext3D* context)
- : context(context)
- , PaintFlags(0)
- , previousProgram(0)
- , targetFrameBuffer(0)
- , didModifyStencil(false)
- , previousScissorState(0)
- , previousDepthState(0)
- , sharedData(TextureMapperGLData::SharedGLData::currentSharedGLData(this->context))
-#if ENABLE(CSS_FILTERS)
- , filterInfo(0)
-#endif
- { }
-
- ~TextureMapperGLData();
- Platform3DObject getStaticVBO(GC3Denum target, GC3Dsizeiptr, const void* data);
+ HashMap<TextureMapperShaderProgram::Options, RefPtr<TextureMapperShaderProgram>> m_programs;
+ };
- GraphicsContext3D* context;
- TransformationMatrix projectionMatrix;
- TextureMapper::PaintFlags PaintFlags;
- GC3Dint previousProgram;
- GC3Dint targetFrameBuffer;
- bool didModifyStencil;
- GC3Dint previousScissorState;
- GC3Dint previousDepthState;
- GC3Dint viewport[4];
- GC3Dint previousScissor[4];
- RefPtr<SharedGLData> sharedData;
- RefPtr<BitmapTexture> currentSurface;
- HashMap<const void*, Platform3DObject> vbos;
-#if ENABLE(CSS_FILTERS)
- const BitmapTextureGL::FilterInfo* filterInfo;
-#endif
+ GraphicsContext3D& m_context;
+ Ref<SharedGLData> m_sharedGLData;
+ HashMap<const void*, Platform3DObject> m_vbos;
};
-Platform3DObject TextureMapperGLData::getStaticVBO(GC3Denum target, GC3Dsizeiptr size, const void* data)
+TextureMapperGLData::TextureMapperGLData(GraphicsContext3D& context)
+ : m_context(context)
+ , m_sharedGLData(SharedGLData::currentSharedGLData(m_context))
{
- HashMap<const void*, Platform3DObject>::AddResult result = vbos.add(data, 0);
- if (result.isNewEntry) {
- Platform3DObject vbo = context->createBuffer();
- context->bindBuffer(target, vbo);
- context->bufferData(target, size, data, GraphicsContext3D::STATIC_DRAW);
- result.iterator->value = vbo;
- }
-
- return result.iterator->value;
}
TextureMapperGLData::~TextureMapperGLData()
{
- HashMap<const void*, Platform3DObject>::iterator end = vbos.end();
- for (HashMap<const void*, Platform3DObject>::iterator it = vbos.begin(); it != end; ++it)
- context->deleteBuffer(it->value);
-}
-
-void TextureMapperGL::ClipStack::reset(const IntRect& rect, TextureMapperGL::ClipStack::YAxisMode mode)
-{
- clipStack.clear();
- size = rect.size();
- yAxisMode = mode;
- clipState = TextureMapperGL::ClipState(rect);
- clipStateDirty = true;
-}
-
-void TextureMapperGL::ClipStack::intersect(const IntRect& rect)
-{
- clipState.scissorBox.intersect(rect);
- clipStateDirty = true;
-}
-
-void TextureMapperGL::ClipStack::setStencilIndex(int stencilIndex)
-{
- clipState.stencilIndex = stencilIndex;
- clipStateDirty = true;
-}
-
-void TextureMapperGL::ClipStack::push()
-{
- clipStack.append(clipState);
- clipStateDirty = true;
-}
-
-void TextureMapperGL::ClipStack::pop()
-{
- if (clipStack.isEmpty())
- return;
- clipState = clipStack.last();
- clipStack.removeLast();
- clipStateDirty = true;
-}
-
-void TextureMapperGL::ClipStack::apply(GraphicsContext3D* context)
-{
- if (clipState.scissorBox.isEmpty())
- return;
-
- context->scissor(clipState.scissorBox.x(),
- (yAxisMode == InvertedYAxis) ? size.height() - clipState.scissorBox.maxY() : clipState.scissorBox.y(),
- clipState.scissorBox.width(), clipState.scissorBox.height());
- context->stencilOp(GraphicsContext3D::KEEP, GraphicsContext3D::KEEP, GraphicsContext3D::KEEP);
- context->stencilFunc(GraphicsContext3D::EQUAL, clipState.stencilIndex - 1, clipState.stencilIndex - 1);
- if (clipState.stencilIndex == 1)
- context->disable(GraphicsContext3D::STENCIL_TEST);
- else
- context->enable(GraphicsContext3D::STENCIL_TEST);
-}
-
-void TextureMapperGL::ClipStack::applyIfNeeded(GraphicsContext3D* context)
-{
- if (!clipStateDirty)
- return;
-
- clipStateDirty = false;
- apply(context);
+ for (auto& entry : m_vbos)
+ m_context.deleteBuffer(entry.value);
}
void TextureMapperGLData::initializeStencil()
@@ -239,30 +137,45 @@ void TextureMapperGLData::initializeStencil()
if (didModifyStencil)
return;
- context->clearStencil(0);
- context->clear(GraphicsContext3D::STENCIL_BUFFER_BIT);
+ m_context.clearStencil(0);
+ m_context.clear(GraphicsContext3D::STENCIL_BUFFER_BIT);
didModifyStencil = true;
}
-BitmapTextureGL* toBitmapTextureGL(BitmapTexture* texture)
+Platform3DObject TextureMapperGLData::getStaticVBO(GC3Denum target, GC3Dsizeiptr size, const void* data)
{
- if (!texture || !texture->isBackedByOpenGL())
- return 0;
+ auto addResult = m_vbos.ensure(data,
+ [this, target, size, data] {
+ Platform3DObject vbo = m_context.createBuffer();
+ m_context.bindBuffer(target, vbo);
+ m_context.bufferData(target, size, data, GraphicsContext3D::STATIC_DRAW);
+ return vbo;
+ });
+ return addResult.iterator->value;
+}
- return static_cast<BitmapTextureGL*>(texture);
+Ref<TextureMapperShaderProgram> TextureMapperGLData::getShaderProgram(TextureMapperShaderProgram::Options options)
+{
+ auto addResult = m_sharedGLData->m_programs.ensure(options,
+ [this, options] { return TextureMapperShaderProgram::create(Ref<GraphicsContext3D>(m_context), options); });
+ return *addResult.iterator->value;
}
TextureMapperGL::TextureMapperGL()
- : TextureMapper(OpenGLMode)
- , m_enableEdgeDistanceAntialiasing(false)
+ : m_enableEdgeDistanceAntialiasing(false)
{
m_context3D = GraphicsContext3D::createForCurrentGLContext();
- m_data = new TextureMapperGLData(m_context3D.get());
+ ASSERT(m_context3D);
+
+ m_data = new TextureMapperGLData(*m_context3D);
+#if USE(TEXTURE_MAPPER_GL)
+ m_texturePool = std::make_unique<BitmapTexturePool>(m_context3D.copyRef());
+#endif
}
-TextureMapperGL::ClipStack& TextureMapperGL::clipStack()
+ClipStack& TextureMapperGL::clipStack()
{
- return data().currentSurface ? toBitmapTextureGL(data().currentSurface.get())->m_clipStack : m_clipStack;
+ return data().currentSurface ? toBitmapTextureGL(data().currentSurface.get())->clipStack() : m_clipStack;
}
void TextureMapperGL::beginPainting(PaintFlags flags)
@@ -276,7 +189,7 @@ void TextureMapperGL::beginPainting(PaintFlags flags)
m_context3D->depthMask(0);
m_context3D->getIntegerv(GraphicsContext3D::VIEWPORT, data().viewport);
m_context3D->getIntegerv(GraphicsContext3D::SCISSOR_BOX, data().previousScissor);
- m_clipStack.reset(IntRect(0, 0, data().viewport[2], data().viewport[3]), ClipStack::InvertedYAxis);
+ m_clipStack.reset(IntRect(0, 0, data().viewport[2], data().viewport[3]), flags & PaintingMirrored ? ClipStack::YAxisMode::Default : ClipStack::YAxisMode::Inverted);
m_context3D->getIntegerv(GraphicsContext3D::FRAMEBUFFER_BINDING, &data().targetFrameBuffer);
data().PaintFlags = flags;
bindSurface(0);
@@ -308,7 +221,7 @@ void TextureMapperGL::drawBorder(const Color& color, float width, const FloatRec
if (clipStack().isCurrentScissorBoxEmpty())
return;
- RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().getShaderProgram(TextureMapperShaderProgram::SolidColor);
+ Ref<TextureMapperShaderProgram> program = data().getShaderProgram(TextureMapperShaderProgram::SolidColor);
m_context3D->useProgram(program->programID());
float r, g, b, a;
@@ -316,7 +229,7 @@ void TextureMapperGL::drawBorder(const Color& color, float width, const FloatRec
m_context3D->uniform4f(program->colorLocation(), r, g, b, a);
m_context3D->lineWidth(width);
- draw(targetRect, modelViewMatrix, program.get(), GraphicsContext3D::LINE_LOOP, color.hasAlpha() ? ShouldBlend : 0);
+ draw(targetRect, modelViewMatrix, program.get(), GraphicsContext3D::LINE_LOOP, !color.isOpaque() ? ShouldBlend : 0);
}
// FIXME: drawNumber() should save a number texture-atlas and re-use whenever possible.
@@ -333,9 +246,15 @@ void TextureMapperGL::drawNumber(int number, const Color& color, const FloatPoin
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
cairo_t* cr = cairo_create(surface);
- float r, g, b, a;
- color.getRGBA(r, g, b, a);
- cairo_set_source_rgba(cr, b, g, r, a); // Since we won't swap R+B when uploading a texture, paint with the swapped R+B color.
+ // Since we won't swap R+B when uploading a texture, paint with the swapped R+B color.
+ if (color.isExtended())
+ cairo_set_source_rgba(cr, color.asExtended().blue(), color.asExtended().green(), color.asExtended().red(), color.asExtended().alpha());
+ else {
+ float r, g, b, a;
+ color.getRGBA(r, g, b, a);
+ cairo_set_source_rgba(cr, b, g, r, a);
+ }
+
cairo_rectangle(cr, 0, 0, width, height);
cairo_fill(cr);
@@ -367,8 +286,6 @@ void TextureMapperGL::drawNumber(int number, const Color& color, const FloatPoin
#endif
}
-#if ENABLE(CSS_FILTERS)
-
static TextureMapperShaderProgram::Options optionsForFilterType(FilterOperation::OperationType type, unsigned pass)
{
switch (type) {
@@ -399,27 +316,6 @@ static TextureMapperShaderProgram::Options optionsForFilterType(FilterOperation:
}
}
-static unsigned getPassesRequiredForFilter(FilterOperation::OperationType type)
-{
- switch (type) {
- case FilterOperation::GRAYSCALE:
- case FilterOperation::SEPIA:
- case FilterOperation::SATURATE:
- case FilterOperation::HUE_ROTATE:
- case FilterOperation::INVERT:
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::OPACITY:
- return 1;
- case FilterOperation::BLUR:
- case FilterOperation::DROP_SHADOW:
- // We use two-passes (vertical+horizontal) for blur and drop-shadow.
- return 2;
- default:
- return 0;
- }
-}
-
// Create a normal distribution of 21 values between -2 and 2.
static const unsigned GaussianKernelHalfWidth = 11;
static const float GaussianKernelStep = 0.2;
@@ -453,23 +349,23 @@ static float* gaussianKernel()
return kernel;
}
-static void prepareFilterProgram(TextureMapperShaderProgram* program, const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture)
+static void prepareFilterProgram(TextureMapperShaderProgram& program, const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture)
{
- RefPtr<GraphicsContext3D> context = program->context();
- context->useProgram(program->programID());
+ Ref<GraphicsContext3D> context = program.context();
+ context->useProgram(program.programID());
switch (operation.type()) {
case FilterOperation::GRAYSCALE:
case FilterOperation::SEPIA:
case FilterOperation::SATURATE:
case FilterOperation::HUE_ROTATE:
- context->uniform1f(program->filterAmountLocation(), static_cast<const BasicColorMatrixFilterOperation&>(operation).amount());
+ context->uniform1f(program.filterAmountLocation(), static_cast<const BasicColorMatrixFilterOperation&>(operation).amount());
break;
case FilterOperation::INVERT:
case FilterOperation::BRIGHTNESS:
case FilterOperation::CONTRAST:
case FilterOperation::OPACITY:
- context->uniform1f(program->filterAmountLocation(), static_cast<const BasicComponentTransferFilterOperation&>(operation).amount());
+ context->uniform1f(program.filterAmountLocation(), static_cast<const BasicComponentTransferFilterOperation&>(operation).amount());
break;
case FilterOperation::BLUR: {
const BlurFilterOperation& blur = static_cast<const BlurFilterOperation&>(operation);
@@ -481,29 +377,29 @@ static void prepareFilterProgram(TextureMapperShaderProgram* program, const Filt
else
radius.setWidth(floatValueForLength(blur.stdDeviation(), size.width()) / size.width());
- context->uniform2f(program->blurRadiusLocation(), radius.width(), radius.height());
- context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
+ context->uniform2f(program.blurRadiusLocation(), radius.width(), radius.height());
+ context->uniform1fv(program.gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
break;
}
case FilterOperation::DROP_SHADOW: {
const DropShadowFilterOperation& shadow = static_cast<const DropShadowFilterOperation&>(operation);
- context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
+ context->uniform1fv(program.gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
switch (pass) {
case 0:
// First pass: horizontal alpha blur.
- context->uniform2f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.width()), 0);
- context->uniform2f(program->shadowOffsetLocation(), float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height()));
+ context->uniform2f(program.blurRadiusLocation(), shadow.stdDeviation() / float(size.width()), 0);
+ context->uniform2f(program.shadowOffsetLocation(), float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height()));
break;
case 1:
// Second pass: we need the shadow color and the content texture for compositing.
float r, g, b, a;
Color(premultipliedARGBFromColor(shadow.color())).getRGBA(r, g, b, a);
- context->uniform4f(program->colorLocation(), r, g, b, a);
- context->uniform2f(program->blurRadiusLocation(), 0, shadow.stdDeviation() / float(size.height()));
- context->uniform2f(program->shadowOffsetLocation(), 0, 0);
+ context->uniform4f(program.colorLocation(), r, g, b, a);
+ context->uniform2f(program.blurRadiusLocation(), 0, shadow.stdDeviation() / float(size.height()));
+ context->uniform2f(program.shadowOffsetLocation(), 0, 0);
context->activeTexture(GraphicsContext3D::TEXTURE1);
context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture);
- context->uniform1i(program->contentTextureLocation(), 1);
+ context->uniform1i(program.contentTextureLocation(), 1);
break;
}
break;
@@ -512,7 +408,6 @@ static void prepareFilterProgram(TextureMapperShaderProgram* program, const Filt
break;
}
}
-#endif
void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, unsigned exposedEdges)
{
@@ -523,13 +418,21 @@ void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect&
return;
const BitmapTextureGL& textureGL = static_cast<const BitmapTextureGL&>(texture);
-#if ENABLE(CSS_FILTERS)
- TemporaryChange<const BitmapTextureGL::FilterInfo*> filterInfo(data().filterInfo, textureGL.filterInfo());
-#endif
+ SetForScope<const BitmapTextureGL::FilterInfo*> filterInfo(data().filterInfo, textureGL.filterInfo());
drawTexture(textureGL.id(), textureGL.isOpaque() ? 0 : ShouldBlend, textureGL.size(), targetRect, matrix, opacity, exposedEdges);
}
+static bool driverSupportsNPOTTextures(GraphicsContext3D& context)
+{
+ if (context.isGLES2Compliant()) {
+ static bool supportsNPOTTextures = context.getExtensions().supports("GL_OES_texture_npot");
+ return supportsNPOTTextures;
+ }
+
+ return true;
+}
+
void TextureMapperGL::drawTexture(Platform3DObject texture, Flags flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, unsigned exposedEdges)
{
bool useRect = flags & ShouldUseARBTextureRect;
@@ -546,8 +449,9 @@ void TextureMapperGL::drawTexture(Platform3DObject texture, Flags flags, const I
options |= TextureMapperShaderProgram::Antialiasing;
flags |= ShouldAntialias;
}
+ if (wrapMode() == RepeatWrap && !driverSupportsNPOTTextures(*m_context3D))
+ options |= TextureMapperShaderProgram::ManualRepeat;
-#if ENABLE(CSS_FILTERS)
RefPtr<FilterOperation> filter = data().filterInfo ? data().filterInfo->filter: 0;
GC3Duint filterContentTextureID = 0;
@@ -558,18 +462,14 @@ void TextureMapperGL::drawTexture(Platform3DObject texture, Flags flags, const I
if (filter->affectsOpacity())
flags |= ShouldBlend;
}
-#endif
if (useAntialiasing || opacity < 1)
flags |= ShouldBlend;
- RefPtr<TextureMapperShaderProgram> program;
- program = data().sharedGLData().getShaderProgram(options);
+ Ref<TextureMapperShaderProgram> program = data().getShaderProgram(options);
-#if ENABLE(CSS_FILTERS)
if (filter)
prepareFilterProgram(program.get(), *filter.get(), data().filterInfo->pass, textureSize, filterContentTextureID);
-#endif
drawTexturedQuadWithProgram(program.get(), texture, flags, textureSize, targetRect, modelViewMatrix, opacity);
}
@@ -583,7 +483,7 @@ void TextureMapperGL::drawSolidColor(const FloatRect& rect, const Transformation
flags |= ShouldBlend | ShouldAntialias;
}
- RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().getShaderProgram(options);
+ Ref<TextureMapperShaderProgram> program = data().getShaderProgram(options);
m_context3D->useProgram(program->programID());
float r, g, b, a;
@@ -595,7 +495,7 @@ void TextureMapperGL::drawSolidColor(const FloatRect& rect, const Transformation
draw(rect, matrix, program.get(), GraphicsContext3D::TRIANGLE_FAN, flags);
}
-void TextureMapperGL::drawEdgeTriangles(TextureMapperShaderProgram* program)
+void TextureMapperGL::drawEdgeTriangles(TextureMapperShaderProgram& program)
{
const GC3Dfloat left = 0;
const GC3Dfloat top = 0;
@@ -620,29 +520,29 @@ void TextureMapperGL::drawEdgeTriangles(TextureMapperShaderProgram* program)
Platform3DObject vbo = data().getStaticVBO(GraphicsContext3D::ARRAY_BUFFER, sizeof(GC3Dfloat) * 48, unitRectSideTriangles);
m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vbo);
- m_context3D->vertexAttribPointer(program->vertexLocation(), 4, GraphicsContext3D::FLOAT, false, 0, 0);
+ m_context3D->vertexAttribPointer(program.vertexLocation(), 4, GraphicsContext3D::FLOAT, false, 0, 0);
m_context3D->drawArrays(GraphicsContext3D::TRIANGLES, 0, 12);
m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
}
-void TextureMapperGL::drawUnitRect(TextureMapperShaderProgram* program, GC3Denum drawingMode)
+void TextureMapperGL::drawUnitRect(TextureMapperShaderProgram& program, GC3Denum drawingMode)
{
static const GC3Dfloat unitRect[] = { 0, 0, 1, 0, 1, 1, 0, 1 };
Platform3DObject vbo = data().getStaticVBO(GraphicsContext3D::ARRAY_BUFFER, sizeof(GC3Dfloat) * 8, unitRect);
m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vbo);
- m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, 0);
+ m_context3D->vertexAttribPointer(program.vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, 0);
m_context3D->drawArrays(drawingMode, 0, 4);
m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
}
-void TextureMapperGL::draw(const FloatRect& rect, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram* shaderProgram, GC3Denum drawingMode, Flags flags)
+void TextureMapperGL::draw(const FloatRect& rect, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram& program, GC3Denum drawingMode, Flags flags)
{
- TransformationMatrix matrix =
- TransformationMatrix(modelViewMatrix).multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), rect));
+ TransformationMatrix matrix(modelViewMatrix);
+ matrix.multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), rect));
- m_context3D->enableVertexAttribArray(shaderProgram->vertexLocation());
- shaderProgram->setMatrix(shaderProgram->modelViewMatrixLocation(), matrix);
- shaderProgram->setMatrix(shaderProgram->projectionMatrixLocation(), data().projectionMatrix);
+ m_context3D->enableVertexAttribArray(program.vertexLocation());
+ program.setMatrix(program.modelViewMatrixLocation(), matrix);
+ program.setMatrix(program.projectionMatrixLocation(), data().projectionMatrix);
if (isInMaskMode()) {
m_context3D->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::SRC_ALPHA);
@@ -656,28 +556,40 @@ void TextureMapperGL::draw(const FloatRect& rect, const TransformationMatrix& mo
}
if (flags & ShouldAntialias)
- drawEdgeTriangles(shaderProgram);
+ drawEdgeTriangles(program);
else
- drawUnitRect(shaderProgram, drawingMode);
+ drawUnitRect(program, drawingMode);
- m_context3D->disableVertexAttribArray(shaderProgram->vertexLocation());
+ m_context3D->disableVertexAttribArray(program.vertexLocation());
m_context3D->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
m_context3D->enable(GraphicsContext3D::BLEND);
}
-void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram* program, uint32_t texture, Flags flags, const IntSize& size, const FloatRect& rect, const TransformationMatrix& modelViewMatrix, float opacity)
+void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram& program, uint32_t texture, Flags flags, const IntSize& size, const FloatRect& rect, const TransformationMatrix& modelViewMatrix, float opacity)
{
- m_context3D->useProgram(program->programID());
+ m_context3D->useProgram(program.programID());
m_context3D->activeTexture(GraphicsContext3D::TEXTURE0);
GC3Denum target = flags & ShouldUseARBTextureRect ? GC3Denum(Extensions3D::TEXTURE_RECTANGLE_ARB) : GC3Denum(GraphicsContext3D::TEXTURE_2D);
m_context3D->bindTexture(target, texture);
- m_context3D->uniform1i(program->samplerLocation(), 0);
- if (wrapMode() == RepeatWrap) {
+ m_context3D->uniform1i(program.samplerLocation(), 0);
+ if (wrapMode() == RepeatWrap && driverSupportsNPOTTextures(*m_context3D)) {
m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::REPEAT);
m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::REPEAT);
}
TransformationMatrix patternTransform = this->patternTransform();
+ if (flags & ShouldRotateTexture90) {
+ patternTransform.rotate(-90);
+ patternTransform.translate(-1, 0);
+ }
+ if (flags & ShouldRotateTexture180) {
+ patternTransform.rotate(180);
+ patternTransform.translate(-1, -1);
+ }
+ if (flags & ShouldRotateTexture270) {
+ patternTransform.rotate(-270);
+ patternTransform.translate(0, -1);
+ }
if (flags & ShouldFlipTexture)
patternTransform.flipY();
if (flags & ShouldUseARBTextureRect)
@@ -685,8 +597,8 @@ void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram* pr
if (flags & ShouldFlipTexture)
patternTransform.translate(0, -1);
- program->setMatrix(program->textureSpaceMatrixLocation(), patternTransform);
- m_context3D->uniform1f(program->opacityLocation(), opacity);
+ program.setMatrix(program.textureSpaceMatrixLocation(), patternTransform);
+ m_context3D->uniform1f(program.opacityLocation(), opacity);
if (opacity < 1)
flags |= ShouldBlend;
@@ -696,225 +608,17 @@ void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram* pr
m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
}
-BitmapTextureGL::BitmapTextureGL(TextureMapperGL* textureMapper)
- : m_id(0)
- , m_fbo(0)
- , m_rbo(0)
- , m_depthBufferObject(0)
- , m_shouldClear(true)
- , m_context3D(textureMapper->graphicsContext3D())
-{
-}
-
-bool BitmapTextureGL::canReuseWith(const IntSize& contentsSize, Flags)
-{
- return contentsSize == m_textureSize;
-}
-
-#if OS(DARWIN)
-#define DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-#else
-#define DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE GraphicsContext3D::UNSIGNED_BYTE
-#endif
-
-static void swizzleBGRAToRGBA(uint32_t* data, const IntRect& rect, int stride = 0)
-{
- stride = stride ? stride : rect.width();
- for (int y = rect.y(); y < rect.maxY(); ++y) {
- uint32_t* p = data + y * stride;
- for (int x = rect.x(); x < rect.maxX(); ++x)
- p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
- }
-}
-
-// If GL_EXT_texture_format_BGRA8888 is supported in the OpenGLES
-// internal and external formats need to be BGRA
-static bool driverSupportsExternalTextureBGRA(GraphicsContext3D* context)
-{
- if (context->isGLES2Compliant()) {
- static bool supportsExternalTextureBGRA = context->getExtensions()->supports("GL_EXT_texture_format_BGRA8888");
- return supportsExternalTextureBGRA;
- }
-
- return true;
-}
-
-static bool driverSupportsSubImage(GraphicsContext3D* context)
-{
- if (context->isGLES2Compliant()) {
- static bool supportsSubImage = context->getExtensions()->supports("GL_EXT_unpack_subimage");
- return supportsSubImage;
- }
-
- return true;
-}
-
-void BitmapTextureGL::didReset()
-{
- if (!m_id)
- m_id = m_context3D->createTexture();
-
- m_shouldClear = true;
- if (m_textureSize == contentSize())
- return;
-
-
- m_textureSize = contentSize();
- m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id);
- m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
- m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
- m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
- m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
-
- Platform3DObject internalFormat = GraphicsContext3D::RGBA;
- Platform3DObject externalFormat = GraphicsContext3D::BGRA;
- if (m_context3D->isGLES2Compliant()) {
- if (driverSupportsExternalTextureBGRA(m_context3D.get()))
- internalFormat = GraphicsContext3D::BGRA;
- else
- externalFormat = GraphicsContext3D::RGBA;
- }
-
- m_context3D->texImage2DDirect(GraphicsContext3D::TEXTURE_2D, 0, internalFormat, m_textureSize.width(), m_textureSize.height(), 0, externalFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, 0);
-}
-
-void BitmapTextureGL::updateContentsNoSwizzle(const void* srcData, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine, unsigned bytesPerPixel, Platform3DObject glFormat)
-{
- m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id);
- if (driverSupportsSubImage(m_context3D.get())) { // For ES drivers that don't support sub-images.
- // Use the OpenGL sub-image extension, now that we know it's available.
- m_context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerLine / bytesPerPixel);
- m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, sourceOffset.y());
- m_context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, sourceOffset.x());
- }
-
- m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, srcData);
-
- if (driverSupportsSubImage(m_context3D.get())) { // For ES drivers that don't support sub-images.
- m_context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, 0);
- m_context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
- }
-}
-
-void BitmapTextureGL::updateContents(const void* srcData, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag updateContentsFlag)
-{
- Platform3DObject glFormat = GraphicsContext3D::RGBA;
- m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id);
-
- const unsigned bytesPerPixel = 4;
- char* data = reinterpret_cast<char*>(const_cast<void*>(srcData));
- Vector<char> temporaryData;
- IntPoint adjustedSourceOffset = sourceOffset;
-
- // Texture upload requires subimage buffer if driver doesn't support subimage and we don't have full image upload.
- bool requireSubImageBuffer = !driverSupportsSubImage(m_context3D.get())
- && !(bytesPerLine == static_cast<int>(targetRect.width() * bytesPerPixel) && adjustedSourceOffset == IntPoint::zero());
-
- // prepare temporaryData if necessary
- if ((!driverSupportsExternalTextureBGRA(m_context3D.get()) && updateContentsFlag == UpdateCannotModifyOriginalImageData) || requireSubImageBuffer) {
- temporaryData.resize(targetRect.width() * targetRect.height() * bytesPerPixel);
- data = temporaryData.data();
- const char* bits = static_cast<const char*>(srcData);
- const char* src = bits + sourceOffset.y() * bytesPerLine + sourceOffset.x() * bytesPerPixel;
- char* dst = data;
- const int targetBytesPerLine = targetRect.width() * bytesPerPixel;
- for (int y = 0; y < targetRect.height(); ++y) {
- memcpy(dst, src, targetBytesPerLine);
- src += bytesPerLine;
- dst += targetBytesPerLine;
- }
-
- bytesPerLine = targetBytesPerLine;
- adjustedSourceOffset = IntPoint(0, 0);
- }
-
- if (driverSupportsExternalTextureBGRA(m_context3D.get()))
- glFormat = GraphicsContext3D::BGRA;
- else
- swizzleBGRAToRGBA(reinterpret_cast_ptr<uint32_t*>(data), IntRect(adjustedSourceOffset, targetRect.size()), bytesPerLine / bytesPerPixel);
-
- updateContentsNoSwizzle(data, targetRect, adjustedSourceOffset, bytesPerLine, bytesPerPixel, glFormat);
-}
-
-void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag)
-{
- if (!image)
- return;
- NativeImagePtr frameImage = image->nativeImageForCurrentFrame();
- if (!frameImage)
- return;
-
- int bytesPerLine;
- const char* imageData;
-
-#if USE(CAIRO)
- cairo_surface_t* surface = frameImage.get();
- imageData = reinterpret_cast<const char*>(cairo_image_surface_get_data(surface));
- bytesPerLine = cairo_image_surface_get_stride(surface);
-#endif
-
- updateContents(imageData, targetRect, offset, bytesPerLine, updateContentsFlag);
-}
-
-#if ENABLE(CSS_FILTERS)
void TextureMapperGL::drawFiltered(const BitmapTexture& sampler, const BitmapTexture* contentTexture, const FilterOperation& filter, int pass)
{
// For standard filters, we always draw the whole texture without transformations.
TextureMapperShaderProgram::Options options = optionsForFilterType(filter.type(), pass);
- RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().getShaderProgram(options);
- ASSERT(program);
+ Ref<TextureMapperShaderProgram> program = data().getShaderProgram(options);
prepareFilterProgram(program.get(), filter, pass, sampler.contentSize(), contentTexture ? static_cast<const BitmapTextureGL*>(contentTexture)->id() : 0);
FloatRect targetRect(IntPoint::zero(), sampler.contentSize());
drawTexturedQuadWithProgram(program.get(), static_cast<const BitmapTextureGL&>(sampler).id(), 0, IntSize(1, 1), targetRect, TransformationMatrix(), 1);
}
-PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(TextureMapper* textureMapper, const FilterOperations& filters)
-{
- if (filters.isEmpty())
- return this;
-
- TextureMapperGL* texmapGL = static_cast<TextureMapperGL*>(textureMapper);
- RefPtr<BitmapTexture> previousSurface = texmapGL->data().currentSurface;
- RefPtr<BitmapTexture> resultSurface = this;
- RefPtr<BitmapTexture> intermediateSurface;
- RefPtr<BitmapTexture> spareSurface;
-
- m_filterInfo = FilterInfo();
-
- for (size_t i = 0; i < filters.size(); ++i) {
- RefPtr<FilterOperation> filter = filters.operations()[i];
- ASSERT(filter);
-
- int numPasses = getPassesRequiredForFilter(filter->type());
- for (int j = 0; j < numPasses; ++j) {
- bool last = (i == filters.size() - 1) && (j == numPasses - 1);
- if (!last) {
- if (!intermediateSurface)
- intermediateSurface = texmapGL->acquireTextureFromPool(contentSize());
- texmapGL->bindSurface(intermediateSurface.get());
- }
-
- if (last) {
- toBitmapTextureGL(resultSurface.get())->m_filterInfo = BitmapTextureGL::FilterInfo(filter, j, spareSurface);
- break;
- }
-
- texmapGL->drawFiltered(*resultSurface.get(), spareSurface.get(), *filter, j);
- if (!j && filter->type() == FilterOperation::DROP_SHADOW) {
- spareSurface = resultSurface;
- resultSurface.clear();
- }
- std::swap(resultSurface, intermediateSurface);
- }
- }
-
- texmapGL->bindSurface(previousSurface.get());
- return resultSurface;
-}
-#endif
-
static inline TransformationMatrix createProjectionMatrix(const IntSize& size, bool mirrored)
{
const float nearValue = 9999999;
@@ -926,95 +630,6 @@ static inline TransformationMatrix createProjectionMatrix(const IntSize& size, b
-1, mirrored ? -1 : 1, -(farValue + nearValue) / (farValue - nearValue), 1);
}
-void BitmapTextureGL::initializeStencil()
-{
- if (m_rbo)
- return;
-
- m_rbo = m_context3D->createRenderbuffer();
- m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_rbo);
-#ifdef TEXMAP_OPENGL_ES_2
- m_context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, m_textureSize.width(), m_textureSize.height());
-#else
- m_context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_STENCIL, m_textureSize.width(), m_textureSize.height());
-#endif
- m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
- m_context3D->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_rbo);
- m_context3D->clearStencil(0);
- m_context3D->clear(GraphicsContext3D::STENCIL_BUFFER_BIT);
-}
-
-void BitmapTextureGL::initializeDepthBuffer()
-{
- if (m_depthBufferObject)
- return;
-
- m_depthBufferObject = m_context3D->createRenderbuffer();
- m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBufferObject);
- m_context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, m_textureSize.width(), m_textureSize.height());
- m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
- m_context3D->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBufferObject);
-}
-
-void BitmapTextureGL::clearIfNeeded()
-{
- if (!m_shouldClear)
- return;
-
- m_clipStack.reset(IntRect(IntPoint::zero(), m_textureSize), TextureMapperGL::ClipStack::DefaultYAxis);
- m_clipStack.applyIfNeeded(m_context3D.get());
- m_context3D->clearColor(0, 0, 0, 0);
- m_context3D->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
- m_shouldClear = false;
-}
-
-void BitmapTextureGL::createFboIfNeeded()
-{
- if (m_fbo)
- return;
-
- m_fbo = m_context3D->createFramebuffer();
- m_context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
- m_context3D->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, id(), 0);
- m_shouldClear = true;
-}
-
-void BitmapTextureGL::bind(TextureMapperGL* textureMapper)
-{
- m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
- createFboIfNeeded();
- m_context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
- m_context3D->viewport(0, 0, m_textureSize.width(), m_textureSize.height());
- clearIfNeeded();
- textureMapper->data().projectionMatrix = createProjectionMatrix(m_textureSize, true /* mirrored */);
- m_clipStack.apply(m_context3D.get());
-}
-
-BitmapTextureGL::~BitmapTextureGL()
-{
- if (m_id)
- m_context3D->deleteTexture(m_id);
-
- if (m_fbo)
- m_context3D->deleteFramebuffer(m_fbo);
-
- if (m_rbo)
- m_context3D->deleteRenderbuffer(m_rbo);
-
- if (m_depthBufferObject)
- m_context3D->deleteRenderbuffer(m_depthBufferObject);
-}
-
-bool BitmapTextureGL::isValid() const
-{
- return m_id;
-}
-
-IntSize BitmapTextureGL::size() const
-{
- return m_textureSize;
-}
-
TextureMapperGL::~TextureMapperGL()
{
delete m_data;
@@ -1023,11 +638,11 @@ TextureMapperGL::~TextureMapperGL()
void TextureMapperGL::bindDefaultSurface()
{
m_context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, data().targetFrameBuffer);
- IntSize viewportSize(data().viewport[2], data().viewport[3]);
- data().projectionMatrix = createProjectionMatrix(viewportSize, data().PaintFlags & PaintingMirrored);
- m_context3D->viewport(data().viewport[0], data().viewport[1], viewportSize.width(), viewportSize.height());
- m_clipStack.apply(m_context3D.get());
- data().currentSurface.clear();
+ auto& viewport = data().viewport;
+ data().projectionMatrix = createProjectionMatrix(IntSize(viewport[2], viewport[3]), data().PaintFlags & PaintingMirrored);
+ m_context3D->viewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+ m_clipStack.apply(*m_context3D);
+ data().currentSurface = nullptr;
}
void TextureMapperGL::bindSurface(BitmapTexture *surface)
@@ -1037,10 +652,16 @@ void TextureMapperGL::bindSurface(BitmapTexture *surface)
return;
}
- static_cast<BitmapTextureGL*>(surface)->bind(this);
+ static_cast<BitmapTextureGL*>(surface)->bindAsSurface(m_context3D.get());
+ data().projectionMatrix = createProjectionMatrix(surface->size(), true /* mirrored */);
data().currentSurface = surface;
}
+BitmapTexture* TextureMapperGL::currentSurface()
+{
+ return data().currentSurface.get();
+}
+
bool TextureMapperGL::beginScissorClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
{
// 3D transforms are currently not supported in scissor clipping
@@ -1056,7 +677,7 @@ bool TextureMapperGL::beginScissorClip(const TransformationMatrix& modelViewMatr
return false;
clipStack().intersect(rect);
- clipStack().applyIfNeeded(m_context3D.get());
+ clipStack().applyIfNeeded(*m_context3D);
return true;
}
@@ -1068,15 +689,17 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con
data().initializeStencil();
- RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().getShaderProgram(TextureMapperShaderProgram::SolidColor);
+ Ref<TextureMapperShaderProgram> program = data().getShaderProgram(TextureMapperShaderProgram::SolidColor);
m_context3D->useProgram(program->programID());
m_context3D->enableVertexAttribArray(program->vertexLocation());
const GC3Dfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
- m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(unitRect));
+ Platform3DObject vbo = data().getStaticVBO(GraphicsContext3D::ARRAY_BUFFER, sizeof(GC3Dfloat) * 8, unitRect);
+ m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vbo);
+ m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, 0);
- TransformationMatrix matrix = TransformationMatrix(modelViewMatrix)
- .multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), targetRect));
+ TransformationMatrix matrix(modelViewMatrix);
+ matrix.multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), targetRect));
static const TransformationMatrix fullProjectionMatrix = TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), FloatRect(-1, -1, 2, 2));
@@ -1103,18 +726,19 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con
m_context3D->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4);
// Clear the state.
+ m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
m_context3D->disableVertexAttribArray(program->vertexLocation());
m_context3D->stencilMask(0);
// Increase stencilIndex and apply stencil testing.
clipStack().setStencilIndex(stencilIndex * 2);
- clipStack().applyIfNeeded(m_context3D.get());
+ clipStack().applyIfNeeded(*m_context3D);
}
void TextureMapperGL::endClip()
{
clipStack().pop();
- clipStack().applyIfNeeded(m_context3D.get());
+ clipStack().applyIfNeeded(*m_context3D);
}
IntRect TextureMapperGL::clipBounds()
@@ -1124,14 +748,14 @@ IntRect TextureMapperGL::clipBounds()
PassRefPtr<BitmapTexture> TextureMapperGL::createTexture()
{
- BitmapTextureGL* texture = new BitmapTextureGL(this);
- return adoptRef(texture);
+ return BitmapTextureGL::create(*m_context3D);
}
-PassOwnPtr<TextureMapper> TextureMapper::platformCreateAccelerated()
+std::unique_ptr<TextureMapper> TextureMapper::platformCreateAccelerated()
{
- return TextureMapperGL::create();
+ return std::make_unique<TextureMapperGL>();
}
};
-#endif
+
+#endif // USE(TEXTURE_MAPPER_GL)
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
index 081403f00..acc78e8c8 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
@@ -1,5 +1,6 @@
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2015 Igalia S.L.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -20,8 +21,9 @@
#ifndef TextureMapperGL_h
#define TextureMapperGL_h
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+#if USE(TEXTURE_MAPPER_GL)
+#include "ClipStack.h"
#include "FilterOperation.h"
#include "FloatQuad.h"
#include "GraphicsContext3D.h"
@@ -38,95 +40,49 @@ class FilterOperation;
// An OpenGL-ES2 implementation of TextureMapper.
class TextureMapperGL : public TextureMapper {
public:
- static PassOwnPtr<TextureMapperGL> create() { return adoptPtr(new TextureMapperGL); }
+ TextureMapperGL();
virtual ~TextureMapperGL();
enum Flag {
ShouldBlend = 0x01,
ShouldFlipTexture = 0x02,
ShouldUseARBTextureRect = 0x04,
- ShouldAntialias = 0x08
+ ShouldAntialias = 0x08,
+ ShouldRotateTexture90 = 0x10,
+ ShouldRotateTexture180 = 0x20,
+ ShouldRotateTexture270 = 0x40
};
typedef int Flags;
// TextureMapper implementation
- virtual void drawBorder(const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) override;
- virtual void drawNumber(int number, const Color&, const FloatPoint&, const TransformationMatrix&) override;
- virtual void drawTexture(const BitmapTexture&, const FloatRect&, const TransformationMatrix&, float opacity, unsigned exposedEdges) override;
+ void drawBorder(const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) override;
+ void drawNumber(int number, const Color&, const FloatPoint&, const TransformationMatrix&) override;
+ void drawTexture(const BitmapTexture&, const FloatRect&, const TransformationMatrix&, float opacity, unsigned exposedEdges) override;
virtual void drawTexture(Platform3DObject texture, Flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, unsigned exposedEdges = AllEdges);
- virtual void drawSolidColor(const FloatRect&, const TransformationMatrix&, const Color&) override;
-
- virtual void bindSurface(BitmapTexture* surface) override;
- virtual void beginClip(const TransformationMatrix&, const FloatRect&) override;
- virtual void beginPainting(PaintFlags = 0) override;
- virtual void endPainting() override;
- virtual void endClip() override;
- virtual IntRect clipBounds() override;
- virtual IntSize maxTextureSize() const override { return IntSize(2000, 2000); }
- virtual PassRefPtr<BitmapTexture> createTexture() override;
+ void drawSolidColor(const FloatRect&, const TransformationMatrix&, const Color&) override;
+
+ void bindSurface(BitmapTexture* surface) override;
+ BitmapTexture* currentSurface();
+ void beginClip(const TransformationMatrix&, const FloatRect&) override;
+ void beginPainting(PaintFlags = 0) override;
+ void endPainting() override;
+ void endClip() override;
+ IntRect clipBounds() override;
+ IntSize maxTextureSize() const override { return IntSize(2000, 2000); }
+ PassRefPtr<BitmapTexture> createTexture() override;
inline GraphicsContext3D* graphicsContext3D() const { return m_context3D.get(); }
-#if ENABLE(CSS_FILTERS)
void drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture* contentTexture, const FilterOperation&, int pass);
-#endif
void setEnableEdgeDistanceAntialiasing(bool enabled) { m_enableEdgeDistanceAntialiasing = enabled; }
private:
- struct ClipState {
- IntRect scissorBox;
- int stencilIndex;
- ClipState(const IntRect& scissors = IntRect(), int stencil = 1)
- : scissorBox(scissors)
- , stencilIndex(stencil)
- { }
- };
-
- class ClipStack {
- public:
- ClipStack()
- : clipStateDirty(false)
- { }
-
- // Y-axis should be inverted only when painting into the window.
- enum YAxisMode {
- DefaultYAxis,
- InvertedYAxis
- };
-
- void push();
- void pop();
- void apply(GraphicsContext3D*);
- void applyIfNeeded(GraphicsContext3D*);
- inline ClipState& current() { return clipState; }
- void reset(const IntRect&, YAxisMode);
- void intersect(const IntRect&);
- void setStencilIndex(int);
- inline int getStencilIndex() const
- {
- return clipState.stencilIndex;
- }
- inline bool isCurrentScissorBoxEmpty() const
- {
- return clipState.scissorBox.isEmpty();
- }
-
- private:
- ClipState clipState;
- Vector<ClipState> clipStack;
- bool clipStateDirty;
- IntSize size;
- YAxisMode yAxisMode;
- };
-
- TextureMapperGL();
-
- void drawTexturedQuadWithProgram(TextureMapperShaderProgram*, uint32_t texture, Flags, const IntSize&, const FloatRect&, const TransformationMatrix& modelViewMatrix, float opacity);
- void draw(const FloatRect&, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram*, GC3Denum drawingMode, Flags);
+ void drawTexturedQuadWithProgram(TextureMapperShaderProgram&, uint32_t texture, Flags, const IntSize&, const FloatRect&, const TransformationMatrix& modelViewMatrix, float opacity);
+ void draw(const FloatRect&, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram&, GC3Denum drawingMode, Flags);
- void drawUnitRect(TextureMapperShaderProgram*, GC3Denum drawingMode);
- void drawEdgeTriangles(TextureMapperShaderProgram*);
+ void drawUnitRect(TextureMapperShaderProgram&, GC3Denum drawingMode);
+ void drawEdgeTriangles(TextureMapperShaderProgram&);
bool beginScissorClip(const TransformationMatrix&, const FloatRect&);
void bindDefaultSurface();
@@ -136,72 +92,10 @@ private:
TextureMapperGLData* m_data;
ClipStack m_clipStack;
bool m_enableEdgeDistanceAntialiasing;
-
- friend class BitmapTextureGL;
-};
-
-class BitmapTextureGL : public BitmapTexture {
-public:
- virtual IntSize size() const;
- virtual bool isValid() const;
- virtual bool canReuseWith(const IntSize& contentsSize, Flags = 0);
- virtual void didReset();
- void bind(TextureMapperGL*);
- void initializeStencil();
- void initializeDepthBuffer();
- ~BitmapTextureGL();
- virtual uint32_t id() const { return m_id; }
- uint32_t textureTarget() const { return GraphicsContext3D::TEXTURE_2D; }
- IntSize textureSize() const { return m_textureSize; }
- void updateContents(Image*, const IntRect&, const IntPoint&, UpdateContentsFlag);
- virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag);
- virtual bool isBackedByOpenGL() const { return true; }
-
-#if ENABLE(CSS_FILTERS)
- virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const FilterOperations&) override;
- struct FilterInfo {
- RefPtr<FilterOperation> filter;
- unsigned pass;
- RefPtr<BitmapTexture> contentTexture;
-
- FilterInfo(PassRefPtr<FilterOperation> f = 0, unsigned p = 0, PassRefPtr<BitmapTexture> t = 0)
- : filter(f)
- , pass(p)
- , contentTexture(t)
- { }
- };
- const FilterInfo* filterInfo() const { return &m_filterInfo; }
-#endif
-
-private:
- void updateContentsNoSwizzle(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine, unsigned bytesPerPixel = 4, Platform3DObject glFormat = GraphicsContext3D::RGBA);
-
- Platform3DObject m_id;
- IntSize m_textureSize;
- IntRect m_dirtyRect;
- Platform3DObject m_fbo;
- Platform3DObject m_rbo;
- Platform3DObject m_depthBufferObject;
- bool m_shouldClear;
- TextureMapperGL::ClipStack m_clipStack;
- RefPtr<GraphicsContext3D> m_context3D;
-
- explicit BitmapTextureGL(TextureMapperGL*);
- BitmapTextureGL();
-
- void clearIfNeeded();
- void createFboIfNeeded();
-
-#if ENABLE(CSS_FILTERS)
- FilterInfo m_filterInfo;
-#endif
-
- friend class TextureMapperGL;
};
-BitmapTextureGL* toBitmapTextureGL(BitmapTexture*);
+} // namespace WebCore
-}
-#endif
+#endif // USE(TEXTURE_MAPPER_GL)
-#endif
+#endif // TextureMapperGL_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp
deleted file mode 100644
index 41041f91a..000000000
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- Copyright (C) 2012 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 "TextureMapperImageBuffer.h"
-
-#include "GraphicsLayer.h"
-#include "NotImplemented.h"
-
-#if USE(TEXTURE_MAPPER)
-namespace WebCore {
-
-static const int s_maximumAllowedImageBufferDimension = 4096;
-
-void BitmapTextureImageBuffer::updateContents(const void* data, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag)
-{
-#if PLATFORM(CAIRO)
- RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create_for_data(static_cast<unsigned char*>(data()),
- CAIRO_FORMAT_ARGB32,
- targetRect.width(), targetRect.height(),
- bytesPerLine));
- m_image->context()->platformContext()->drawSurfaceToContext(surface.get(), targetRect,
- IntRect(sourceOffset, targetRect.size()), m_image->context());
-#else
- UNUSED_PARAM(data);
- UNUSED_PARAM(targetRect);
- UNUSED_PARAM(sourceOffset);
- UNUSED_PARAM(bytesPerLine);
-#endif
-}
-
-void BitmapTextureImageBuffer::updateContents(TextureMapper*, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& sourceOffset, UpdateContentsFlag)
-{
- GraphicsContext* context = m_image->context();
-
- context->clearRect(targetRect);
-
- IntRect sourceRect(targetRect);
- sourceRect.setLocation(sourceOffset);
- context->save();
- context->clip(targetRect);
- context->translate(targetRect.x() - sourceOffset.x(), targetRect.y() - sourceOffset.y());
- sourceLayer->paintGraphicsLayerContents(*context, sourceRect);
- context->restore();
-}
-
-void BitmapTextureImageBuffer::didReset()
-{
- m_image = ImageBuffer::create(contentSize());
-}
-
-void BitmapTextureImageBuffer::updateContents(Image* image, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag)
-{
- m_image->context()->drawImage(image, ColorSpaceDeviceRGB, targetRect, IntRect(offset, targetRect.size()), CompositeCopy, ImageOrientationDescription());
-}
-
-IntSize TextureMapperImageBuffer::maxTextureSize() const
-{
- return IntSize(s_maximumAllowedImageBufferDimension, s_maximumAllowedImageBufferDimension);
-}
-
-void TextureMapperImageBuffer::beginClip(const TransformationMatrix& matrix, const FloatRect& rect)
-{
- GraphicsContext* context = currentContext();
- if (!context)
- return;
-#if ENABLE(3D_RENDERING)
- TransformationMatrix previousTransform = context->get3DTransform();
-#else
- AffineTransform previousTransform = context->getCTM();
-#endif
- context->save();
-
-#if ENABLE(3D_RENDERING)
- context->concat3DTransform(matrix);
-#else
- context->concatCTM(matrix.toAffineTransform());
-#endif
-
- context->clip(rect);
-
-#if ENABLE(3D_RENDERING)
- context->set3DTransform(previousTransform);
-#else
- context->setCTM(previousTransform);
-#endif
-}
-
-void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, unsigned /* exposedEdges */)
-{
- GraphicsContext* context = currentContext();
- if (!context)
- return;
-
- const BitmapTextureImageBuffer& textureImageBuffer = static_cast<const BitmapTextureImageBuffer&>(texture);
- ImageBuffer* image = textureImageBuffer.m_image.get();
- context->save();
- context->setCompositeOperation(isInMaskMode() ? CompositeDestinationIn : CompositeSourceOver);
- context->setAlpha(opacity);
-#if ENABLE(3D_RENDERING)
- context->concat3DTransform(matrix);
-#else
- context->concatCTM(matrix.toAffineTransform());
-#endif
- context->drawImageBuffer(image, ColorSpaceDeviceRGB, targetRect);
- context->restore();
-}
-
-void TextureMapperImageBuffer::drawSolidColor(const FloatRect& rect, const TransformationMatrix& matrix, const Color& color)
-{
- GraphicsContext* context = currentContext();
- if (!context)
- return;
-
- context->save();
- context->setCompositeOperation(isInMaskMode() ? CompositeDestinationIn : CompositeSourceOver);
-#if ENABLE(3D_RENDERING)
- context->concat3DTransform(matrix);
-#else
- context->concatCTM(matrix.toAffineTransform());
-#endif
-
- context->fillRect(rect, color, ColorSpaceDeviceRGB);
- context->restore();
-}
-
-void TextureMapperImageBuffer::drawBorder(const Color&, float /* borderWidth */, const FloatRect&, const TransformationMatrix&)
-{
- notImplemented();
-}
-
-void TextureMapperImageBuffer::drawNumber(int /* number */, const Color&, const FloatPoint&, const TransformationMatrix&)
-{
- notImplemented();
-}
-
-#if ENABLE(CSS_FILTERS)
-PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(TextureMapper*, const FilterOperations&)
-{
- ASSERT_NOT_REACHED();
- return this;
-}
-#endif
-
-}
-#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h
deleted file mode 100644
index f5e38b358..000000000
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- Copyright (C) 2012 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 TextureMapperImageBuffer_h
-#define TextureMapperImageBuffer_h
-
-#include "ImageBuffer.h"
-#include "TextureMapper.h"
-
-#if USE(TEXTURE_MAPPER)
-namespace WebCore {
-
-class BitmapTextureImageBuffer : public BitmapTexture {
- friend class TextureMapperImageBuffer;
-public:
- static PassRefPtr<BitmapTexture> create() { return adoptRef(new BitmapTextureImageBuffer); }
- virtual IntSize size() const { return m_image->internalSize(); }
- virtual void didReset();
- virtual bool isValid() const { return m_image.get(); }
- inline GraphicsContext* graphicsContext() { return m_image ? m_image->context() : 0; }
- virtual void updateContents(Image*, const IntRect&, const IntPoint&, UpdateContentsFlag);
- virtual void updateContents(TextureMapper*, GraphicsLayer*, const IntRect& target, const IntPoint& offset, UpdateContentsFlag);
- virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag);
-#if ENABLE(CSS_FILTERS)
- PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const FilterOperations&);
-#endif
-
-private:
- BitmapTextureImageBuffer() { }
- std::unique_ptr<ImageBuffer> m_image;
-};
-
-
-class TextureMapperImageBuffer : public TextureMapper {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- static PassOwnPtr<TextureMapper> create() { return adoptPtr(new TextureMapperImageBuffer); }
-
- // TextureMapper implementation
- virtual void drawBorder(const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) override;
- virtual void drawNumber(int number, const Color&, const FloatPoint&, const TransformationMatrix&) override;
- virtual void drawTexture(const BitmapTexture&, const FloatRect& targetRect, const TransformationMatrix&, float opacity, unsigned exposedEdges) override;
- virtual void drawSolidColor(const FloatRect&, const TransformationMatrix&, const Color&) override;
- virtual void beginClip(const TransformationMatrix&, const FloatRect&) override;
- virtual void bindSurface(BitmapTexture* surface) override { m_currentSurface = surface;}
- virtual void endClip() override { graphicsContext()->restore(); }
- virtual IntRect clipBounds() override { return currentContext()->clipBounds(); }
- virtual IntSize maxTextureSize() const;
- virtual PassRefPtr<BitmapTexture> createTexture() override { return BitmapTextureImageBuffer::create(); }
-
- inline GraphicsContext* currentContext()
- {
- return m_currentSurface ? static_cast<BitmapTextureImageBuffer*>(m_currentSurface.get())->graphicsContext() : graphicsContext();
- }
-
-private:
- TextureMapperImageBuffer()
- : TextureMapper(SoftwareMode)
- { }
- RefPtr<BitmapTexture> m_currentSurface;
-};
-
-}
-#endif // USE(TEXTURE_MAPPER)
-
-#endif // TextureMapperImageBuffer_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
index 7e7babbcd..d39cffcbb 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
@@ -21,35 +21,25 @@
#include "TextureMapperLayer.h"
#include "FloatQuad.h"
+#include "GraphicsLayerTextureMapper.h"
#include "Region.h"
#include <wtf/MathExtras.h>
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-
namespace WebCore {
class TextureMapperPaintOptions {
public:
- RefPtr<BitmapTexture> surface;
- float opacity;
+ TextureMapperPaintOptions(TextureMapper& textureMapper)
+ : textureMapper(textureMapper)
+ { }
+
+ TextureMapper& textureMapper;
TransformationMatrix transform;
+ RefPtr<BitmapTexture> surface;
+ float opacity { 1 };
IntSize offset;
- TextureMapper* textureMapper;
- TextureMapperPaintOptions()
- : opacity(1)
- , textureMapper(0)
- { }
};
-const TextureMapperLayer* TextureMapperLayer::rootLayer() const
-{
- if (m_effectTarget)
- return m_effectTarget->rootLayer();
- if (m_parent)
- return m_parent->rootLayer();
- return this;
-}
-
void TextureMapperLayer::computeTransformsRecursive()
{
if (m_state.size.isEmpty() && m_state.masksToBounds)
@@ -72,9 +62,9 @@ void TextureMapperLayer::computeTransformsRecursive()
m_state.maskLayer->computeTransformsRecursive();
if (m_state.replicaLayer)
m_state.replicaLayer->computeTransformsRecursive();
- for (size_t i = 0; i < m_children.size(); ++i) {
- RELEASE_ASSERT(m_children[i]->m_parent == this);
- m_children[i]->computeTransformsRecursive();
+ for (auto* child : m_children) {
+ ASSERT(child->m_parent == this);
+ child->computeTransformsRecursive();
}
// Reorder children if needed on the way back up.
@@ -86,19 +76,19 @@ void TextureMapperLayer::paint()
{
computeTransformsRecursive();
- TextureMapperPaintOptions options;
- options.textureMapper = m_textureMapper;
- options.textureMapper->bindSurface(0);
+ ASSERT(m_textureMapper);
+ TextureMapperPaintOptions options(*m_textureMapper);
+ options.textureMapper.bindSurface(0);
+
paintRecursive(options);
}
static Color blendWithOpacity(const Color& color, float opacity)
{
- RGBA32 rgba = color.rgb();
- // See Color::getRGBA() to know how to extract alpha from color.
- float alpha = alphaChannel(rgba) / 255.;
- float effectiveAlpha = alpha * opacity;
- return Color(colorWithOverrideAlpha(rgba, effectiveAlpha));
+ if (color.isOpaque() && opacity == 1.)
+ return color;
+
+ return color.colorWithAlphaMultipliedBy(opacity);
}
void TextureMapperLayer::computePatternTransformIfNeeded()
@@ -108,8 +98,8 @@ void TextureMapperLayer::computePatternTransformIfNeeded()
m_patternTransformDirty = false;
m_patternTransform =
- TransformationMatrix::rectToRect(FloatRect(FloatPoint::zero(), m_state.contentsTileSize), m_state.contentsRect)
- .multiply(TransformationMatrix().translate(m_state.contentsTilePhase.x() / m_state.contentsRect.width(), m_state.contentsTilePhase.y() / m_state.contentsRect.height()));
+ TransformationMatrix::rectToRect(FloatRect(FloatPoint::zero(), m_state.contentsTileSize), FloatRect(FloatPoint::zero(), m_state.contentsRect.size()))
+ .multiply(TransformationMatrix().translate(m_state.contentsTilePhase.width() / m_state.contentsRect.width(), m_state.contentsTilePhase.height() / m_state.contentsRect.height()));
}
void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
@@ -123,15 +113,15 @@ void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
transform.multiply(options.transform);
transform.multiply(m_currentTransform.combined());
- if (m_state.solidColor.isValid() && !m_state.contentsRect.isEmpty() && m_state.solidColor.alpha()) {
- options.textureMapper->drawSolidColor(m_state.contentsRect, transform, blendWithOpacity(m_state.solidColor, options.opacity));
+ if (m_state.solidColor.isValid() && !m_state.contentsRect.isEmpty() && m_state.solidColor.isVisible()) {
+ options.textureMapper.drawSolidColor(m_state.contentsRect, transform, blendWithOpacity(m_state.solidColor, options.opacity));
if (m_state.showDebugBorders)
- options.textureMapper->drawBorder(m_state.debugBorderColor, m_state.debugBorderWidth, layerRect(), transform);
+ options.textureMapper.drawBorder(m_state.debugBorderColor, m_state.debugBorderWidth, layerRect(), transform);
return;
}
- options.textureMapper->setWrapMode(TextureMapper::StretchWrap);
- options.textureMapper->setPatternTransform(TransformationMatrix());
+ options.textureMapper.setWrapMode(TextureMapper::StretchWrap);
+ options.textureMapper.setPatternTransform(TransformationMatrix());
if (m_backingStore) {
FloatRect targetRect = layerRect();
@@ -149,8 +139,8 @@ void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
if (!m_state.contentsTileSize.isEmpty()) {
computePatternTransformIfNeeded();
- options.textureMapper->setWrapMode(TextureMapper::RepeatWrap);
- options.textureMapper->setPatternTransform(m_patternTransform);
+ options.textureMapper.setWrapMode(TextureMapper::RepeatWrap);
+ options.textureMapper.setPatternTransform(m_patternTransform);
}
ASSERT(!layerRect().isEmpty());
@@ -159,16 +149,12 @@ void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
m_contentsLayer->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, m_state.contentsRect, transform);
}
-int TextureMapperLayer::compareGraphicsLayersZValue(const void* a, const void* b)
-{
- TextureMapperLayer* const* layerA = static_cast<TextureMapperLayer* const*>(a);
- TextureMapperLayer* const* layerB = static_cast<TextureMapperLayer* const*>(b);
- return int(((*layerA)->m_centerZ - (*layerB)->m_centerZ) * 1000);
-}
-
void TextureMapperLayer::sortByZOrder(Vector<TextureMapperLayer* >& array)
{
- qsort(array.data(), array.size(), sizeof(TextureMapperLayer*), compareGraphicsLayersZValue);
+ std::sort(array.begin(), array.end(),
+ [](TextureMapperLayer* a, TextureMapperLayer* b) {
+ return a->m_centerZ < b->m_centerZ;
+ });
}
void TextureMapperLayer::paintSelfAndChildren(const TextureMapperPaintOptions& options)
@@ -184,14 +170,14 @@ void TextureMapperLayer::paintSelfAndChildren(const TextureMapperPaintOptions& o
clipTransform.translate(options.offset.width(), options.offset.height());
clipTransform.multiply(options.transform);
clipTransform.multiply(m_currentTransform.combined());
- options.textureMapper->beginClip(clipTransform, layerRect());
+ options.textureMapper.beginClip(clipTransform, layerRect());
}
- for (size_t i = 0; i < m_children.size(); ++i)
- m_children[i]->paintRecursive(options);
+ for (auto* child : m_children)
+ child->paintRecursive(options);
if (shouldClip)
- options.textureMapper->endClip();
+ options.textureMapper.endClip();
}
bool TextureMapperLayer::shouldBlend() const
@@ -224,7 +210,7 @@ void TextureMapperLayer::paintSelfAndChildrenWithReplica(const TextureMapperPain
TextureMapperPaintOptions replicaOptions(options);
replicaOptions.transform
.multiply(m_state.replicaLayer->m_currentTransform.combined())
- .multiply(m_currentTransform.combined().inverse());
+ .multiply(m_currentTransform.combined().inverse().value_or(TransformationMatrix()));
paintSelfAndChildren(replicaOptions);
}
@@ -243,17 +229,15 @@ void TextureMapperLayer::setAnimatedOpacity(float opacity)
TransformationMatrix TextureMapperLayer::replicaTransform()
{
- return TransformationMatrix(m_state.replicaLayer->m_currentTransform.combined()).multiply(m_currentTransform.combined().inverse());
+ return TransformationMatrix(m_state.replicaLayer->m_currentTransform.combined()).multiply(m_currentTransform.combined().inverse().value_or(TransformationMatrix()));
}
-#if ENABLE(CSS_FILTERS)
void TextureMapperLayer::setAnimatedFilters(const FilterOperations& filters)
{
m_currentFilters = filters;
}
-#endif
-static void resolveOverlaps(Region newRegion, Region& overlapRegion, Region& nonOverlapRegion)
+static void resolveOverlaps(Region& newRegion, Region& overlapRegion, Region& nonOverlapRegion)
{
Region newOverlapRegion(newRegion);
newOverlapRegion.intersect(nonOverlapRegion);
@@ -271,10 +255,9 @@ void TextureMapperLayer::computeOverlapRegions(Region& overlapRegion, Region& no
FloatRect boundingRect;
if (m_backingStore || m_state.masksToBounds || m_state.maskLayer || hasFilters())
boundingRect = layerRect();
- else if (m_contentsLayer || m_state.solidColor.alpha())
+ else if (m_contentsLayer || m_state.solidColor.isVisible())
boundingRect = m_state.contentsRect;
-#if ENABLE(CSS_FILTERS)
if (m_currentFilters.hasOutsets()) {
FilterOutsets outsets = m_currentFilters.outsets();
IntRect unfilteredTargetRect(boundingRect);
@@ -282,7 +265,6 @@ void TextureMapperLayer::computeOverlapRegions(Region& overlapRegion, Region& no
boundingRect.expand(outsets.left() + outsets.right(), outsets.top() + outsets.bottom());
boundingRect.unite(unfilteredTargetRect);
}
-#endif
TransformationMatrix replicaMatrix;
if (m_state.replicaLayer) {
@@ -304,10 +286,8 @@ void TextureMapperLayer::computeOverlapRegions(Region& overlapRegion, Region& no
Region newNonOverlapRegion(enclosingIntRect(boundingRect));
if (!m_state.masksToBounds) {
- for (size_t i = 0; i < m_children.size(); ++i) {
- TextureMapperLayer* child = m_children[i];
+ for (auto* child : m_children)
child->computeOverlapRegions(newOverlapRegion, newNonOverlapRegion, ResolveSelfOverlapIfNeeded);
- }
}
if (m_state.replicaLayer) {
@@ -345,14 +325,13 @@ void TextureMapperLayer::paintUsingOverlapRegions(const TextureMapperPaintOption
nonOverlapRegion.translate(options.offset);
Vector<IntRect> rects = nonOverlapRegion.rects();
- for (size_t i = 0; i < rects.size(); ++i) {
- IntRect rect = rects[i];
- if (!rect.intersects(options.textureMapper->clipBounds()))
+ for (auto& rect : rects) {
+ if (!rect.intersects(options.textureMapper.clipBounds()))
continue;
- options.textureMapper->beginClip(TransformationMatrix(), rects[i]);
+ options.textureMapper.beginClip(TransformationMatrix(), rect);
paintSelfAndChildrenWithReplica(options);
- options.textureMapper->endClip();
+ options.textureMapper.endClip();
}
rects = overlapRegion.rects();
@@ -362,11 +341,10 @@ void TextureMapperLayer::paintUsingOverlapRegions(const TextureMapperPaintOption
rects.append(overlapRegion.bounds());
}
- IntSize maxTextureSize = options.textureMapper->maxTextureSize();
- IntRect adjustedClipBounds(options.textureMapper->clipBounds());
+ IntSize maxTextureSize = options.textureMapper.maxTextureSize();
+ IntRect adjustedClipBounds(options.textureMapper.clipBounds());
adjustedClipBounds.move(-options.offset);
- for (size_t i = 0; i < rects.size(); ++i) {
- IntRect rect = rects[i];
+ for (auto& rect : rects) {
for (int x = rect.x(); x < rect.maxX(); x += maxTextureSize.width()) {
for (int y = rect.y(); y < rect.maxY(); y += maxTextureSize.height()) {
IntRect tileRect(IntPoint(x, y), maxTextureSize);
@@ -382,34 +360,32 @@ void TextureMapperLayer::paintUsingOverlapRegions(const TextureMapperPaintOption
void TextureMapperLayer::applyMask(const TextureMapperPaintOptions& options)
{
- options.textureMapper->setMaskMode(true);
+ options.textureMapper.setMaskMode(true);
paintSelf(options);
- options.textureMapper->setMaskMode(false);
+ options.textureMapper.setMaskMode(false);
}
PassRefPtr<BitmapTexture> TextureMapperLayer::paintIntoSurface(const TextureMapperPaintOptions& options, const IntSize& size)
{
- RefPtr<BitmapTexture> surface = options.textureMapper->acquireTextureFromPool(size);
+ RefPtr<BitmapTexture> surface = options.textureMapper.acquireTextureFromPool(size, BitmapTexture::SupportsAlpha | BitmapTexture::FBOAttachment);
TextureMapperPaintOptions paintOptions(options);
paintOptions.surface = surface;
- options.textureMapper->bindSurface(surface.get());
+ options.textureMapper.bindSurface(surface.get());
paintSelfAndChildren(paintOptions);
if (m_state.maskLayer)
m_state.maskLayer->applyMask(options);
-#if ENABLE(CSS_FILTERS)
surface = surface->applyFilters(options.textureMapper, m_currentFilters);
-#endif
- options.textureMapper->bindSurface(surface.get());
- return surface;
+ options.textureMapper.bindSurface(surface.get());
+ return surface.release();
}
static void commitSurface(const TextureMapperPaintOptions& options, PassRefPtr<BitmapTexture> surface, const IntRect& rect, float opacity)
{
- options.textureMapper->bindSurface(options.surface.get());
+ options.textureMapper.bindSurface(options.surface.get());
TransformationMatrix targetTransform;
targetTransform.translate(options.offset.width(), options.offset.height());
targetTransform.multiply(options.transform);
- options.textureMapper->drawTexture(*surface.get(), rect, targetTransform, opacity);
+ options.textureMapper.drawTexture(*surface.get(), rect, targetTransform, opacity);
}
void TextureMapperLayer::paintWithIntermediateSurface(const TextureMapperPaintOptions& options, const IntRect& rect)
@@ -430,13 +406,13 @@ void TextureMapperLayer::paintWithIntermediateSurface(const TextureMapperPaintOp
if (replicaSurface && options.opacity == 1) {
commitSurface(options, replicaSurface, rect, 1);
- replicaSurface.clear();
+ replicaSurface = nullptr;
}
mainSurface = paintIntoSurface(paintOptions, rect.size());
if (replicaSurface) {
- options.textureMapper->bindSurface(replicaSurface.get());
- options.textureMapper->drawTexture(*mainSurface.get(), FloatRect(FloatPoint::zero(), rect.size()));
+ options.textureMapper.bindSurface(replicaSurface.get());
+ options.textureMapper.drawTexture(*mainSurface.get(), FloatRect(FloatPoint::zero(), rect.size()));
mainSurface = replicaSurface;
}
@@ -461,23 +437,33 @@ void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options
TextureMapperLayer::~TextureMapperLayer()
{
- for (int i = m_children.size() - 1; i >= 0; --i)
- m_children[i]->m_parent = 0;
+ for (auto* child : m_children)
+ child->m_parent = nullptr;
- if (m_parent)
- m_parent->m_children.remove(m_parent->m_children.find(this));
+ removeFromParent();
+
+ if (m_effectTarget) {
+ if (m_effectTarget->m_state.maskLayer == this)
+ m_effectTarget->m_state.maskLayer = nullptr;
+ if (m_effectTarget->m_state.replicaLayer == this)
+ m_effectTarget->m_state.replicaLayer = nullptr;
+ }
}
-TextureMapper* TextureMapperLayer::textureMapper() const
+#if !USE(COORDINATED_GRAPHICS)
+void TextureMapperLayer::setChildren(const Vector<GraphicsLayer*>& newChildren)
{
- return rootLayer()->m_textureMapper;
+ removeAllChildren();
+ for (auto* child : newChildren)
+ addChild(&downcast<GraphicsLayerTextureMapper>(child)->layer());
}
+#endif
void TextureMapperLayer::setChildren(const Vector<TextureMapperLayer*>& newChildren)
{
removeAllChildren();
- for (size_t i = 0; i < newChildren.size(); ++i)
- addChild(newChildren[i]);
+ for (auto* child : newChildren)
+ addChild(child);
}
void TextureMapperLayer::addChild(TextureMapperLayer* childLayer)
@@ -494,25 +480,19 @@ void TextureMapperLayer::addChild(TextureMapperLayer* childLayer)
void TextureMapperLayer::removeFromParent()
{
if (m_parent) {
- unsigned i;
- for (i = 0; i < m_parent->m_children.size(); i++) {
- if (this == m_parent->m_children[i]) {
- m_parent->m_children.remove(i);
- break;
- }
- }
-
- m_parent = 0;
+ size_t index = m_parent->m_children.find(this);
+ ASSERT(index != notFound);
+ m_parent->m_children.remove(index);
}
+
+ m_parent = nullptr;
}
void TextureMapperLayer::removeAllChildren()
{
- while (m_children.size()) {
- TextureMapperLayer* curLayer = m_children[0];
- ASSERT(curLayer->m_parent);
- curLayer->removeFromParent();
- }
+ auto oldChildren = WTFMove(m_children);
+ for (auto* child : oldChildren)
+ child->m_parent = nullptr;
}
void TextureMapperLayer::setMaskLayer(TextureMapperLayer* maskLayer)
@@ -565,7 +545,7 @@ void TextureMapperLayer::setChildrenTransform(const TransformationMatrix& childr
m_currentTransform.setChildrenTransform(childrenTransform);
}
-void TextureMapperLayer::setContentsRect(const IntRect& contentsRect)
+void TextureMapperLayer::setContentsRect(const FloatRect& contentsRect)
{
if (contentsRect == m_state.contentsRect)
return;
@@ -573,7 +553,7 @@ void TextureMapperLayer::setContentsRect(const IntRect& contentsRect)
m_patternTransformDirty = true;
}
-void TextureMapperLayer::setContentsTileSize(const IntSize& size)
+void TextureMapperLayer::setContentsTileSize(const FloatSize& size)
{
if (size == m_state.contentsTileSize)
return;
@@ -581,7 +561,7 @@ void TextureMapperLayer::setContentsTileSize(const IntSize& size)
m_patternTransformDirty = true;
}
-void TextureMapperLayer::setContentsTilePhase(const IntPoint& phase)
+void TextureMapperLayer::setContentsTilePhase(const FloatSize& phase)
{
if (phase == m_state.contentsTilePhase)
return;
@@ -624,12 +604,10 @@ void TextureMapperLayer::setSolidColor(const Color& color)
m_state.solidColor = color;
}
-#if ENABLE(CSS_FILTERS)
void TextureMapperLayer::setFilters(const FilterOperations& filters)
{
m_state.filters = filters;
}
-#endif
void TextureMapperLayer::setDebugVisuals(bool showDebugBorders, const Color& debugBorderColor, float debugBorderWidth, bool showRepaintCounter)
{
@@ -649,7 +627,7 @@ void TextureMapperLayer::setContentsLayer(TextureMapperPlatformLayer* platformLa
m_contentsLayer = platformLayer;
}
-void TextureMapperLayer::setAnimations(const GraphicsLayerAnimations& animations)
+void TextureMapperLayer::setAnimations(const TextureMapperAnimations& animations)
{
m_animations = animations;
}
@@ -669,33 +647,29 @@ bool TextureMapperLayer::descendantsOrSelfHaveRunningAnimations() const
if (m_animations.hasRunningAnimations())
return true;
- for (size_t i = 0; i < m_children.size(); ++i) {
- if (m_children[i]->descendantsOrSelfHaveRunningAnimations())
- return true;
- }
-
- return false;
+ return std::any_of(m_children.begin(), m_children.end(),
+ [](TextureMapperLayer* child) {
+ return child->descendantsOrSelfHaveRunningAnimations();
+ });
}
void TextureMapperLayer::applyAnimationsRecursively()
{
syncAnimations();
- for (size_t i = 0; i < m_children.size(); ++i)
- m_children[i]->applyAnimationsRecursively();
+ for (auto* child : m_children)
+ child->applyAnimationsRecursively();
}
void TextureMapperLayer::syncAnimations()
{
- m_animations.apply(this);
- if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
+ m_animations.apply(*this);
+ if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyTransform))
m_currentTransform.setLocalTransform(m_state.transform);
if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
m_currentOpacity = m_state.opacity;
-#if ENABLE(CSS_FILTERS)
- if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitFilter))
+ if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyFilter))
m_currentFilters = m_state.filters;
-#endif
}
bool TextureMapperLayer::isAncestorFixedToViewport() const
@@ -756,7 +730,7 @@ TextureMapperLayer* TextureMapperLayer::findScrollableContentsLayerAt(const Floa
FloatSize TextureMapperLayer::mapScrollOffset(const FloatSize& offset)
{
double zeroX, zeroY, offsetX, offsetY;
- TransformationMatrix transform = m_currentTransform.combined().inverse();
+ TransformationMatrix transform = m_currentTransform.combined().inverse().value_or(TransformationMatrix());
transform.map(0, 0, zeroX, zeroY);
transform.map(offset.width(), offset.height(), offsetX, offsetY);
return FloatSize(offsetX - zeroX, offsetY - zeroY);
@@ -795,4 +769,3 @@ void TextureMapperLayer::didCommitScrollOffset(const IntSize& offset)
}
}
-#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h
index 87ff3f4a7..3b1c16b0b 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h
@@ -20,22 +20,21 @@
#ifndef TextureMapperLayer_h
#define TextureMapperLayer_h
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-
#include "FilterOperations.h"
#include "FloatRect.h"
-#include "GraphicsLayerAnimation.h"
#include "GraphicsLayerTransform.h"
#include "TextureMapper.h"
+#include "TextureMapperAnimation.h"
#include "TextureMapperBackingStore.h"
namespace WebCore {
+class GraphicsLayer;
class Region;
class TextureMapperPaintOptions;
class TextureMapperPlatformLayer;
-class TextureMapperLayer : public GraphicsLayerAnimation::Client {
+class TextureMapperLayer : public TextureMapperAnimation::Client {
WTF_MAKE_NONCOPYABLE(TextureMapperLayer);
WTF_MAKE_FAST_ALLOCATED;
public:
@@ -74,9 +73,12 @@ public:
void setIsScrollable(bool isScrollable) { m_isScrollable = isScrollable; }
bool isScrollable() const { return m_isScrollable; }
- TextureMapper* textureMapper() const;
+ TextureMapper* textureMapper() const { return rootLayer().m_textureMapper; }
void setTextureMapper(TextureMapper* texmap) { m_textureMapper = texmap; }
+#if !USE(COORDINATED_GRAPHICS)
+ void setChildren(const Vector<GraphicsLayer*>&);
+#endif
void setChildren(const Vector<TextureMapperLayer*>&);
void setMaskLayer(TextureMapperLayer*);
void setReplicaLayer(TextureMapperLayer*);
@@ -86,7 +88,7 @@ public:
void setPreserves3D(bool);
void setTransform(const TransformationMatrix&);
void setChildrenTransform(const TransformationMatrix&);
- void setContentsRect(const IntRect&);
+ void setContentsRect(const FloatRect&);
void setMasksToBounds(bool);
void setDrawsContent(bool);
bool drawsContent() const { return m_state.drawsContent; }
@@ -99,26 +101,20 @@ public:
void setBackfaceVisibility(bool);
void setOpacity(float);
void setSolidColor(const Color&);
- void setContentsTileSize(const IntSize&);
- void setContentsTilePhase(const IntPoint&);
-#if ENABLE(CSS_FILTERS)
+ void setContentsTileSize(const FloatSize&);
+ void setContentsTilePhase(const FloatSize&);
void setFilters(const FilterOperations&);
-#endif
bool hasFilters() const
{
-#if ENABLE(CSS_FILTERS)
return !m_currentFilters.isEmpty();
-#else
- return false;
-#endif
}
void setDebugVisuals(bool showDebugBorders, const Color& debugBorderColor, float debugBorderWidth, bool showRepaintCounter);
bool isShowingRepaintCounter() const { return m_state.showRepaintCounter; }
void setRepaintCount(int);
void setContentsLayer(TextureMapperPlatformLayer*);
- void setAnimations(const GraphicsLayerAnimations&);
+ void setAnimations(const TextureMapperAnimations&);
void setFixedToViewport(bool);
bool fixedToViewport() const { return m_fixedToViewport; }
void setBackingStore(PassRefPtr<TextureMapperBackingStore>);
@@ -134,13 +130,19 @@ public:
void addChild(TextureMapperLayer*);
private:
- const TextureMapperLayer* rootLayer() const;
+ const TextureMapperLayer& rootLayer() const
+ {
+ if (m_effectTarget)
+ return m_effectTarget->rootLayer();
+ if (m_parent)
+ return m_parent->rootLayer();
+ return *this;
+ }
void computeTransformsRecursive();
- static int compareGraphicsLayersZValue(const void* a, const void* b);
static void sortByZOrder(Vector<TextureMapperLayer* >& array);
- PassRefPtr<BitmapTexture> texture() { return m_backingStore ? m_backingStore->texture() : 0; }
+ RefPtr<BitmapTexture> texture() { return m_backingStore ? m_backingStore->texture() : 0; }
FloatPoint adjustedPosition() const { return m_state.pos + m_scrollPositionDelta - m_userScrollOffset; }
bool isAncestorFixedToViewport() const;
TransformationMatrix replicaTransform();
@@ -163,12 +165,10 @@ private:
void applyMask(const TextureMapperPaintOptions&);
void computePatternTransformIfNeeded();
- // GraphicsLayerAnimation::Client
- virtual void setAnimatedTransform(const TransformationMatrix&) override;
- virtual void setAnimatedOpacity(float) override;
-#if ENABLE(CSS_FILTERS)
- virtual void setAnimatedFilters(const FilterOperations&) override;
-#endif
+ // TextureMapperAnimation::Client
+ void setAnimatedTransform(const TransformationMatrix&) override;
+ void setAnimatedOpacity(float) override;
+ void setAnimatedFilters(const FilterOperations&) override;
bool isVisible() const;
enum ContentsLayerCount {
@@ -191,9 +191,7 @@ private:
TextureMapperPlatformLayer* m_contentsLayer;
GraphicsLayerTransform m_currentTransform;
float m_currentOpacity;
-#if ENABLE(CSS_FILTERS)
FilterOperations m_currentFilters;
-#endif
float m_centerZ;
template<class HitTestCondition> TextureMapperLayer* hitTest(const FloatPoint&, HitTestCondition);
@@ -210,14 +208,12 @@ private:
TransformationMatrix childrenTransform;
float opacity;
FloatRect contentsRect;
- IntSize contentsTileSize;
- IntPoint contentsTilePhase;
+ FloatSize contentsTileSize;
+ FloatSize contentsTilePhase;
TextureMapperLayer* maskLayer;
TextureMapperLayer* replicaLayer;
Color solidColor;
-#if ENABLE(CSS_FILTERS)
FilterOperations filters;
-#endif
Color debugBorderColor;
float debugBorderWidth;
int repaintCount;
@@ -253,7 +249,7 @@ private:
State m_state;
TextureMapper* m_textureMapper;
- GraphicsLayerAnimations m_animations;
+ TextureMapperAnimations m_animations;
FloatSize m_scrollPositionDelta;
bool m_fixedToViewport;
uint32_t m_id;
@@ -266,6 +262,5 @@ private:
};
}
-#endif
#endif // TextureMapperLayer_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
index 2482e0e94..ddacbfd0a 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
@@ -20,9 +20,7 @@
#ifndef TextureMapperPlatformLayer_h
#define TextureMapperPlatformLayer_h
-#if USE(GRAPHICS_SURFACE)
-#include "GraphicsSurface.h"
-#endif
+#if USE(TEXTURE_MAPPER)
#include "TextureMapper.h"
#include "TransformationMatrix.h"
@@ -39,22 +37,16 @@ public:
TextureMapperPlatformLayer() : m_client(0) { }
virtual ~TextureMapperPlatformLayer() { }
- virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0) = 0;
+ virtual void paintToTextureMapper(TextureMapper&, const FloatRect&, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0) = 0;
virtual void swapBuffers() { }
- virtual void drawBorder(TextureMapper* textureMapper, const Color& color, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& transform)
+ virtual void drawBorder(TextureMapper& textureMapper, const Color& color, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& transform)
{
- textureMapper->drawBorder(color, borderWidth, targetRect, transform);
+ textureMapper.drawBorder(color, borderWidth, targetRect, transform);
}
void setClient(TextureMapperPlatformLayer::Client* client)
{
m_client = client;
}
-#if USE(GRAPHICS_SURFACE)
- virtual IntSize platformLayerSize() const { return IntSize(); }
- virtual uint32_t copyToGraphicsSurface() { return 0; }
- virtual GraphicsSurfaceToken graphicsSurfaceToken() const { return GraphicsSurfaceToken(); }
- virtual GraphicsSurface::Flags graphicsSurfaceFlags() const { return GraphicsSurface::SupportsTextureTarget | GraphicsSurface::SupportsSharing; }
-#endif
protected:
TextureMapperPlatformLayer::Client* client() { return m_client; }
@@ -65,4 +57,6 @@ private:
};
+#endif // USE(TEXTURE_MAPPER)
+
#endif // TextureMapperPlatformLayer_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerBuffer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerBuffer.cpp
new file mode 100644
index 000000000..88851fe4b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerBuffer.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "TextureMapperPlatformLayerBuffer.h"
+
+namespace WebCore {
+
+TextureMapperPlatformLayerBuffer::TextureMapperPlatformLayerBuffer(RefPtr<BitmapTexture>&& texture)
+ : m_texture(WTFMove(texture))
+ , m_textureID(0)
+ , m_extraFlags(0)
+ , m_hasManagedTexture(true)
+{
+}
+
+TextureMapperPlatformLayerBuffer::TextureMapperPlatformLayerBuffer(GLuint textureID, const IntSize& size, TextureMapperGL::Flags flags)
+ : m_textureID(textureID)
+ , m_size(size)
+ , m_extraFlags(flags)
+ , m_hasManagedTexture(false)
+{
+}
+
+bool TextureMapperPlatformLayerBuffer::canReuseWithoutReset(const IntSize& size, GC3Dint internalFormat)
+{
+ return m_texture && (m_texture->size() == size) && (static_cast<BitmapTextureGL*>(m_texture.get())->internalFormat() == internalFormat || internalFormat == GraphicsContext3D::DONT_CARE);
+}
+
+void TextureMapperPlatformLayerBuffer::paintToTextureMapper(TextureMapper& textureMapper, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity)
+{
+ TextureMapperGL& texmapGL = static_cast<TextureMapperGL&>(textureMapper);
+
+ if (m_hasManagedTexture) {
+ ASSERT(m_texture);
+ BitmapTextureGL* textureGL = static_cast<BitmapTextureGL*>(m_texture.get());
+ texmapGL.drawTexture(textureGL->id(), m_extraFlags, textureGL->size(), targetRect, modelViewMatrix, opacity);
+ return;
+ }
+
+ ASSERT(m_textureID);
+ texmapGL.drawTexture(m_textureID, m_extraFlags, m_size, targetRect, modelViewMatrix, opacity);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerBuffer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerBuffer.h
new file mode 100644
index 000000000..2afe5b308
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerBuffer.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "BitmapTextureGL.h"
+#include "GraphicsTypes3D.h"
+#include "TextureMapperPlatformLayer.h"
+#include <wtf/CurrentTime.h>
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+namespace WebCore {
+
+class TextureMapperPlatformLayerBuffer : public TextureMapperPlatformLayer {
+ WTF_MAKE_NONCOPYABLE(TextureMapperPlatformLayerBuffer);
+ WTF_MAKE_FAST_ALLOCATED();
+public:
+ TextureMapperPlatformLayerBuffer(RefPtr<BitmapTexture>&&);
+ TextureMapperPlatformLayerBuffer(GLuint textureID, const IntSize&, TextureMapperGL::Flags);
+
+ virtual ~TextureMapperPlatformLayerBuffer() = default;
+
+ void paintToTextureMapper(TextureMapper&, const FloatRect&, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0) final;
+
+ bool canReuseWithoutReset(const IntSize&, GC3Dint internalFormat);
+ BitmapTextureGL& textureGL() { return static_cast<BitmapTextureGL&>(*m_texture); }
+
+ inline void markUsed() { m_timeLastUsed = monotonicallyIncreasingTime(); }
+ double lastUsedTime() const { return m_timeLastUsed; }
+
+ class UnmanagedBufferDataHolder {
+ WTF_MAKE_NONCOPYABLE(UnmanagedBufferDataHolder);
+ WTF_MAKE_FAST_ALLOCATED();
+ public:
+ UnmanagedBufferDataHolder() = default;
+ virtual ~UnmanagedBufferDataHolder() = default;
+ };
+
+ bool hasManagedTexture() const { return m_hasManagedTexture; }
+ void setUnmanagedBufferDataHolder(std::unique_ptr<UnmanagedBufferDataHolder> holder) { m_unmanagedBufferDataHolder = WTFMove(holder); }
+ void setExtraFlags(TextureMapperGL::Flags flags) { m_extraFlags = flags; }
+
+private:
+
+ RefPtr<BitmapTexture> m_texture;
+ double m_timeLastUsed { 0 };
+
+ GLuint m_textureID;
+ IntSize m_size;
+ TextureMapperGL::Flags m_extraFlags;
+ bool m_hasManagedTexture;
+ std::unique_ptr<UnmanagedBufferDataHolder> m_unmanagedBufferDataHolder;
+};
+
+} // namespace WebCore
+
+#endif // COORDINATED_GRAPHICS_THREADED
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerProxy.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerProxy.cpp
new file mode 100644
index 000000000..a3ea24754
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerProxy.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "TextureMapperPlatformLayerProxy.h"
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+#include "BitmapTextureGL.h"
+#include "TextureMapperGL.h"
+#include "TextureMapperLayer.h"
+#include "TextureMapperPlatformLayerBuffer.h"
+
+const double s_releaseUnusedSecondsTolerance = 1;
+const double s_releaseUnusedBuffersTimerInterval = 0.5;
+
+namespace WebCore {
+
+TextureMapperPlatformLayerProxy::TextureMapperPlatformLayerProxy()
+ : m_compositor(nullptr)
+ , m_targetLayer(nullptr)
+ , m_releaseUnusedBuffersTimer(RunLoop::current(), this, &TextureMapperPlatformLayerProxy::releaseUnusedBuffersTimerFired)
+{
+}
+
+TextureMapperPlatformLayerProxy::~TextureMapperPlatformLayerProxy()
+{
+ LockHolder locker(m_lock);
+ if (m_targetLayer)
+ m_targetLayer->setContentsLayer(nullptr);
+}
+
+void TextureMapperPlatformLayerProxy::activateOnCompositingThread(Compositor* compositor, TextureMapperLayer* targetLayer)
+{
+#ifndef NDEBUG
+ m_compositorThreadID = m_compositorThreadID ? m_compositorThreadID : WTF::currentThread();
+#endif
+ ASSERT(m_compositorThreadID == WTF::currentThread());
+ ASSERT(compositor);
+ ASSERT(targetLayer);
+ LockHolder locker(m_lock);
+ m_compositor = compositor;
+ m_targetLayer = targetLayer;
+ if (m_targetLayer && m_currentBuffer)
+ m_targetLayer->setContentsLayer(m_currentBuffer.get());
+
+ m_compositorThreadUpdateTimer = std::make_unique<RunLoop::Timer<TextureMapperPlatformLayerProxy>>(RunLoop::current(), this, &TextureMapperPlatformLayerProxy::compositorThreadUpdateTimerFired);
+}
+
+void TextureMapperPlatformLayerProxy::invalidate()
+{
+ ASSERT(m_compositorThreadID == WTF::currentThread());
+ Function<void()> updateFunction;
+ {
+ LockHolder locker(m_lock);
+ m_compositor = nullptr;
+ m_targetLayer = nullptr;
+
+ m_currentBuffer = nullptr;
+ m_pendingBuffer = nullptr;
+ m_releaseUnusedBuffersTimer.stop();
+ m_usedBuffers.clear();
+
+ // Clear the timer and dispatch the update function manually now.
+ m_compositorThreadUpdateTimer = nullptr;
+ if (!m_compositorThreadUpdateFunction)
+ return;
+ updateFunction = WTFMove(m_compositorThreadUpdateFunction);
+ }
+
+ updateFunction();
+}
+
+bool TextureMapperPlatformLayerProxy::isActive()
+{
+ ASSERT(m_lock.isHeld());
+ return !!m_targetLayer && !!m_compositor;
+}
+
+void TextureMapperPlatformLayerProxy::pushNextBuffer(std::unique_ptr<TextureMapperPlatformLayerBuffer> newBuffer)
+{
+ ASSERT(m_lock.isHeld());
+ m_pendingBuffer = WTFMove(newBuffer);
+
+ if (m_compositor)
+ m_compositor->onNewBufferAvailable();
+}
+
+std::unique_ptr<TextureMapperPlatformLayerBuffer> TextureMapperPlatformLayerProxy::getAvailableBuffer(const IntSize& size, GC3Dint internalFormat)
+{
+ ASSERT(m_lock.isHeld());
+ std::unique_ptr<TextureMapperPlatformLayerBuffer> availableBuffer;
+
+ auto buffers = WTFMove(m_usedBuffers);
+ for (auto& buffer : buffers) {
+ if (!buffer)
+ continue;
+
+ if (!availableBuffer && buffer->canReuseWithoutReset(size, internalFormat)) {
+ availableBuffer = WTFMove(buffer);
+ availableBuffer->markUsed();
+ continue;
+ }
+ m_usedBuffers.append(WTFMove(buffer));
+ }
+
+ if (!m_usedBuffers.isEmpty())
+ scheduleReleaseUnusedBuffers();
+ return availableBuffer;
+}
+
+void TextureMapperPlatformLayerProxy::scheduleReleaseUnusedBuffers()
+{
+ if (!m_releaseUnusedBuffersTimer.isActive())
+ m_releaseUnusedBuffersTimer.startOneShot(s_releaseUnusedBuffersTimerInterval);
+}
+
+void TextureMapperPlatformLayerProxy::releaseUnusedBuffersTimerFired()
+{
+ LockHolder locker(m_lock);
+ if (m_usedBuffers.isEmpty())
+ return;
+
+ auto buffers = WTFMove(m_usedBuffers);
+ double minUsedTime = monotonicallyIncreasingTime() - s_releaseUnusedSecondsTolerance;
+
+ for (auto& buffer : buffers) {
+ if (buffer && buffer->lastUsedTime() >= minUsedTime)
+ m_usedBuffers.append(WTFMove(buffer));
+ }
+}
+
+void TextureMapperPlatformLayerProxy::swapBuffer()
+{
+ ASSERT(m_compositorThreadID == WTF::currentThread());
+ LockHolder locker(m_lock);
+ if (!m_targetLayer || !m_pendingBuffer)
+ return;
+
+ auto prevBuffer = WTFMove(m_currentBuffer);
+
+ m_currentBuffer = WTFMove(m_pendingBuffer);
+ m_targetLayer->setContentsLayer(m_currentBuffer.get());
+
+ if (prevBuffer && prevBuffer->hasManagedTexture())
+ m_usedBuffers.append(WTFMove(prevBuffer));
+}
+
+bool TextureMapperPlatformLayerProxy::scheduleUpdateOnCompositorThread(Function<void()>&& updateFunction)
+{
+ LockHolder locker(m_lock);
+ if (!m_compositorThreadUpdateTimer)
+ return false;
+
+ m_compositorThreadUpdateFunction = WTFMove(updateFunction);
+ m_compositorThreadUpdateTimer->startOneShot(0);
+ return true;
+}
+
+void TextureMapperPlatformLayerProxy::compositorThreadUpdateTimerFired()
+{
+ Function<void()> updateFunction;
+ {
+ LockHolder locker(m_lock);
+ if (!m_compositorThreadUpdateFunction)
+ return;
+ updateFunction = WTFMove(m_compositorThreadUpdateFunction);
+ }
+
+ updateFunction();
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerProxy.h b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerProxy.h
new file mode 100644
index 000000000..b710ab4ce
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerProxy.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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 TextureMapperPlatformLayerProxy_h
+#define TextureMapperPlatformLayerProxy_h
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+#include "GraphicsTypes3D.h"
+#include "TextureMapper.h"
+#include "TransformationMatrix.h"
+#include <wtf/Condition.h>
+#include <wtf/Function.h>
+#include <wtf/Lock.h>
+#include <wtf/RunLoop.h>
+#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/Vector.h>
+
+#ifndef NDEBUG
+#include <wtf/Threading.h>
+#endif
+
+namespace WebCore {
+
+class TextureMapperLayer;
+class TextureMapperPlatformLayerProxy;
+class TextureMapperPlatformLayerBuffer;
+
+class TextureMapperPlatformLayerProxyProvider {
+public:
+ virtual RefPtr<TextureMapperPlatformLayerProxy> proxy() const = 0;
+ virtual void swapBuffersIfNeeded() = 0;
+};
+
+class TextureMapperPlatformLayerProxy : public ThreadSafeRefCounted<TextureMapperPlatformLayerProxy> {
+ WTF_MAKE_FAST_ALLOCATED();
+public:
+ class Compositor {
+ public:
+ virtual void onNewBufferAvailable() = 0;
+ };
+
+ TextureMapperPlatformLayerProxy();
+ virtual ~TextureMapperPlatformLayerProxy();
+
+ // To avoid multiple lock/release situation to update a single frame,
+ // the implementation of TextureMapperPlatformLayerProxyProvider should
+ // aquire / release the lock explicitly to use below methods.
+ Lock& lock() { return m_lock; }
+ std::unique_ptr<TextureMapperPlatformLayerBuffer> getAvailableBuffer(const IntSize&, GC3Dint internalFormat);
+ void pushNextBuffer(std::unique_ptr<TextureMapperPlatformLayerBuffer>);
+ bool isActive();
+
+ void activateOnCompositingThread(Compositor*, TextureMapperLayer*);
+ void invalidate();
+
+ void swapBuffer();
+
+ bool scheduleUpdateOnCompositorThread(Function<void()>&&);
+
+private:
+ void scheduleReleaseUnusedBuffers();
+ void releaseUnusedBuffersTimerFired();
+
+ Compositor* m_compositor;
+ TextureMapperLayer* m_targetLayer;
+
+ std::unique_ptr<TextureMapperPlatformLayerBuffer> m_currentBuffer;
+ std::unique_ptr<TextureMapperPlatformLayerBuffer> m_pendingBuffer;
+
+ Lock m_lock;
+
+ Vector<std::unique_ptr<TextureMapperPlatformLayerBuffer>> m_usedBuffers;
+
+ RunLoop::Timer<TextureMapperPlatformLayerProxy> m_releaseUnusedBuffersTimer;
+#ifndef NDEBUG
+ ThreadIdentifier m_compositorThreadID { 0 };
+#endif
+
+ void compositorThreadUpdateTimerFired();
+ std::unique_ptr<RunLoop::Timer<TextureMapperPlatformLayerProxy>> m_compositorThreadUpdateTimer;
+ Function<void()> m_compositorThreadUpdateFunction;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
+
+#endif // TextureMapperPlatformLayerProxy_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp
index 5c0a76db6..b0c371b99 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp
@@ -22,19 +22,12 @@
#include "config.h"
#include "TextureMapperShaderProgram.h"
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-#include "LengthFunctions.h"
+#if USE(TEXTURE_MAPPER_GL)
+
#include "Logging.h"
#include "TextureMapperGL.h"
-
#include <wtf/text/StringBuilder.h>
-#if PLATFORM(WIN) || (PLATFORM(GTK) && OS(WINDOWS))
-#undef NO_ERROR
-#endif
-
-#define STRINGIFY(...) #__VA_ARGS__
-
namespace WebCore {
static inline bool compositingLogEnabled()
@@ -46,85 +39,21 @@ static inline bool compositingLogEnabled()
#endif
}
-TextureMapperShaderProgram::TextureMapperShaderProgram(PassRefPtr<GraphicsContext3D> context, const String& vertex, const String& fragment)
- : m_context(context)
-{
- m_vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER);
- m_fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER);
- m_context->shaderSource(m_vertexShader, vertex);
- m_context->shaderSource(m_fragmentShader, fragment);
- m_id = m_context->createProgram();
- m_context->compileShader(m_vertexShader);
- m_context->compileShader(m_fragmentShader);
- m_context->attachShader(m_id, m_vertexShader);
- m_context->attachShader(m_id, m_fragmentShader);
- m_context->linkProgram(m_id);
-
- if (!compositingLogEnabled())
- return;
-
- if (m_context->getError() == GraphicsContext3D::NO_ERROR)
- return;
-
- String log = m_context->getShaderInfoLog(m_vertexShader);
- LOG(Compositing, "Vertex shader log: %s\n", log.utf8().data());
- log = m_context->getShaderInfoLog(m_fragmentShader);
- LOG(Compositing, "Fragment shader log: %s\n", log.utf8().data());
- log = m_context->getProgramInfoLog(m_id);
- LOG(Compositing, "Program log: %s\n", log.utf8().data());
-}
-
-void TextureMapperShaderProgram::setMatrix(GC3Duint location, const TransformationMatrix& matrix)
-{
- GC3Dfloat matrixAsFloats[] = {
- GC3Dfloat(matrix.m11()), GC3Dfloat(matrix.m12()), GC3Dfloat(matrix.m13()), GC3Dfloat(matrix.m14()),
- GC3Dfloat(matrix.m21()), GC3Dfloat(matrix.m22()), GC3Dfloat(matrix.m23()), GC3Dfloat(matrix.m24()),
- GC3Dfloat(matrix.m31()), GC3Dfloat(matrix.m32()), GC3Dfloat(matrix.m33()), GC3Dfloat(matrix.m34()),
- GC3Dfloat(matrix.m41()), GC3Dfloat(matrix.m42()), GC3Dfloat(matrix.m43()), GC3Dfloat(matrix.m44())
- };
-
- m_context->uniformMatrix4fv(location, 1, false, matrixAsFloats);
-}
-
-GC3Duint TextureMapperShaderProgram::getLocation(const AtomicString& name, VariableType type)
-{
- HashMap<AtomicString, GC3Duint>::iterator it = m_variables.find(name);
- if (it != m_variables.end())
- return it->value;
-
- GC3Duint location = 0;
- switch (type) {
- case UniformVariable:
- location = m_context->getUniformLocation(m_id, name);
- break;
- case AttribVariable:
- location = m_context->getAttribLocation(m_id, name);
- break;
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-
- m_variables.add(name, location);
- return location;
-}
+#define STRINGIFY(...) #__VA_ARGS__
-TextureMapperShaderProgram::~TextureMapperShaderProgram()
-{
- Platform3DObject programID = m_id;
- if (!programID)
- return;
+#define GLSL_DIRECTIVE(...) "#"#__VA_ARGS__"\n"
- m_context->detachShader(programID, m_vertexShader);
- m_context->deleteShader(m_vertexShader);
- m_context->detachShader(programID, m_fragmentShader);
- m_context->deleteShader(m_fragmentShader);
- m_context->deleteProgram(programID);
-}
+#define TEXTURE_SPACE_MATRIX_PRECISION_DIRECTIVE \
+ GLSL_DIRECTIVE(ifdef GL_FRAGMENT_PRECISION_HIGH) \
+ GLSL_DIRECTIVE(define TextureSpaceMatrixPrecision highp) \
+ GLSL_DIRECTIVE(else) \
+ GLSL_DIRECTIVE(define TextureSpaceMatrixPrecision mediump) \
+ GLSL_DIRECTIVE(endif)
-#define GLSL_DIRECTIVE(...) "#"#__VA_ARGS__"\n"
static const char* vertexTemplate =
+ TEXTURE_SPACE_MATRIX_PRECISION_DIRECTIVE
STRINGIFY(
+ precision TextureSpaceMatrixPrecision float;
attribute vec4 a_vertex;
uniform mat4 u_modelViewMatrix;
uniform mat4 u_projectionMatrix;
@@ -211,7 +140,10 @@ static const char* fragmentTemplate =
RECT_TEXTURE_DIRECTIVE
ANTIALIASING_TEX_COORD_DIRECTIVE
BLUR_CONSTANTS
+ TEXTURE_SPACE_MATRIX_PRECISION_DIRECTIVE
STRINGIFY(
+ precision TextureSpaceMatrixPrecision float;
+ uniform mat4 u_textureSpaceMatrix;
precision mediump float;
uniform SamplerType s_sampler;
uniform sampler2D s_contentTexture;
@@ -224,10 +156,10 @@ static const char* fragmentTemplate =
uniform vec2 u_shadowOffset;
uniform vec4 u_color;
uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
- uniform mat4 u_textureSpaceMatrix;
void noop(inout vec4 dummyParameter) { }
void noop(inout vec4 dummyParameter, vec2 texCoord) { }
+ void noop(inout vec2 dummyParameter) { }
float antialias() { return smoothstep(0., 1., v_antialias); }
@@ -239,6 +171,8 @@ static const char* fragmentTemplate =
vec2 vertexTransformTexCoord() { return v_transformedTexCoord; }
+ void applyManualRepeat(inout vec2 pos) { pos = fract(pos); }
+
void applyTexture(inout vec4 color, vec2 texCoord) { color = SamplerFunction(s_sampler, texCoord); }
void applyOpacity(inout vec4 color) { color *= u_opacity; }
void applyAntialiasing(inout vec4 color) { color *= antialias(); }
@@ -350,6 +284,7 @@ static const char* fragmentTemplate =
{
vec4 color = vec4(1., 1., 1., 1.);
vec2 texCoord = transformTexCoord();
+ applyManualRepeatIfNeeded(texCoord);
applyTextureIfNeeded(color, texCoord);
applySolidColorIfNeeded(color);
applyAntialiasingIfNeeded(color);
@@ -369,13 +304,13 @@ static const char* fragmentTemplate =
}
);
-PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderProgram::create(PassRefPtr<GraphicsContext3D> context, TextureMapperShaderProgram::Options options)
+Ref<TextureMapperShaderProgram> TextureMapperShaderProgram::create(Ref<GraphicsContext3D>&& context, TextureMapperShaderProgram::Options options)
{
- StringBuilder shaderBuilder;
#define SET_APPLIER_FROM_OPTIONS(Applier) \
- shaderBuilder.append(\
+ optionsApplierBuilder.append(\
(options & TextureMapperShaderProgram::Applier) ? ENABLE_APPLIER(Applier) : DISABLE_APPLIER(Applier))
+ StringBuilder optionsApplierBuilder;
SET_APPLIER_FROM_OPTIONS(Texture);
SET_APPLIER_FROM_OPTIONS(Rect);
SET_APPLIER_FROM_OPTIONS(SolidColor);
@@ -392,16 +327,84 @@ PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderProgram::create(PassRe
SET_APPLIER_FROM_OPTIONS(BlurFilter);
SET_APPLIER_FROM_OPTIONS(AlphaBlur);
SET_APPLIER_FROM_OPTIONS(ContentTexture);
- StringBuilder vertexBuilder;
- vertexBuilder.append(shaderBuilder.toString());
- vertexBuilder.append(vertexTemplate);
- shaderBuilder.append(fragmentTemplate);
+ SET_APPLIER_FROM_OPTIONS(ManualRepeat);
+
+ StringBuilder vertexShaderBuilder;
+ vertexShaderBuilder.append(optionsApplierBuilder.toString());
+ vertexShaderBuilder.append(vertexTemplate);
+
+ StringBuilder fragmentShaderBuilder;
+ fragmentShaderBuilder.append(optionsApplierBuilder.toString());
+ fragmentShaderBuilder.append(fragmentTemplate);
+
+ return adoptRef(*new TextureMapperShaderProgram(WTFMove(context), vertexShaderBuilder.toString(), fragmentShaderBuilder.toString()));
+}
+
+TextureMapperShaderProgram::TextureMapperShaderProgram(Ref<GraphicsContext3D>&& context, const String& vertex, const String& fragment)
+ : m_context(WTFMove(context))
+{
+ m_vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER);
+ m_context->shaderSource(m_vertexShader, vertex);
+
+ m_fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER);
+ m_context->shaderSource(m_fragmentShader, fragment);
+
+ m_id = m_context->createProgram();
+ m_context->compileShader(m_vertexShader);
+ m_context->compileShader(m_fragmentShader);
+ m_context->attachShader(m_id, m_vertexShader);
+ m_context->attachShader(m_id, m_fragmentShader);
+ m_context->linkProgram(m_id);
+
+ if (!compositingLogEnabled())
+ return;
+
+ if (m_context->getError() == GraphicsContext3D::NO_ERROR)
+ return;
- String vertexSource = vertexBuilder.toString();
- String fragmentSource = shaderBuilder.toString();
+ String log = m_context->getShaderInfoLog(m_vertexShader);
+ LOG(Compositing, "Vertex shader log: %s\n", log.utf8().data());
+ log = m_context->getShaderInfoLog(m_fragmentShader);
+ LOG(Compositing, "Fragment shader log: %s\n", log.utf8().data());
+ log = m_context->getProgramInfoLog(m_id);
+ LOG(Compositing, "Program log: %s\n", log.utf8().data());
+}
+
+TextureMapperShaderProgram::~TextureMapperShaderProgram()
+{
+ if (!m_id)
+ return;
- return adoptRef(new TextureMapperShaderProgram(context, vertexSource, fragmentSource));
+ m_context->detachShader(m_id, m_vertexShader);
+ m_context->deleteShader(m_vertexShader);
+ m_context->detachShader(m_id, m_fragmentShader);
+ m_context->deleteShader(m_fragmentShader);
+ m_context->deleteProgram(m_id);
}
+void TextureMapperShaderProgram::setMatrix(GC3Duint location, const TransformationMatrix& matrix)
+{
+ TransformationMatrix::FloatMatrix4 floatMatrix;
+ matrix.toColumnMajorFloatArray(floatMatrix);
+ m_context->uniformMatrix4fv(location, 1, false, floatMatrix);
}
-#endif
+
+GC3Duint TextureMapperShaderProgram::getLocation(const AtomicString& name, VariableType type)
+{
+ auto addResult = m_variables.ensure(name,
+ [this, &name, type] {
+ switch (type) {
+ case UniformVariable:
+ return m_context->getUniformLocation(m_id, name);
+ case AttribVariable:
+ return m_context->getAttribLocation(m_id, name);
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+ });
+ return addResult.iterator->value;
+}
+
+} // namespace WebCore
+
+#endif // USE(TEXTURE_MAPPER_GL)
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h
index 3345fc9fe..541a42b27 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h
@@ -21,16 +21,23 @@
#ifndef TextureMapperShaderProgram_h
#define TextureMapperShaderProgram_h
-#if USE(TEXTURE_MAPPER)
+#if USE(TEXTURE_MAPPER_GL)
+
#include "GraphicsContext3D.h"
#include "TransformationMatrix.h"
#include <wtf/HashMap.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/Ref.h>
#include <wtf/text/AtomicStringHash.h>
namespace WebCore {
-#define TEXMAP_DECLARE_VARIABLE(Accessor, Name, Type) GC3Duint Accessor##Location() { static const AtomicString name(Name); return getLocation(name, Type); }
+
+#define TEXMAP_DECLARE_VARIABLE(Accessor, Name, Type) \
+ GC3Duint Accessor##Location() { \
+ static NeverDestroyed<const AtomicString> name(Name, AtomicString::ConstructFromLiteral); \
+ return getLocation(name.get(), Type); \
+ }
+
#define TEXMAP_DECLARE_UNIFORM(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "u_"#Accessor, UniformVariable)
#define TEXMAP_DECLARE_ATTRIBUTE(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "a_"#Accessor, AttribVariable)
#define TEXMAP_DECLARE_SAMPLER(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "s_"#Accessor, UniformVariable)
@@ -53,15 +60,17 @@ public:
OpacityFilter = 1L << 13,
BlurFilter = 1L << 14,
AlphaBlur = 1L << 15,
- ContentTexture = 1L << 16
+ ContentTexture = 1L << 16,
+ ManualRepeat = 1L << 17
};
typedef unsigned Options;
- static PassRefPtr<TextureMapperShaderProgram> create(PassRefPtr<GraphicsContext3D>, Options);
+ static Ref<TextureMapperShaderProgram> create(Ref<GraphicsContext3D>&&, Options);
virtual ~TextureMapperShaderProgram();
+
Platform3DObject programID() const { return m_id; }
- GraphicsContext3D* context() { return m_context.get(); }
+ GraphicsContext3D& context() { return m_context; }
TEXMAP_DECLARE_ATTRIBUTE(vertex)
@@ -74,30 +83,29 @@ public:
TEXMAP_DECLARE_SAMPLER(sampler)
TEXMAP_DECLARE_SAMPLER(mask)
-#if ENABLE(CSS_FILTERS)
TEXMAP_DECLARE_UNIFORM(filterAmount)
TEXMAP_DECLARE_UNIFORM(gaussianKernel)
TEXMAP_DECLARE_UNIFORM(blurRadius)
TEXMAP_DECLARE_UNIFORM(shadowOffset)
TEXMAP_DECLARE_SAMPLER(contentTexture)
-#endif
void setMatrix(GC3Duint, const TransformationMatrix&);
private:
- TextureMapperShaderProgram(PassRefPtr<GraphicsContext3D>, const String& vertexShaderSource, const String& fragmentShaderSource);
+ TextureMapperShaderProgram(Ref<GraphicsContext3D>&&, const String& vertexShaderSource, const String& fragmentShaderSource);
+
Platform3DObject m_vertexShader;
Platform3DObject m_fragmentShader;
enum VariableType { UniformVariable, AttribVariable };
GC3Duint getLocation(const AtomicString&, VariableType);
- RefPtr<GraphicsContext3D> m_context;
+ Ref<GraphicsContext3D> m_context;
Platform3DObject m_id;
HashMap<AtomicString, GC3Duint> m_variables;
};
}
-#endif
+#endif // USE(TEXTURE_MAPPER_GL)
#endif // TextureMapperShaderProgram_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.cpp
deleted file mode 100644
index 8d38776e9..000000000
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- Copyright (C) 2013 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"
-
-#if USE(ACCELERATED_COMPOSITING) && USE(GRAPHICS_SURFACE)
-#include "TextureMapperSurfaceBackingStore.h"
-
-#include "GraphicsSurface.h"
-
-namespace WebCore {
-
-void TextureMapperSurfaceBackingStore::setGraphicsSurface(PassRefPtr<GraphicsSurface> surface)
-{
- m_graphicsSurface = surface;
-}
-
-void TextureMapperSurfaceBackingStore::swapBuffersIfNeeded(uint32_t)
-{
- if (m_graphicsSurface)
- m_graphicsSurface->swapBuffers();
-}
-
-PassRefPtr<BitmapTexture> TextureMapperSurfaceBackingStore::texture() const
-{
- // FIXME: Instead of just returning an empty texture, we should wrap the texture contents into a BitmapTexture.
- RefPtr<BitmapTexture> emptyTexture;
- return emptyTexture;
-}
-
-void TextureMapperSurfaceBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity)
-{
- if (m_graphicsSurface)
- m_graphicsSurface->paintToTextureMapper(textureMapper, targetRect, transform, opacity);
-}
-
-} // namespace WebCore
-#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.h
deleted file mode 100644
index 793c61dc3..000000000
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- Copyright (C) 2013 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 TextureMapperSurfaceBackingStore_h
-#define TextureMapperSurfaceBackingStore_h
-
-#if USE(ACCELERATED_COMPOSITING) && USE(GRAPHICS_SURFACE)
-
-#include "GraphicsSurface.h"
-#include "TextureMapperBackingStore.h"
-#include <wtf/RefPtr.h>
-
-namespace WebCore {
-
-class TextureMapper;
-class FloatRect;
-
-class TextureMapperSurfaceBackingStore : public TextureMapperBackingStore {
-public:
- static PassRefPtr<TextureMapperSurfaceBackingStore> create() { return adoptRef(new TextureMapperSurfaceBackingStore); }
- void setGraphicsSurface(PassRefPtr<GraphicsSurface>);
- void swapBuffersIfNeeded(uint32_t frontBuffer);
- virtual PassRefPtr<BitmapTexture> texture() const;
- virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float);
- virtual ~TextureMapperSurfaceBackingStore() { }
-
-private:
- TextureMapperSurfaceBackingStore()
- : TextureMapperBackingStore()
- { }
-
- RefPtr<GraphicsSurface> m_graphicsSurface;
-};
-
-}
-
-#endif
-
-#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperTile.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperTile.cpp
index 2ea7fb6ed..39365673e 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperTile.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperTile.cpp
@@ -18,18 +18,16 @@
*/
#include "config.h"
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
#include "TextureMapperTile.h"
#include "Image.h"
#include "TextureMapper.h"
-#include <wtf/RefPtr.h>
namespace WebCore {
class GraphicsLayer;
-void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* image, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
+void TextureMapperTile::updateContents(TextureMapper& textureMapper, Image* image, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
{
IntRect targetRect = enclosingIntRect(m_rect);
targetRect.intersect(dirtyRect);
@@ -43,14 +41,14 @@ void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* imag
// Normalize targetRect to the texture's coordinates.
targetRect.move(-m_rect.x(), -m_rect.y());
if (!m_texture) {
- m_texture = textureMapper->createTexture();
+ m_texture = textureMapper.createTexture();
m_texture->reset(targetRect.size(), image->currentFrameKnownToBeOpaque() ? 0 : BitmapTexture::SupportsAlpha);
}
m_texture->updateContents(image, targetRect, sourceOffset, updateContentsFlag);
}
-void TextureMapperTile::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
+void TextureMapperTile::updateContents(TextureMapper& textureMapper, GraphicsLayer* sourceLayer, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag, float scale)
{
IntRect targetRect = enclosingIntRect(m_rect);
targetRect.intersect(dirtyRect);
@@ -62,18 +60,17 @@ void TextureMapperTile::updateContents(TextureMapper* textureMapper, GraphicsLay
targetRect.move(-m_rect.x(), -m_rect.y());
if (!m_texture) {
- m_texture = textureMapper->createTexture();
+ m_texture = textureMapper.createTexture();
m_texture->reset(targetRect.size(), BitmapTexture::SupportsAlpha);
}
- m_texture->updateContents(textureMapper, sourceLayer, targetRect, sourceOffset, updateContentsFlag);
+ m_texture->updateContents(textureMapper, sourceLayer, targetRect, sourceOffset, updateContentsFlag, scale);
}
-void TextureMapperTile::paint(TextureMapper* textureMapper, const TransformationMatrix& transform, float opacity, const unsigned exposedEdges)
+void TextureMapperTile::paint(TextureMapper& textureMapper, const TransformationMatrix& transform, float opacity, const unsigned exposedEdges)
{
if (texture().get())
- textureMapper->drawTexture(*texture().get(), rect(), transform, opacity, exposedEdges);
+ textureMapper.drawTexture(*texture().get(), rect(), transform, opacity, exposedEdges);
}
} // namespace WebCore
-#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperTile.h b/Source/WebCore/platform/graphics/texmap/TextureMapperTile.h
index ee6809f20..6aebd3139 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperTile.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperTile.h
@@ -20,8 +20,6 @@
#ifndef TextureMapperTile_h
#define TextureMapperTile_h
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-
#include "FloatRect.h"
#include "Image.h"
#include "TextureMapper.h"
@@ -34,14 +32,14 @@ class GraphicsLayer;
class TextureMapperTile {
public:
- inline PassRefPtr<BitmapTexture> texture() const { return m_texture; }
+ inline RefPtr<BitmapTexture> texture() const { return m_texture; }
inline FloatRect rect() const { return m_rect; }
inline void setTexture(BitmapTexture* texture) { m_texture = texture; }
inline void setRect(const FloatRect& rect) { m_rect = rect; }
- void updateContents(TextureMapper*, Image*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData);
- void updateContents(TextureMapper*, GraphicsLayer*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData);
- virtual void paint(TextureMapper*, const TransformationMatrix&, float, const unsigned exposedEdges);
+ void updateContents(TextureMapper&, Image*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData);
+ void updateContents(TextureMapper&, GraphicsLayer*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData, float scale = 1);
+ virtual void paint(TextureMapper&, const TransformationMatrix&, float, const unsigned exposedEdges);
virtual ~TextureMapperTile() { }
explicit TextureMapperTile(const FloatRect& rect)
@@ -55,6 +53,5 @@ private:
};
}
-#endif
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.cpp
index ef564023d..6833ac6b5 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.cpp
@@ -19,27 +19,26 @@
#include "config.h"
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
#include "TextureMapperTiledBackingStore.h"
#include "ImageBuffer.h"
+#include "ImageObserver.h"
#include "TextureMapper.h"
namespace WebCore {
class GraphicsLayer;
-TextureMapperTiledBackingStore::TextureMapperTiledBackingStore()
-{
-}
-
-void TextureMapperTiledBackingStore::updateContentsFromImageIfNeeded(TextureMapper* textureMapper)
+void TextureMapperTiledBackingStore::updateContentsFromImageIfNeeded(TextureMapper& textureMapper)
{
if (!m_image)
return;
- updateContents(textureMapper, m_image.get(), m_image->size(), m_image->rect(), BitmapTexture::UpdateCannotModifyOriginalImageData);
- m_image.clear();
+ updateContents(textureMapper, m_image.get(), m_image->size(), enclosingIntRect(m_image->rect()), BitmapTexture::UpdateCannotModifyOriginalImageData);
+
+ if (m_image->imageObserver())
+ m_image->imageObserver()->didDraw(m_image.get());
+ m_image = nullptr;
}
TransformationMatrix TextureMapperTiledBackingStore::adjustedTransformForRect(const FloatRect& targetRect)
@@ -47,34 +46,48 @@ TransformationMatrix TextureMapperTiledBackingStore::adjustedTransformForRect(co
return TransformationMatrix::rectToRect(rect(), targetRect);
}
-void TextureMapperTiledBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity)
+void TextureMapperTiledBackingStore::paintToTextureMapper(TextureMapper& textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity)
{
updateContentsFromImageIfNeeded(textureMapper);
TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect);
- for (size_t i = 0; i < m_tiles.size(); ++i)
- m_tiles[i].paint(textureMapper, adjustedTransform, opacity, calculateExposedTileEdges(rect(), m_tiles[i].rect()));
+ for (auto& tile : m_tiles)
+ tile.paint(textureMapper, adjustedTransform, opacity, calculateExposedTileEdges(rect(), tile.rect()));
}
-void TextureMapperTiledBackingStore::drawBorder(TextureMapper* textureMapper, const Color& borderColor, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& transform)
+void TextureMapperTiledBackingStore::drawBorder(TextureMapper& textureMapper, const Color& borderColor, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& transform)
{
TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect);
- for (size_t i = 0; i < m_tiles.size(); ++i)
- textureMapper->drawBorder(borderColor, borderWidth, m_tiles[i].rect(), adjustedTransform);
+ for (auto& tile : m_tiles)
+ textureMapper.drawBorder(borderColor, borderWidth, tile.rect(), adjustedTransform);
}
-void TextureMapperTiledBackingStore::drawRepaintCounter(TextureMapper* textureMapper, int repaintCount, const Color& borderColor, const FloatRect& targetRect, const TransformationMatrix& transform)
+void TextureMapperTiledBackingStore::drawRepaintCounter(TextureMapper& textureMapper, int repaintCount, const Color& borderColor, const FloatRect& targetRect, const TransformationMatrix& transform)
{
TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect);
- for (size_t i = 0; i < m_tiles.size(); ++i)
- textureMapper->drawNumber(repaintCount, borderColor, m_tiles[i].rect().location(), adjustedTransform);
+ for (auto& tile : m_tiles)
+ textureMapper.drawNumber(repaintCount, borderColor, tile.rect().location(), adjustedTransform);
+}
+
+void TextureMapperTiledBackingStore::updateContentsScale(float scale)
+{
+ if (m_contentsScale == scale)
+ return;
+
+ m_isScaleDirty = true;
+ m_contentsScale = scale;
}
void TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded(const FloatSize& size, const IntSize& tileSize, bool hasAlpha)
{
- if (size == m_size)
+ if (size == m_size && !m_isScaleDirty)
return;
m_size = size;
+ m_isScaleDirty = false;
+
+ FloatSize scaledSize(m_size);
+ if (!m_image)
+ scaledSize.scale(m_contentsScale);
Vector<FloatRect> tileRectsToAdd;
Vector<int> tileIndicesToRemove;
@@ -82,8 +95,8 @@ void TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded(const FloatSiz
// This method recycles tiles. We check which tiles we need to add, which to remove, and use as many
// removable tiles as replacement for new tiles when possible.
- for (float y = 0; y < m_size.height(); y += tileSize.height()) {
- for (float x = 0; x < m_size.width(); x += tileSize.width()) {
+ for (float y = 0; y < scaledSize.height(); y += tileSize.height()) {
+ for (float x = 0; x < scaledSize.width(); x += tileSize.width()) {
FloatRect tileRect(x, y, tileSize.width(), tileSize.height());
tileRect.intersect(rect());
tileRectsToAdd.append(tileRect);
@@ -112,51 +125,52 @@ void TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded(const FloatSiz
}
// Recycle removable tiles to be used for newly requested tiles.
- for (size_t i = 0; i < tileRectsToAdd.size(); ++i) {
+ for (auto& rect : tileRectsToAdd) {
if (!tileIndicesToRemove.isEmpty()) {
// We recycle an existing tile for usage with a new tile rect.
TextureMapperTile& tile = m_tiles[tileIndicesToRemove.last()];
tileIndicesToRemove.removeLast();
- tile.setRect(tileRectsToAdd[i]);
+ tile.setRect(rect);
if (tile.texture())
tile.texture()->reset(enclosingIntRect(tile.rect()).size(), hasAlpha ? BitmapTexture::SupportsAlpha : 0);
continue;
}
- m_tiles.append(TextureMapperTile(tileRectsToAdd[i]));
+ m_tiles.append(TextureMapperTile(rect));
}
// Remove unnecessary tiles, if they weren't recycled.
// We use a threshold to make sure we don't create/destroy tiles too eagerly.
- for (size_t i = 0; i < tileIndicesToRemove.size() && m_tiles.size() > TileEraseThreshold; ++i)
- m_tiles.remove(tileIndicesToRemove[i]);
+ for (auto& index : tileIndicesToRemove) {
+ if (m_tiles.size() <= TileEraseThreshold)
+ break;
+ m_tiles.remove(index);
+ }
}
-void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, Image* image, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
+void TextureMapperTiledBackingStore::updateContents(TextureMapper& textureMapper, Image* image, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
{
- createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), !image->currentFrameKnownToBeOpaque());
- for (size_t i = 0; i < m_tiles.size(); ++i)
- m_tiles[i].updateContents(textureMapper, image, dirtyRect, updateContentsFlag);
+ createOrDestroyTilesIfNeeded(totalSize, textureMapper.maxTextureSize(), !image->currentFrameKnownToBeOpaque());
+ for (auto& tile : m_tiles)
+ tile.updateContents(textureMapper, image, dirtyRect, updateContentsFlag);
}
-void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
+void TextureMapperTiledBackingStore::updateContents(TextureMapper& textureMapper, GraphicsLayer* sourceLayer, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
{
- createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), true);
- for (size_t i = 0; i < m_tiles.size(); ++i)
- m_tiles[i].updateContents(textureMapper, sourceLayer, dirtyRect, updateContentsFlag);
+ createOrDestroyTilesIfNeeded(totalSize, textureMapper.maxTextureSize(), true);
+ for (auto& tile : m_tiles)
+ tile.updateContents(textureMapper, sourceLayer, dirtyRect, updateContentsFlag, m_contentsScale);
}
-PassRefPtr<BitmapTexture> TextureMapperTiledBackingStore::texture() const
+RefPtr<BitmapTexture> TextureMapperTiledBackingStore::texture() const
{
- for (size_t i = 0; i < m_tiles.size(); ++i) {
- RefPtr<BitmapTexture> texture = m_tiles[i].texture();
- if (texture)
+ for (const auto& tile : m_tiles) {
+ if (auto texture = tile.texture())
return texture;
}
- return PassRefPtr<BitmapTexture>();
+ return nullptr;
}
} // namespace WebCore
-#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.h
index 38161c475..8514a4f73 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.h
@@ -20,8 +20,6 @@
#ifndef TextureMapperTiledBackingStore_h
#define TextureMapperTiledBackingStore_h
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-
#include "FloatRect.h"
#include "Image.h"
#include "TextureMapperBackingStore.h"
@@ -37,28 +35,37 @@ public:
static PassRefPtr<TextureMapperTiledBackingStore> create() { return adoptRef(new TextureMapperTiledBackingStore); }
virtual ~TextureMapperTiledBackingStore() { }
- virtual PassRefPtr<BitmapTexture> texture() const override;
- virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float) override;
- virtual void drawBorder(TextureMapper*, const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) override;
- virtual void drawRepaintCounter(TextureMapper*, int repaintCount, const Color&, const FloatRect&, const TransformationMatrix&) override;
- void updateContents(TextureMapper*, Image*, const FloatSize&, const IntRect&, BitmapTexture::UpdateContentsFlag);
- void updateContents(TextureMapper*, GraphicsLayer*, const FloatSize&, const IntRect&, BitmapTexture::UpdateContentsFlag);
+ RefPtr<BitmapTexture> texture() const override;
+ void paintToTextureMapper(TextureMapper&, const FloatRect&, const TransformationMatrix&, float) override;
+ void drawBorder(TextureMapper&, const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) override;
+ void drawRepaintCounter(TextureMapper&, int repaintCount, const Color&, const FloatRect&, const TransformationMatrix&) override;
+
+ void updateContentsScale(float);
+ void updateContents(TextureMapper&, Image*, const FloatSize&, const IntRect&, BitmapTexture::UpdateContentsFlag);
+ void updateContents(TextureMapper&, GraphicsLayer*, const FloatSize&, const IntRect&, BitmapTexture::UpdateContentsFlag);
void setContentsToImage(Image* image) { m_image = image; }
private:
- TextureMapperTiledBackingStore();
+ TextureMapperTiledBackingStore() { }
+
void createOrDestroyTilesIfNeeded(const FloatSize& backingStoreSize, const IntSize& tileSize, bool hasAlpha);
- void updateContentsFromImageIfNeeded(TextureMapper*);
+ void updateContentsFromImageIfNeeded(TextureMapper&);
TransformationMatrix adjustedTransformForRect(const FloatRect&);
- inline FloatRect rect() const { return FloatRect(FloatPoint::zero(), m_size); }
+ inline FloatRect rect() const
+ {
+ FloatRect rect(FloatPoint::zero(), m_size);
+ rect.scale(m_contentsScale);
+ return rect;
+ }
Vector<TextureMapperTile> m_tiles;
FloatSize m_size;
RefPtr<Image> m_image;
+ float m_contentsScale { 1 };
+ bool m_isScaleDirty { false };
};
} // namespace WebCore
-#endif
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp
new file mode 100644
index 000000000..8da58b2ce
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp
@@ -0,0 +1,1182 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2010 Apple Inc. All rights reserved.
+ Copyright (C) 2012 Company 100, Inc.
+ Copyright (C) 2012 Intel Corporation. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "CoordinatedGraphicsLayer.h"
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "FloatQuad.h"
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+#include "GraphicsLayerFactory.h"
+#include "ScrollableArea.h"
+#include <wtf/CurrentTime.h>
+#ifndef NDEBUG
+#include <wtf/SetForScope.h>
+#endif
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+std::unique_ptr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client, Type layerType)
+{
+ if (!factory)
+ return std::make_unique<CoordinatedGraphicsLayer>(layerType, client);
+
+ return factory->createGraphicsLayer(layerType, client);
+}
+
+static CoordinatedLayerID toCoordinatedLayerID(GraphicsLayer* layer)
+{
+ return is<CoordinatedGraphicsLayer>(layer) ? downcast<CoordinatedGraphicsLayer>(*layer).id() : 0;
+}
+
+void CoordinatedGraphicsLayer::notifyFlushRequired()
+{
+ if (!m_coordinator)
+ return;
+
+ if (m_coordinator->isFlushingLayerChanges())
+ return;
+
+ client().notifyFlushRequired(this);
+}
+
+void CoordinatedGraphicsLayer::didChangeLayerState()
+{
+ m_shouldSyncLayerState = true;
+ notifyFlushRequired();
+}
+
+void CoordinatedGraphicsLayer::didChangeAnimations()
+{
+ m_shouldSyncAnimations = true;
+ notifyFlushRequired();
+}
+
+void CoordinatedGraphicsLayer::didChangeChildren()
+{
+ m_shouldSyncChildren = true;
+ notifyFlushRequired();
+}
+
+void CoordinatedGraphicsLayer::didChangeFilters()
+{
+ m_shouldSyncFilters = true;
+ notifyFlushRequired();
+}
+
+void CoordinatedGraphicsLayer::didChangeImageBacking()
+{
+ m_shouldSyncImageBacking = true;
+ notifyFlushRequired();
+}
+
+void CoordinatedGraphicsLayer::setShouldUpdateVisibleRect()
+{
+ m_shouldUpdateVisibleRect = true;
+ for (auto& child : children())
+ downcast<CoordinatedGraphicsLayer>(*child).setShouldUpdateVisibleRect();
+ if (replicaLayer())
+ downcast<CoordinatedGraphicsLayer>(*replicaLayer()).setShouldUpdateVisibleRect();
+}
+
+void CoordinatedGraphicsLayer::didChangeGeometry()
+{
+ didChangeLayerState();
+ setShouldUpdateVisibleRect();
+}
+
+CoordinatedGraphicsLayer::CoordinatedGraphicsLayer(Type layerType, GraphicsLayerClient& client)
+ : GraphicsLayer(layerType, client)
+#ifndef NDEBUG
+ , m_isPurging(false)
+#endif
+ , m_shouldUpdateVisibleRect(true)
+ , m_shouldSyncLayerState(true)
+ , m_shouldSyncChildren(true)
+ , m_shouldSyncFilters(true)
+ , m_shouldSyncImageBacking(true)
+ , m_shouldSyncAnimations(true)
+ , m_fixedToViewport(false)
+ , m_movingVisibleRect(false)
+ , m_pendingContentsScaleAdjustment(false)
+ , m_pendingVisibleRectAdjustment(false)
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ , m_shouldSyncPlatformLayer(false)
+ , m_shouldUpdatePlatformLayer(false)
+#endif
+ , m_coordinator(0)
+ , m_compositedNativeImagePtr(0)
+ , m_platformLayer(0)
+ , m_animationStartedTimer(*this, &CoordinatedGraphicsLayer::animationStartedTimerFired)
+ , m_scrollableArea(0)
+{
+ static CoordinatedLayerID nextLayerID = 1;
+ m_id = nextLayerID++;
+}
+
+CoordinatedGraphicsLayer::~CoordinatedGraphicsLayer()
+{
+ if (m_coordinator) {
+ purgeBackingStores();
+ m_coordinator->detachLayer(this);
+ }
+ ASSERT(!m_coordinatedImageBacking);
+ ASSERT(!m_mainBackingStore);
+ willBeDestroyed();
+}
+
+bool CoordinatedGraphicsLayer::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ bool ok = GraphicsLayer::setChildren(children);
+ if (!ok)
+ return false;
+ didChangeChildren();
+ return true;
+}
+
+void CoordinatedGraphicsLayer::addChild(GraphicsLayer* layer)
+{
+ GraphicsLayer::addChild(layer);
+ didChangeChildren();
+}
+
+void CoordinatedGraphicsLayer::addChildAtIndex(GraphicsLayer* layer, int index)
+{
+ GraphicsLayer::addChildAtIndex(layer, index);
+ didChangeChildren();
+}
+
+void CoordinatedGraphicsLayer::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildAbove(layer, sibling);
+ didChangeChildren();
+}
+
+void CoordinatedGraphicsLayer::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildBelow(layer, sibling);
+ didChangeChildren();
+}
+
+bool CoordinatedGraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ bool ok = GraphicsLayer::replaceChild(oldChild, newChild);
+ if (!ok)
+ return false;
+ didChangeChildren();
+ return true;
+}
+
+void CoordinatedGraphicsLayer::removeFromParent()
+{
+ if (CoordinatedGraphicsLayer* parentLayer = downcast<CoordinatedGraphicsLayer>(parent()))
+ parentLayer->didChangeChildren();
+ GraphicsLayer::removeFromParent();
+}
+
+void CoordinatedGraphicsLayer::setPosition(const FloatPoint& p)
+{
+ if (position() == p)
+ return;
+
+ GraphicsLayer::setPosition(p);
+ m_layerState.positionChanged = true;
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
+{
+ if (anchorPoint() == p)
+ return;
+
+ GraphicsLayer::setAnchorPoint(p);
+ m_layerState.anchorPointChanged = true;
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setSize(const FloatSize& size)
+{
+ if (this->size() == size)
+ return;
+
+ GraphicsLayer::setSize(size);
+ m_layerState.sizeChanged = true;
+
+ if (maskLayer())
+ maskLayer()->setSize(size);
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setTransform(const TransformationMatrix& t)
+{
+ if (transform() == t)
+ return;
+
+ GraphicsLayer::setTransform(t);
+ m_layerState.transformChanged = true;
+
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setChildrenTransform(const TransformationMatrix& t)
+{
+ if (childrenTransform() == t)
+ return;
+
+ GraphicsLayer::setChildrenTransform(t);
+ m_layerState.childrenTransformChanged = true;
+
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setPreserves3D(bool b)
+{
+ if (preserves3D() == b)
+ return;
+
+ GraphicsLayer::setPreserves3D(b);
+ m_layerState.preserves3D = b;
+ m_layerState.flagsChanged = true;
+
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setMasksToBounds(bool b)
+{
+ if (masksToBounds() == b)
+ return;
+ GraphicsLayer::setMasksToBounds(b);
+ m_layerState.masksToBounds = b;
+ m_layerState.flagsChanged = true;
+
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setDrawsContent(bool b)
+{
+ if (drawsContent() == b)
+ return;
+ GraphicsLayer::setDrawsContent(b);
+ m_layerState.drawsContent = b;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsVisible(bool b)
+{
+ if (contentsAreVisible() == b)
+ return;
+ GraphicsLayer::setContentsVisible(b);
+ m_layerState.contentsVisible = b;
+ m_layerState.flagsChanged = true;
+
+ if (maskLayer())
+ maskLayer()->setContentsVisible(b);
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsOpaque(bool b)
+{
+ if (contentsOpaque() == b)
+ return;
+ if (m_mainBackingStore)
+ m_mainBackingStore->setSupportsAlpha(!b);
+ GraphicsLayer::setContentsOpaque(b);
+ m_layerState.contentsOpaque = b;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setBackfaceVisibility(bool b)
+{
+ if (backfaceVisibility() == b)
+ return;
+
+ GraphicsLayer::setBackfaceVisibility(b);
+ m_layerState.backfaceVisible = b;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setOpacity(float opacity)
+{
+ if (this->opacity() == opacity)
+ return;
+
+ GraphicsLayer::setOpacity(opacity);
+ m_layerState.opacity = opacity;
+ m_layerState.opacityChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsRect(const FloatRect& r)
+{
+ if (contentsRect() == r)
+ return;
+
+ GraphicsLayer::setContentsRect(r);
+ m_layerState.contentsRect = r;
+ m_layerState.contentsRectChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsTileSize(const FloatSize& s)
+{
+ if (contentsTileSize() == s)
+ return;
+
+ GraphicsLayer::setContentsTileSize(s);
+ m_layerState.contentsTileSize = s;
+ m_layerState.contentsTilingChanged = true;
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsTilePhase(const FloatSize& p)
+{
+ if (contentsTilePhase() == p)
+ return;
+
+ GraphicsLayer::setContentsTilePhase(p);
+ m_layerState.contentsTilePhase = p;
+ m_layerState.contentsTilingChanged = true;
+ didChangeLayerState();
+}
+
+bool GraphicsLayer::supportsContentsTiling()
+{
+ return true;
+}
+
+void CoordinatedGraphicsLayer::setContentsNeedsDisplay()
+{
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ if (m_platformLayer)
+ m_shouldUpdatePlatformLayer = true;
+#endif
+
+ notifyFlushRequired();
+ addRepaintRect(contentsRect());
+}
+
+void CoordinatedGraphicsLayer::setContentsToPlatformLayer(PlatformLayer* platformLayer, ContentsLayerPurpose)
+{
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ if (m_platformLayer != platformLayer)
+ m_shouldSyncPlatformLayer = true;
+
+ m_platformLayer = platformLayer;
+ notifyFlushRequired();
+#else
+ UNUSED_PARAM(platformLayer);
+#endif
+}
+
+bool CoordinatedGraphicsLayer::filtersCanBeComposited(const FilterOperations& filters) const
+{
+ if (!filters.size())
+ return false;
+
+ for (const auto& filterOperation : filters.operations()) {
+ if (filterOperation->type() == FilterOperation::REFERENCE)
+ return false;
+ }
+
+ return true;
+}
+
+bool CoordinatedGraphicsLayer::setFilters(const FilterOperations& newFilters)
+{
+ bool canCompositeFilters = filtersCanBeComposited(newFilters);
+ if (filters() == newFilters)
+ return canCompositeFilters;
+
+ if (canCompositeFilters) {
+ if (!GraphicsLayer::setFilters(newFilters))
+ return false;
+ didChangeFilters();
+ } else if (filters().size()) {
+ clearFilters();
+ didChangeFilters();
+ }
+
+ return canCompositeFilters;
+}
+
+void CoordinatedGraphicsLayer::setContentsToSolidColor(const Color& color)
+{
+ if (m_layerState.solidColor == color)
+ return;
+
+ m_layerState.solidColor = color;
+ m_layerState.solidColorChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setShowDebugBorder(bool show)
+{
+ if (isShowingDebugBorder() == show)
+ return;
+
+ GraphicsLayer::setShowDebugBorder(show);
+ m_layerState.showDebugBorders = true;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setShowRepaintCounter(bool show)
+{
+ if (isShowingRepaintCounter() == show)
+ return;
+
+ GraphicsLayer::setShowRepaintCounter(show);
+ m_layerState.showRepaintCounter = true;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsToImage(Image* image)
+{
+ NativeImagePtr nativeImagePtr = image ? image->nativeImageForCurrentFrame() : nullptr;
+ if (m_compositedImage == image && m_compositedNativeImagePtr == nativeImagePtr)
+ return;
+
+ m_compositedImage = image;
+ m_compositedNativeImagePtr = nativeImagePtr;
+
+ GraphicsLayer::setContentsToImage(image);
+ didChangeImageBacking();
+}
+
+void CoordinatedGraphicsLayer::setMaskLayer(GraphicsLayer* layer)
+{
+ if (layer == maskLayer())
+ return;
+
+ GraphicsLayer::setMaskLayer(layer);
+
+ if (!layer)
+ return;
+
+ layer->setSize(size());
+ layer->setContentsVisible(contentsAreVisible());
+ auto& coordinatedLayer = downcast<CoordinatedGraphicsLayer>(*layer);
+ coordinatedLayer.didChangeLayerState();
+
+ m_layerState.mask = coordinatedLayer.id();
+ m_layerState.maskChanged = true;
+
+ didChangeLayerState();
+}
+
+bool CoordinatedGraphicsLayer::shouldDirectlyCompositeImage(Image* image) const
+{
+ if (!image || !image->isBitmapImage())
+ return false;
+
+ enum { MaxDimenstionForDirectCompositing = 2000 };
+ if (image->width() > MaxDimenstionForDirectCompositing || image->height() > MaxDimenstionForDirectCompositing)
+ return false;
+
+ return true;
+}
+
+void CoordinatedGraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
+{
+ if (layer == replicaLayer())
+ return;
+
+ GraphicsLayer::setReplicatedByLayer(layer);
+ m_layerState.replica = toCoordinatedLayerID(layer);
+ m_layerState.replicaChanged = true;
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setNeedsDisplay()
+{
+ setNeedsDisplayInRect(FloatRect(FloatPoint(), size()));
+}
+
+void CoordinatedGraphicsLayer::setNeedsDisplayInRect(const FloatRect& rect, ShouldClipToLayer)
+{
+ if (m_mainBackingStore)
+ m_mainBackingStore->invalidate(IntRect(rect));
+
+ didChangeLayerState();
+
+ addRepaintRect(rect);
+}
+
+void CoordinatedGraphicsLayer::setScrollableArea(ScrollableArea* scrollableArea)
+{
+ bool oldScrollable = isScrollable();
+ m_scrollableArea = scrollableArea;
+ if (oldScrollable == isScrollable())
+ return;
+
+ m_layerState.isScrollable = isScrollable();
+ m_layerState.flagsChanged = true;
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::commitScrollOffset(const IntSize& offset)
+{
+ if (!isScrollable() || offset.isZero())
+ return;
+
+ m_scrollableArea->notifyScrollPositionChanged(m_scrollableArea->scrollPosition() + offset);
+ m_layerState.committedScrollOffset += offset;
+ m_layerState.committedScrollOffsetChanged = true;
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setFixedToViewport(bool isFixed)
+{
+ if (m_fixedToViewport == isFixed)
+ return;
+
+ m_fixedToViewport = isFixed;
+ m_layerState.fixedToViewport = isFixed;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::flushCompositingState(const FloatRect& rect)
+{
+ if (CoordinatedGraphicsLayer* mask = downcast<CoordinatedGraphicsLayer>(maskLayer()))
+ mask->flushCompositingStateForThisLayerOnly();
+
+ if (CoordinatedGraphicsLayer* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer()))
+ replica->flushCompositingStateForThisLayerOnly();
+
+ flushCompositingStateForThisLayerOnly();
+
+ for (auto& child : children())
+ child->flushCompositingState(rect);
+}
+
+void CoordinatedGraphicsLayer::syncChildren()
+{
+ if (!m_shouldSyncChildren)
+ return;
+ m_shouldSyncChildren = false;
+ m_layerState.childrenChanged = true;
+ m_layerState.children.clear();
+ for (auto& child : children())
+ m_layerState.children.append(toCoordinatedLayerID(child));
+}
+
+void CoordinatedGraphicsLayer::syncFilters()
+{
+ if (!m_shouldSyncFilters)
+ return;
+ m_shouldSyncFilters = false;
+
+ m_layerState.filters = GraphicsLayer::filters();
+ m_layerState.filtersChanged = true;
+}
+
+void CoordinatedGraphicsLayer::syncImageBacking()
+{
+ if (!m_shouldSyncImageBacking)
+ return;
+ m_shouldSyncImageBacking = false;
+
+ if (m_compositedNativeImagePtr) {
+ ASSERT(!shouldHaveBackingStore());
+ ASSERT(m_compositedImage);
+
+ bool imageInstanceReplaced = m_coordinatedImageBacking && (m_coordinatedImageBacking->id() != CoordinatedImageBacking::getCoordinatedImageBackingID(m_compositedImage.get()));
+ if (imageInstanceReplaced)
+ releaseImageBackingIfNeeded();
+
+ if (!m_coordinatedImageBacking) {
+ m_coordinatedImageBacking = m_coordinator->createImageBackingIfNeeded(m_compositedImage.get());
+ m_coordinatedImageBacking->addHost(this);
+ m_layerState.imageID = m_coordinatedImageBacking->id();
+ }
+
+ m_coordinatedImageBacking->markDirty();
+ m_layerState.imageChanged = true;
+ } else
+ releaseImageBackingIfNeeded();
+}
+
+void CoordinatedGraphicsLayer::syncLayerState()
+{
+ if (!m_shouldSyncLayerState)
+ return;
+ m_shouldSyncLayerState = false;
+
+ m_layerState.childrenTransform = childrenTransform();
+ m_layerState.contentsRect = contentsRect();
+ m_layerState.mask = toCoordinatedLayerID(maskLayer());
+ m_layerState.opacity = opacity();
+ m_layerState.replica = toCoordinatedLayerID(replicaLayer());
+ m_layerState.transform = transform();
+
+ m_layerState.anchorPoint = m_adjustedAnchorPoint;
+ m_layerState.pos = m_adjustedPosition;
+ m_layerState.size = m_adjustedSize;
+
+ if (m_layerState.flagsChanged) {
+ m_layerState.contentsOpaque = contentsOpaque();
+ m_layerState.drawsContent = drawsContent();
+ m_layerState.contentsVisible = contentsAreVisible();
+ m_layerState.backfaceVisible = backfaceVisibility();
+ m_layerState.masksToBounds = masksToBounds();
+ m_layerState.preserves3D = preserves3D();
+ m_layerState.fixedToViewport = fixedToViewport();
+ m_layerState.showDebugBorders = isShowingDebugBorder();
+ m_layerState.showRepaintCounter = isShowingRepaintCounter();
+ m_layerState.isScrollable = isScrollable();
+ }
+
+ if (m_layerState.showDebugBorders)
+ updateDebugIndicators();
+}
+
+void CoordinatedGraphicsLayer::setDebugBorder(const Color& color, float width)
+{
+ ASSERT(m_layerState.showDebugBorders);
+ if (m_layerState.debugBorderColor != color) {
+ m_layerState.debugBorderColor = color;
+ m_layerState.debugBorderColorChanged = true;
+ }
+
+ if (m_layerState.debugBorderWidth != width) {
+ m_layerState.debugBorderWidth = width;
+ m_layerState.debugBorderWidthChanged = true;
+ }
+}
+
+void CoordinatedGraphicsLayer::syncAnimations()
+{
+ if (!m_shouldSyncAnimations)
+ return;
+
+ m_shouldSyncAnimations = false;
+ m_layerState.animations = m_animations.getActiveAnimations();
+ m_layerState.animationsChanged = true;
+}
+
+void CoordinatedGraphicsLayer::syncPlatformLayer()
+{
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ if (!m_shouldSyncPlatformLayer)
+ return;
+
+ m_shouldSyncPlatformLayer = false;
+ m_layerState.platformLayerChanged = true;
+ if (m_platformLayer)
+ m_layerState.platformLayerProxy = m_platformLayer->proxy();
+#endif
+}
+
+void CoordinatedGraphicsLayer::updatePlatformLayer()
+{
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ if (!m_shouldUpdatePlatformLayer)
+ return;
+
+ m_shouldUpdatePlatformLayer = false;
+ if (m_platformLayer)
+ m_platformLayer->swapBuffersIfNeeded();
+#endif
+}
+
+void CoordinatedGraphicsLayer::flushCompositingStateForThisLayerOnly()
+{
+ // When we have a transform animation, we need to update visible rect every frame to adjust the visible rect of a backing store.
+ bool hasActiveTransformAnimation = selfOrAncestorHasActiveTransformAnimation();
+ if (hasActiveTransformAnimation)
+ m_movingVisibleRect = true;
+
+ // Sets the values.
+ computePixelAlignment(m_adjustedPosition, m_adjustedSize, m_adjustedAnchorPoint, m_pixelAlignmentOffset);
+
+ syncImageBacking();
+ syncLayerState();
+ syncAnimations();
+ computeTransformedVisibleRect();
+ syncChildren();
+ syncFilters();
+ syncPlatformLayer();
+ updatePlatformLayer();
+
+ // Only unset m_movingVisibleRect after we have updated the visible rect after the animation stopped.
+ if (!hasActiveTransformAnimation)
+ m_movingVisibleRect = false;
+}
+
+void CoordinatedGraphicsLayer::syncPendingStateChangesIncludingSubLayers()
+{
+ if (m_layerState.hasPendingChanges()) {
+ m_coordinator->syncLayerState(m_id, m_layerState);
+ resetLayerState();
+ }
+
+ if (maskLayer())
+ downcast<CoordinatedGraphicsLayer>(*maskLayer()).syncPendingStateChangesIncludingSubLayers();
+
+ for (auto& child : children())
+ downcast<CoordinatedGraphicsLayer>(*child).syncPendingStateChangesIncludingSubLayers();
+}
+
+void CoordinatedGraphicsLayer::resetLayerState()
+{
+ m_layerState.changeMask = 0;
+ m_layerState.tilesToCreate.clear();
+ m_layerState.tilesToRemove.clear();
+ m_layerState.tilesToUpdate.clear();
+ m_layerState.committedScrollOffset = IntSize();
+}
+
+bool CoordinatedGraphicsLayer::imageBackingVisible()
+{
+ ASSERT(m_coordinatedImageBacking);
+ return transformedVisibleRect().intersects(IntRect(contentsRect()));
+}
+
+void CoordinatedGraphicsLayer::releaseImageBackingIfNeeded()
+{
+ if (!m_coordinatedImageBacking)
+ return;
+
+ ASSERT(m_coordinator);
+ m_coordinatedImageBacking->removeHost(this);
+ m_coordinatedImageBacking = nullptr;
+ m_layerState.imageID = InvalidCoordinatedImageBackingID;
+ m_layerState.imageChanged = true;
+}
+
+CoordinatedGraphicsLayer* CoordinatedGraphicsLayer::findFirstDescendantWithContentsRecursively()
+{
+ if (shouldHaveBackingStore())
+ return this;
+
+ for (auto& child : children()) {
+ if (CoordinatedGraphicsLayer* layer = downcast<CoordinatedGraphicsLayer>(*child).findFirstDescendantWithContentsRecursively())
+ return layer;
+ }
+
+ return nullptr;
+}
+
+void CoordinatedGraphicsLayer::setVisibleContentRectTrajectoryVector(const FloatPoint& trajectoryVector)
+{
+ if (!m_mainBackingStore)
+ return;
+
+ m_mainBackingStore->setTrajectoryVector(trajectoryVector);
+ setNeedsVisibleRectAdjustment();
+}
+
+void CoordinatedGraphicsLayer::deviceOrPageScaleFactorChanged()
+{
+ if (shouldHaveBackingStore())
+ m_pendingContentsScaleAdjustment = true;
+}
+
+float CoordinatedGraphicsLayer::effectiveContentsScale()
+{
+ return selfOrAncestorHaveNonAffineTransforms() ? 1 : deviceScaleFactor() * pageScaleFactor();
+}
+
+void CoordinatedGraphicsLayer::adjustContentsScale()
+{
+ ASSERT(shouldHaveBackingStore());
+ if (!m_mainBackingStore || m_mainBackingStore->contentsScale() == effectiveContentsScale())
+ return;
+
+ // Between creating the new backing store and painting the content,
+ // we do not want to drop the previous one as that might result in
+ // briefly seeing flickering as the old tiles may be dropped before
+ // something replaces them.
+ m_previousBackingStore = WTFMove(m_mainBackingStore);
+
+ // No reason to save the previous backing store for non-visible areas.
+ m_previousBackingStore->removeAllNonVisibleTiles(transformedVisibleRect(), IntRect(0, 0, size().width(), size().height()));
+}
+
+void CoordinatedGraphicsLayer::createBackingStore()
+{
+ m_mainBackingStore = std::make_unique<TiledBackingStore>(this, effectiveContentsScale());
+ m_mainBackingStore->setSupportsAlpha(!contentsOpaque());
+}
+
+void CoordinatedGraphicsLayer::tiledBackingStorePaint(GraphicsContext& context, const IntRect& rect)
+{
+ if (rect.isEmpty())
+ return;
+ paintGraphicsLayerContents(context, rect);
+}
+
+void CoordinatedGraphicsLayer::didUpdateTileBuffers()
+{
+ if (!isShowingRepaintCounter())
+ return;
+
+ m_layerState.repaintCount = incrementRepaintCount();
+ m_layerState.repaintCountChanged = true;
+}
+
+void CoordinatedGraphicsLayer::tiledBackingStoreHasPendingTileCreation()
+{
+ setNeedsVisibleRectAdjustment();
+ notifyFlushRequired();
+}
+
+static void clampToContentsRectIfRectIsInfinite(FloatRect& rect, const FloatSize& contentsSize)
+{
+ if (rect.width() >= LayoutUnit::nearlyMax() || rect.width() <= LayoutUnit::nearlyMin()) {
+ rect.setX(0);
+ rect.setWidth(contentsSize.width());
+ }
+
+ if (rect.height() >= LayoutUnit::nearlyMax() || rect.height() <= LayoutUnit::nearlyMin()) {
+ rect.setY(0);
+ rect.setHeight(contentsSize.height());
+ }
+}
+
+IntRect CoordinatedGraphicsLayer::transformedVisibleRect()
+{
+ // Non-invertible layers are not visible.
+ if (!m_layerTransform.combined().isInvertible())
+ return IntRect();
+
+ // Return a projection of the visible rect (surface coordinates) onto the layer's plane (layer coordinates).
+ // The resulting quad might be squewed and the visible rect is the bounding box of this quad,
+ // so it might spread further than the real visible area (and then even more amplified by the cover rect multiplier).
+ ASSERT(m_cachedInverseTransform == m_layerTransform.combined().inverse().value_or(TransformationMatrix()));
+ FloatRect rect = m_cachedInverseTransform.clampedBoundsOfProjectedQuad(FloatQuad(m_coordinator->visibleContentsRect()));
+ clampToContentsRectIfRectIsInfinite(rect, size());
+ return enclosingIntRect(rect);
+}
+
+bool CoordinatedGraphicsLayer::paintToSurface(const IntSize& size, uint32_t& atlas, IntPoint& offset, CoordinatedSurface::Client& client)
+{
+ ASSERT(m_coordinator);
+ ASSERT(m_coordinator->isFlushingLayerChanges());
+ return m_coordinator->paintToSurface(size, contentsOpaque() ? CoordinatedSurface::NoFlags : CoordinatedSurface::SupportsAlpha, atlas, offset, client);
+}
+
+void CoordinatedGraphicsLayer::createTile(uint32_t tileID, float scaleFactor)
+{
+ ASSERT(m_coordinator);
+ ASSERT(m_coordinator->isFlushingLayerChanges());
+
+ TileCreationInfo creationInfo;
+ creationInfo.tileID = tileID;
+ creationInfo.scale = scaleFactor;
+ m_layerState.tilesToCreate.append(creationInfo);
+}
+
+void CoordinatedGraphicsLayer::updateTile(uint32_t tileID, const SurfaceUpdateInfo& updateInfo, const IntRect& tileRect)
+{
+ ASSERT(m_coordinator);
+ ASSERT(m_coordinator->isFlushingLayerChanges());
+
+ TileUpdateInfo tileUpdateInfo;
+ tileUpdateInfo.tileID = tileID;
+ tileUpdateInfo.tileRect = tileRect;
+ tileUpdateInfo.updateInfo = updateInfo;
+ m_layerState.tilesToUpdate.append(tileUpdateInfo);
+}
+
+void CoordinatedGraphicsLayer::removeTile(uint32_t tileID)
+{
+ ASSERT(m_coordinator);
+ ASSERT(m_coordinator->isFlushingLayerChanges() || m_isPurging);
+ m_layerState.tilesToRemove.append(tileID);
+}
+
+void CoordinatedGraphicsLayer::updateContentBuffersIncludingSubLayers()
+{
+ if (CoordinatedGraphicsLayer* mask = downcast<CoordinatedGraphicsLayer>(maskLayer()))
+ mask->updateContentBuffers();
+
+ if (CoordinatedGraphicsLayer* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer()))
+ replica->updateContentBuffers();
+
+ updateContentBuffers();
+
+ for (auto& child : children())
+ downcast<CoordinatedGraphicsLayer>(*child).updateContentBuffersIncludingSubLayers();
+}
+
+void CoordinatedGraphicsLayer::updateContentBuffers()
+{
+ if (!shouldHaveBackingStore()) {
+ m_mainBackingStore = nullptr;
+ m_previousBackingStore = nullptr;
+ return;
+ }
+
+ if (m_pendingContentsScaleAdjustment) {
+ adjustContentsScale();
+ m_pendingContentsScaleAdjustment = false;
+ }
+
+ // This is the only place we (re)create the main tiled backing store, once we
+ // have a remote client and we are ready to send our data to the UI process.
+ if (!m_mainBackingStore) {
+ createBackingStore();
+ m_pendingVisibleRectAdjustment = true;
+ }
+
+ if (m_pendingVisibleRectAdjustment) {
+ m_pendingVisibleRectAdjustment = false;
+ m_mainBackingStore->createTilesIfNeeded(transformedVisibleRect(), IntRect(0, 0, size().width(), size().height()));
+ }
+
+ m_mainBackingStore->updateTileBuffers();
+
+ // The previous backing store is kept around to avoid flickering between
+ // removing the existing tiles and painting the new ones. The first time
+ // the visibleRect is full painted we remove the previous backing store.
+ if (m_mainBackingStore->visibleAreaIsCovered())
+ m_previousBackingStore = nullptr;
+}
+
+void CoordinatedGraphicsLayer::purgeBackingStores()
+{
+#ifndef NDEBUG
+ SetForScope<bool> updateModeProtector(m_isPurging, true);
+#endif
+ m_mainBackingStore = nullptr;
+ m_previousBackingStore = nullptr;
+
+ releaseImageBackingIfNeeded();
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setCoordinator(CoordinatedGraphicsLayerClient* coordinator)
+{
+ m_coordinator = coordinator;
+}
+
+void CoordinatedGraphicsLayer::setNeedsVisibleRectAdjustment()
+{
+ if (shouldHaveBackingStore())
+ m_pendingVisibleRectAdjustment = true;
+}
+
+static inline bool isIntegral(float value)
+{
+ return static_cast<int>(value) == value;
+}
+
+FloatPoint CoordinatedGraphicsLayer::computePositionRelativeToBase()
+{
+ FloatPoint offset;
+ for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent())
+ offset += currLayer->position();
+
+ return offset;
+}
+
+void CoordinatedGraphicsLayer::computePixelAlignment(FloatPoint& position, FloatSize& size, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset)
+{
+ if (isIntegral(effectiveContentsScale())) {
+ position = m_position;
+ size = m_size;
+ anchorPoint = m_anchorPoint;
+ alignmentOffset = FloatSize();
+ return;
+ }
+
+ FloatPoint positionRelativeToBase = computePositionRelativeToBase();
+
+ FloatRect baseRelativeBounds(positionRelativeToBase, m_size);
+ FloatRect scaledBounds = baseRelativeBounds;
+
+ // Scale by the effective scale factor to compute the screen-relative bounds.
+ scaledBounds.scale(effectiveContentsScale());
+
+ // Round to integer boundaries.
+ // NOTE: When using enclosingIntRect (as mac) it will have different sizes depending on position.
+ FloatRect alignedBounds = enclosingIntRect(scaledBounds);
+
+ // Convert back to layer coordinates.
+ alignedBounds.scale(1 / effectiveContentsScale());
+
+ // Convert back to layer coordinates.
+ alignmentOffset = baseRelativeBounds.location() - alignedBounds.location();
+
+ position = m_position - alignmentOffset;
+ size = alignedBounds.size();
+
+ // Now we have to compute a new anchor point which compensates for rounding.
+ float anchorPointX = m_anchorPoint.x();
+ float anchorPointY = m_anchorPoint.y();
+
+ if (alignedBounds.width())
+ anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width();
+
+ if (alignedBounds.height())
+ anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height();
+
+ anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * effectiveContentsScale());
+}
+
+void CoordinatedGraphicsLayer::computeTransformedVisibleRect()
+{
+ if (!m_shouldUpdateVisibleRect && !m_movingVisibleRect)
+ return;
+
+ m_shouldUpdateVisibleRect = false;
+ TransformationMatrix currentTransform = transform();
+ if (m_movingVisibleRect)
+ client().getCurrentTransform(this, currentTransform);
+ m_layerTransform.setLocalTransform(currentTransform);
+
+ m_layerTransform.setAnchorPoint(m_adjustedAnchorPoint);
+ m_layerTransform.setPosition(m_adjustedPosition);
+ m_layerTransform.setSize(m_adjustedSize);
+
+ m_layerTransform.setFlattening(!preserves3D());
+ m_layerTransform.setChildrenTransform(childrenTransform());
+ m_layerTransform.combineTransforms(parent() ? downcast<CoordinatedGraphicsLayer>(*parent()).m_layerTransform.combinedForChildren() : TransformationMatrix());
+
+ m_cachedInverseTransform = m_layerTransform.combined().inverse().value_or(TransformationMatrix());
+
+ // The combined transform will be used in tiledBackingStoreVisibleRect.
+ setNeedsVisibleRectAdjustment();
+}
+
+bool CoordinatedGraphicsLayer::shouldHaveBackingStore() const
+{
+ return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
+}
+
+bool CoordinatedGraphicsLayer::selfOrAncestorHasActiveTransformAnimation() const
+{
+ if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyTransform))
+ return true;
+
+ if (!parent())
+ return false;
+
+ return downcast<CoordinatedGraphicsLayer>(*parent()).selfOrAncestorHasActiveTransformAnimation();
+}
+
+bool CoordinatedGraphicsLayer::selfOrAncestorHaveNonAffineTransforms()
+{
+ if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyTransform))
+ return true;
+
+ if (!m_layerTransform.combined().isAffine())
+ return true;
+
+ if (!parent())
+ return false;
+
+ return downcast<CoordinatedGraphicsLayer>(*parent()).selfOrAncestorHaveNonAffineTransforms();
+}
+
+bool CoordinatedGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double delayAsNegativeTimeOffset)
+{
+ ASSERT(!keyframesName.isEmpty());
+
+ if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity && valueList.property() != AnimatedPropertyFilter))
+ return false;
+
+ if (valueList.property() == AnimatedPropertyFilter) {
+ int listIndex = validateFilterOperations(valueList);
+ if (listIndex < 0)
+ return false;
+
+ const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
+ if (!filtersCanBeComposited(filters))
+ return false;
+ }
+
+ bool listsMatch = false;
+ bool ignoredHasBigRotation;
+
+ if (valueList.property() == AnimatedPropertyTransform)
+ listsMatch = validateTransformOperations(valueList, ignoredHasBigRotation) >= 0;
+
+ m_lastAnimationStartTime = monotonicallyIncreasingTime() - delayAsNegativeTimeOffset;
+ m_animations.add(TextureMapperAnimation(keyframesName, valueList, boxSize, *anim, listsMatch, m_lastAnimationStartTime, 0, TextureMapperAnimation::AnimationState::Playing));
+ m_animationStartedTimer.startOneShot(0);
+ didChangeAnimations();
+ return true;
+}
+
+void CoordinatedGraphicsLayer::pauseAnimation(const String& animationName, double time)
+{
+ m_animations.pause(animationName, time);
+ didChangeAnimations();
+}
+
+void CoordinatedGraphicsLayer::removeAnimation(const String& animationName)
+{
+ m_animations.remove(animationName);
+ didChangeAnimations();
+}
+
+void CoordinatedGraphicsLayer::suspendAnimations(double time)
+{
+ m_animations.suspend(time);
+ didChangeAnimations();
+}
+
+void CoordinatedGraphicsLayer::resumeAnimations()
+{
+ m_animations.resume();
+ didChangeAnimations();
+}
+
+void CoordinatedGraphicsLayer::animationStartedTimerFired()
+{
+ client().notifyAnimationStarted(this, "", m_lastAnimationStartTime);
+}
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+void CoordinatedGraphicsLayer::platformLayerWillBeDestroyed()
+{
+}
+
+void CoordinatedGraphicsLayer::setPlatformLayerNeedsDisplay()
+{
+}
+#endif
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.h
new file mode 100644
index 000000000..bf25111db
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.h
@@ -0,0 +1,246 @@
+/*
+ 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 CoordinatedGraphicsLayer_h
+#define CoordinatedGraphicsLayer_h
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "CoordinatedGraphicsState.h"
+#include "CoordinatedImageBacking.h"
+#include "FloatPoint3D.h"
+#include "GraphicsLayer.h"
+#include "GraphicsLayerTransform.h"
+#include "Image.h"
+#include "IntSize.h"
+#include "TextureMapperAnimation.h"
+#include "TextureMapperPlatformLayer.h"
+#include "TiledBackingStore.h"
+#include "TiledBackingStoreClient.h"
+#include "TransformationMatrix.h"
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+class CoordinatedGraphicsLayer;
+class TextureMapperAnimations;
+class ScrollableArea;
+
+class CoordinatedGraphicsLayerClient {
+public:
+ virtual bool isFlushingLayerChanges() const = 0;
+ virtual FloatRect visibleContentsRect() const = 0;
+ virtual Ref<CoordinatedImageBacking> createImageBackingIfNeeded(Image*) = 0;
+ virtual void detachLayer(CoordinatedGraphicsLayer*) = 0;
+ virtual bool paintToSurface(const IntSize&, CoordinatedSurface::Flags, uint32_t& atlasID, IntPoint&, CoordinatedSurface::Client&) = 0;
+
+ virtual void syncLayerState(CoordinatedLayerID, CoordinatedGraphicsLayerState&) = 0;
+};
+
+class CoordinatedGraphicsLayer : public GraphicsLayer
+ , public TiledBackingStoreClient
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ , public TextureMapperPlatformLayer::Client
+#endif
+ , public CoordinatedImageBacking::Host {
+public:
+ explicit CoordinatedGraphicsLayer(Type, GraphicsLayerClient&);
+ virtual ~CoordinatedGraphicsLayer();
+
+ PlatformLayerID primaryLayerID() const override { return id(); }
+
+ // Reimplementations from GraphicsLayer.h.
+ bool setChildren(const Vector<GraphicsLayer*>&) override;
+ void addChild(GraphicsLayer*) override;
+ void addChildAtIndex(GraphicsLayer*, int) override;
+ void addChildAbove(GraphicsLayer*, GraphicsLayer*) override;
+ void addChildBelow(GraphicsLayer*, GraphicsLayer*) override;
+ bool replaceChild(GraphicsLayer*, GraphicsLayer*) override;
+ void removeFromParent() override;
+ void setPosition(const FloatPoint&) override;
+ void setAnchorPoint(const FloatPoint3D&) override;
+ void setSize(const FloatSize&) override;
+ void setTransform(const TransformationMatrix&) override;
+ void setChildrenTransform(const TransformationMatrix&) override;
+ void setPreserves3D(bool) override;
+ void setMasksToBounds(bool) override;
+ void setDrawsContent(bool) override;
+ void setContentsVisible(bool) override;
+ void setContentsOpaque(bool) override;
+ void setBackfaceVisibility(bool) override;
+ void setOpacity(float) override;
+ void setContentsRect(const FloatRect&) override;
+ void setContentsTilePhase(const FloatSize&) override;
+ void setContentsTileSize(const FloatSize&) override;
+ void setContentsToImage(Image*) override;
+ void setContentsToSolidColor(const Color&) override;
+ void setShowDebugBorder(bool) override;
+ void setShowRepaintCounter(bool) override;
+ bool shouldDirectlyCompositeImage(Image*) const override;
+ void setContentsToPlatformLayer(PlatformLayer*, ContentsLayerPurpose) override;
+ void setMaskLayer(GraphicsLayer*) override;
+ void setReplicatedByLayer(GraphicsLayer*) override;
+ void setNeedsDisplay() override;
+ void setNeedsDisplayInRect(const FloatRect&, ShouldClipToLayer = ClipToLayer) override;
+ void setContentsNeedsDisplay() override;
+ void deviceOrPageScaleFactorChanged() override;
+ void flushCompositingState(const FloatRect&) override;
+ void flushCompositingStateForThisLayerOnly() override;
+ bool setFilters(const FilterOperations&) override;
+ bool addAnimation(const KeyframeValueList&, const FloatSize&, const Animation*, const String&, double) override;
+ void pauseAnimation(const String&, double) override;
+ void removeAnimation(const String&) override;
+ void suspendAnimations(double time) override;
+ void resumeAnimations() override;
+ bool usesContentsLayer() const override { return m_platformLayer || m_compositedImage; }
+
+ void syncPendingStateChangesIncludingSubLayers();
+ void updateContentBuffersIncludingSubLayers();
+
+ FloatPoint computePositionRelativeToBase();
+ void computePixelAlignment(FloatPoint& position, FloatSize&, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset);
+
+ void setVisibleContentRectTrajectoryVector(const FloatPoint&);
+
+ void setScrollableArea(ScrollableArea*);
+ bool isScrollable() const { return !!m_scrollableArea; }
+ void commitScrollOffset(const IntSize&);
+
+ CoordinatedLayerID id() const { return m_id; }
+
+ void setFixedToViewport(bool isFixed);
+
+ IntRect coverRect() const { return m_mainBackingStore ? m_mainBackingStore->mapToContents(m_mainBackingStore->coverRect()) : IntRect(); }
+ IntRect transformedVisibleRect();
+
+ // TiledBackingStoreClient
+ void tiledBackingStorePaint(GraphicsContext&, const IntRect&) override;
+ void didUpdateTileBuffers() override;
+ void tiledBackingStoreHasPendingTileCreation() override;
+ void createTile(uint32_t tileID, float) override;
+ void updateTile(uint32_t tileID, const SurfaceUpdateInfo&, const IntRect&) override;
+ void removeTile(uint32_t tileID) override;
+ bool paintToSurface(const IntSize&, uint32_t& /* atlasID */, IntPoint&, CoordinatedSurface::Client&) override;
+
+ void setCoordinator(CoordinatedGraphicsLayerClient*);
+
+ void setNeedsVisibleRectAdjustment();
+ void purgeBackingStores();
+
+ CoordinatedGraphicsLayer* findFirstDescendantWithContentsRecursively();
+
+private:
+ bool isCoordinatedGraphicsLayer() const override { return true; }
+
+ void syncPlatformLayer();
+ void updatePlatformLayer();
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ void platformLayerWillBeDestroyed() override;
+ void setPlatformLayerNeedsDisplay() override;
+#endif
+
+ void setDebugBorder(const Color&, float width) override;
+
+ bool fixedToViewport() const { return m_fixedToViewport; }
+
+ void didChangeLayerState();
+ void didChangeAnimations();
+ void didChangeGeometry();
+ void didChangeChildren();
+ void didChangeFilters();
+ void didChangeImageBacking();
+
+ void resetLayerState();
+ void syncLayerState();
+ void syncAnimations();
+ void syncChildren();
+ void syncFilters();
+ void syncImageBacking();
+ void computeTransformedVisibleRect();
+ void updateContentBuffers();
+
+ void createBackingStore();
+ void releaseImageBackingIfNeeded();
+
+ void notifyFlushRequired();
+
+ // CoordinatedImageBacking::Host
+ bool imageBackingVisible() override;
+ bool shouldHaveBackingStore() const;
+ bool selfOrAncestorHasActiveTransformAnimation() const;
+ bool selfOrAncestorHaveNonAffineTransforms();
+ void adjustContentsScale();
+
+ void setShouldUpdateVisibleRect();
+ float effectiveContentsScale();
+
+ void animationStartedTimerFired();
+
+ bool filtersCanBeComposited(const FilterOperations&) const;
+
+ CoordinatedLayerID m_id;
+ CoordinatedGraphicsLayerState m_layerState;
+ GraphicsLayerTransform m_layerTransform;
+ TransformationMatrix m_cachedInverseTransform;
+ FloatSize m_pixelAlignmentOffset;
+ FloatSize m_adjustedSize;
+ FloatPoint m_adjustedPosition;
+ FloatPoint3D m_adjustedAnchorPoint;
+
+#ifndef NDEBUG
+ bool m_isPurging;
+#endif
+ bool m_shouldUpdateVisibleRect: 1;
+ bool m_shouldSyncLayerState: 1;
+ bool m_shouldSyncChildren: 1;
+ bool m_shouldSyncFilters: 1;
+ bool m_shouldSyncImageBacking: 1;
+ bool m_shouldSyncAnimations: 1;
+ bool m_fixedToViewport : 1;
+ bool m_movingVisibleRect : 1;
+ bool m_pendingContentsScaleAdjustment : 1;
+ bool m_pendingVisibleRectAdjustment : 1;
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ bool m_shouldSyncPlatformLayer : 1;
+ bool m_shouldUpdatePlatformLayer : 1;
+#endif
+
+ CoordinatedGraphicsLayerClient* m_coordinator;
+ std::unique_ptr<TiledBackingStore> m_mainBackingStore;
+ std::unique_ptr<TiledBackingStore> m_previousBackingStore;
+
+ RefPtr<Image> m_compositedImage;
+ NativeImagePtr m_compositedNativeImagePtr;
+ RefPtr<CoordinatedImageBacking> m_coordinatedImageBacking;
+
+ PlatformLayer* m_platformLayer;
+ Timer m_animationStartedTimer;
+ TextureMapperAnimations m_animations;
+ double m_lastAnimationStartTime { 0.0 };
+
+ ScrollableArea* m_scrollableArea;
+};
+
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_GRAPHICSLAYER(WebCore::CoordinatedGraphicsLayer, isCoordinatedGraphicsLayer())
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedGraphicsLayer_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsState.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsState.h
new file mode 100644
index 000000000..c810530b5
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsState.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2013 Company 100, 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 CoordinatedGraphicsState_h
+#define CoordinatedGraphicsState_h
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "Color.h"
+#include "FilterOperations.h"
+#include "FloatRect.h"
+#include "FloatSize.h"
+#include "IntRect.h"
+#include "IntSize.h"
+#include "SurfaceUpdateInfo.h"
+#include "TextureMapperAnimation.h"
+#include "TransformationMatrix.h"
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+#include "TextureMapperPlatformLayerProxy.h"
+#endif
+
+namespace WebCore {
+
+class CoordinatedSurface;
+
+typedef uint32_t CoordinatedLayerID;
+enum { InvalidCoordinatedLayerID = 0 };
+
+typedef uint64_t CoordinatedImageBackingID;
+enum { InvalidCoordinatedImageBackingID = 0 };
+
+struct TileUpdateInfo {
+ uint32_t tileID;
+ IntRect tileRect;
+ WebCore::SurfaceUpdateInfo updateInfo;
+};
+
+struct TileCreationInfo {
+ uint32_t tileID;
+ float scale;
+};
+
+struct CoordinatedGraphicsLayerState {
+ union {
+ struct {
+ bool positionChanged: 1;
+ bool anchorPointChanged: 1;
+ bool sizeChanged: 1;
+ bool transformChanged: 1;
+ bool childrenTransformChanged: 1;
+ bool contentsRectChanged: 1;
+ bool opacityChanged: 1;
+ bool solidColorChanged: 1;
+ bool debugBorderColorChanged: 1;
+ bool debugBorderWidthChanged: 1;
+ bool replicaChanged: 1;
+ bool maskChanged: 1;
+ bool imageChanged: 1;
+ bool flagsChanged: 1;
+ bool animationsChanged: 1;
+ bool filtersChanged: 1;
+ bool childrenChanged: 1;
+ bool repaintCountChanged : 1;
+ bool platformLayerChanged: 1;
+ bool platformLayerShouldSwapBuffers: 1;
+ bool isScrollableChanged: 1;
+ bool committedScrollOffsetChanged: 1;
+ bool contentsTilingChanged: 1;
+ };
+ unsigned changeMask;
+ };
+ union {
+ struct {
+ bool contentsOpaque : 1;
+ bool drawsContent : 1;
+ bool contentsVisible : 1;
+ bool backfaceVisible : 1;
+ bool masksToBounds : 1;
+ bool preserves3D : 1;
+ bool fixedToViewport : 1;
+ bool showDebugBorders : 1;
+ bool showRepaintCounter : 1;
+ bool isScrollable: 1;
+ };
+ unsigned flags;
+ };
+
+ CoordinatedGraphicsLayerState()
+ : changeMask(0)
+ , contentsOpaque(false)
+ , drawsContent(false)
+ , contentsVisible(true)
+ , backfaceVisible(true)
+ , masksToBounds(false)
+ , preserves3D(false)
+ , fixedToViewport(false)
+ , showDebugBorders(false)
+ , showRepaintCounter(false)
+ , isScrollable(false)
+ , opacity(0)
+ , debugBorderWidth(0)
+ , replica(InvalidCoordinatedLayerID)
+ , mask(InvalidCoordinatedLayerID)
+ , imageID(InvalidCoordinatedImageBackingID)
+ , repaintCount(0)
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ , platformLayerProxy(0)
+#endif
+ {
+ }
+
+ FloatPoint pos;
+ FloatPoint3D anchorPoint;
+ FloatSize size;
+ TransformationMatrix transform;
+ TransformationMatrix childrenTransform;
+ FloatRect contentsRect;
+ FloatSize contentsTilePhase;
+ FloatSize contentsTileSize;
+ float opacity;
+ Color solidColor;
+ Color debugBorderColor;
+ float debugBorderWidth;
+ FilterOperations filters;
+ TextureMapperAnimations animations;
+ Vector<uint32_t> children;
+ Vector<TileCreationInfo> tilesToCreate;
+ Vector<uint32_t> tilesToRemove;
+ CoordinatedLayerID replica;
+ CoordinatedLayerID mask;
+ CoordinatedImageBackingID imageID;
+
+ unsigned repaintCount;
+ Vector<TileUpdateInfo> tilesToUpdate;
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ RefPtr<TextureMapperPlatformLayerProxy> platformLayerProxy;
+#endif
+
+ IntSize committedScrollOffset;
+
+ bool hasPendingChanges() const
+ {
+ return changeMask || tilesToUpdate.size() || tilesToRemove.size() || tilesToCreate.size();
+ }
+};
+
+struct CoordinatedGraphicsState {
+ uint32_t rootCompositingLayer;
+ FloatPoint scrollPosition;
+ IntSize contentsSize;
+ IntRect coveredRect;
+
+ Vector<CoordinatedLayerID> layersToCreate;
+ Vector<std::pair<CoordinatedLayerID, CoordinatedGraphicsLayerState> > layersToUpdate;
+ Vector<CoordinatedLayerID> layersToRemove;
+
+ Vector<CoordinatedImageBackingID> imagesToCreate;
+ Vector<CoordinatedImageBackingID> imagesToRemove;
+ Vector<std::pair<CoordinatedImageBackingID, RefPtr<CoordinatedSurface> > > imagesToUpdate;
+ Vector<CoordinatedImageBackingID> imagesToClear;
+
+ Vector<std::pair<uint32_t /* atlasID */, RefPtr<CoordinatedSurface> > > updateAtlasesToCreate;
+ Vector<uint32_t /* atlasID */> updateAtlasesToRemove;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedGraphicsState_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.cpp
new file mode 100644
index 000000000..3f5673e8f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2012 Company 100, 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.
+ */
+
+#include "config.h"
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CoordinatedImageBacking.h"
+
+#include "CoordinatedGraphicsState.h"
+#include "GraphicsContext.h"
+
+namespace WebCore {
+
+class ImageBackingSurfaceClient : public CoordinatedSurface::Client {
+public:
+ ImageBackingSurfaceClient(Image& image, const IntRect& rect)
+ : m_image(image)
+ , m_rect(rect)
+ {
+ }
+
+ void paintToSurfaceContext(GraphicsContext& context) override
+ {
+ context.drawImage(m_image, m_rect, m_rect);
+ }
+
+private:
+ Image& m_image;
+ IntRect m_rect;
+};
+
+CoordinatedImageBackingID CoordinatedImageBacking::getCoordinatedImageBackingID(Image* image)
+{
+ // CoordinatedImageBacking keeps a RefPtr<Image> member, so the same Image pointer can not refer two different instances until CoordinatedImageBacking releases the member.
+ return reinterpret_cast<CoordinatedImageBackingID>(image);
+}
+
+PassRefPtr<CoordinatedImageBacking> CoordinatedImageBacking::create(Client* client, PassRefPtr<Image> image)
+{
+ return adoptRef(new CoordinatedImageBacking(client, image));
+}
+
+CoordinatedImageBacking::CoordinatedImageBacking(Client* client, PassRefPtr<Image> image)
+ : m_client(client)
+ , m_image(image)
+ , m_id(getCoordinatedImageBackingID(m_image.get()))
+ , m_clearContentsTimer(*this, &CoordinatedImageBacking::clearContentsTimerFired)
+ , m_isDirty(false)
+ , m_isVisible(false)
+{
+ // FIXME: We would need to decode a small image directly into a GraphicsSurface.
+ // http://webkit.org/b/101426
+
+ m_client->createImageBacking(id());
+}
+
+CoordinatedImageBacking::~CoordinatedImageBacking()
+{
+}
+
+void CoordinatedImageBacking::addHost(Host* host)
+{
+ ASSERT(!m_hosts.contains(host));
+ m_hosts.append(host);
+}
+
+void CoordinatedImageBacking::removeHost(Host* host)
+{
+ size_t position = m_hosts.find(host);
+ ASSERT(position != notFound);
+ m_hosts.remove(position);
+
+ if (m_hosts.isEmpty())
+ m_client->removeImageBacking(id());
+}
+
+void CoordinatedImageBacking::markDirty()
+{
+ m_isDirty = true;
+}
+
+void CoordinatedImageBacking::update()
+{
+ releaseSurfaceIfNeeded();
+
+ bool changedToVisible;
+ updateVisibilityIfNeeded(changedToVisible);
+ if (!m_isVisible)
+ return;
+
+ if (!changedToVisible) {
+ if (!m_isDirty)
+ return;
+
+ if (m_nativeImagePtr == m_image->nativeImageForCurrentFrame()) {
+ m_isDirty = false;
+ return;
+ }
+ }
+
+ m_surface = CoordinatedSurface::create(IntSize(m_image->size()), !m_image->currentFrameKnownToBeOpaque() ? CoordinatedSurface::SupportsAlpha : CoordinatedSurface::NoFlags);
+ if (!m_surface) {
+ m_isDirty = false;
+ return;
+ }
+
+ IntRect rect(IntPoint::zero(), IntSize(m_image->size()));
+
+ ImageBackingSurfaceClient surfaceClient(*m_image, rect);
+ m_surface->paintToSurface(rect, surfaceClient);
+
+ m_nativeImagePtr = m_image->nativeImageForCurrentFrame();
+
+ m_client->updateImageBacking(id(), m_surface.copyRef());
+ m_isDirty = false;
+}
+
+void CoordinatedImageBacking::releaseSurfaceIfNeeded()
+{
+ // We must keep m_surface until UI Process reads m_surface.
+ // If m_surface exists, it was created in the previous update.
+ m_surface = nullptr;
+}
+
+static const double clearContentsTimerInterval = 3;
+
+void CoordinatedImageBacking::updateVisibilityIfNeeded(bool& changedToVisible)
+{
+ bool previousIsVisible = m_isVisible;
+
+ m_isVisible = false;
+ for (auto& host : m_hosts) {
+ if (host->imageBackingVisible()) {
+ m_isVisible = true;
+ break;
+ }
+ }
+
+ bool changedToInvisible = previousIsVisible && !m_isVisible;
+ if (changedToInvisible) {
+ ASSERT(!m_clearContentsTimer.isActive());
+ m_clearContentsTimer.startOneShot(clearContentsTimerInterval);
+ }
+
+ changedToVisible = !previousIsVisible && m_isVisible;
+
+ if (m_isVisible && m_clearContentsTimer.isActive()) {
+ m_clearContentsTimer.stop();
+ // We don't want to update the texture if we didn't remove the texture.
+ changedToVisible = false;
+ }
+}
+
+void CoordinatedImageBacking::clearContentsTimerFired()
+{
+ m_client->clearImageBackingContents(id());
+}
+
+} // namespace WebCore
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.h
new file mode 100644
index 000000000..b8603c68e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 Company 100, 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 CoordinatedImageBacking_h
+#define CoordinatedImageBacking_h
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CoordinatedGraphicsState.h"
+#include "CoordinatedSurface.h"
+#include "Image.h"
+#include "Timer.h"
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CoordinatedImageBacking : public RefCounted<CoordinatedImageBacking> {
+public:
+ class Client {
+ public:
+ virtual void createImageBacking(CoordinatedImageBackingID) = 0;
+ virtual void updateImageBacking(CoordinatedImageBackingID, RefPtr<CoordinatedSurface>&&) = 0;
+ virtual void clearImageBackingContents(CoordinatedImageBackingID) = 0;
+ virtual void removeImageBacking(CoordinatedImageBackingID) = 0;
+ };
+
+ class Host {
+ public:
+ virtual bool imageBackingVisible() = 0;
+ };
+
+ static PassRefPtr<CoordinatedImageBacking> create(Client*, PassRefPtr<Image>);
+ virtual ~CoordinatedImageBacking();
+
+ static CoordinatedImageBackingID getCoordinatedImageBackingID(Image*);
+ CoordinatedImageBackingID id() const { return m_id; }
+
+ void addHost(Host*);
+ void removeHost(Host*);
+
+ // When a new image is updated or an animated gif is progressed, CoordinatedGraphicsLayer calls markDirty().
+ void markDirty();
+
+ // Create, remove or update its backing.
+ void update();
+
+private:
+ CoordinatedImageBacking(Client*, PassRefPtr<Image>);
+
+ void releaseSurfaceIfNeeded();
+ void updateVisibilityIfNeeded(bool& changedToVisible);
+ void clearContentsTimerFired();
+
+ Client* m_client;
+ RefPtr<Image> m_image;
+ NativeImagePtr m_nativeImagePtr;
+ CoordinatedImageBackingID m_id;
+ Vector<Host*> m_hosts;
+
+ RefPtr<CoordinatedSurface> m_surface;
+
+ Timer m_clearContentsTimer;
+
+ bool m_isDirty;
+ bool m_isVisible;
+
+};
+
+} // namespace WebCore
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedImageBacking_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.cpp
new file mode 100644
index 000000000..e0d815bd0
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 Company 100, 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.
+ */
+
+#include "config.h"
+#include "CoordinatedSurface.h"
+
+#if USE(COORDINATED_GRAPHICS)
+
+namespace WebCore {
+
+CoordinatedSurface::Factory* CoordinatedSurface::s_factory = 0;
+
+void CoordinatedSurface::setFactory(CoordinatedSurface::Factory factory)
+{
+ s_factory = factory;
+}
+
+RefPtr<CoordinatedSurface> CoordinatedSurface::create(const IntSize& size, Flags flags)
+{
+ ASSERT(s_factory);
+ return s_factory(size, flags);
+}
+
+CoordinatedSurface::CoordinatedSurface(const IntSize& size, Flags flags)
+ : m_size(size)
+ , m_flags(flags)
+{
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.h
new file mode 100644
index 000000000..ac9ae1712
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.h
@@ -0,0 +1,76 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012 Company 100, Inc.
+
+ 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 CoordinatedSurface_h
+#define CoordinatedSurface_h
+
+#if USE(COORDINATED_GRAPHICS)
+#include "IntRect.h"
+#include <wtf/RefPtr.h>
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace WebCore {
+class BitmapTexture;
+class GraphicsContext;
+
+class CoordinatedSurface : public ThreadSafeRefCounted<CoordinatedSurface> {
+public:
+ enum Flag {
+ NoFlags = 0,
+ SupportsAlpha = 1 << 0,
+ };
+ typedef unsigned Flags;
+
+ class Client {
+ public:
+ virtual ~Client() { }
+ virtual void paintToSurfaceContext(GraphicsContext&) = 0;
+ };
+
+ typedef RefPtr<CoordinatedSurface> Factory(const IntSize&, Flags);
+ static void setFactory(Factory);
+ static RefPtr<CoordinatedSurface> create(const IntSize&, Flags);
+
+ virtual ~CoordinatedSurface() { }
+
+ bool supportsAlpha() const { return flags() & SupportsAlpha; }
+ IntSize size() const { return m_size; }
+
+ virtual void paintToSurface(const IntRect&, Client&) = 0;
+
+#if USE(TEXTURE_MAPPER)
+ virtual void copyToTexture(RefPtr<BitmapTexture>, const IntRect& target, const IntPoint& sourceOffset) = 0;
+#endif
+
+protected:
+ CoordinatedSurface(const IntSize&, Flags);
+ Flags flags() const { return m_flags; }
+
+ IntSize m_size;
+ Flags m_flags;
+
+private:
+ static CoordinatedSurface::Factory* s_factory;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+#endif // CoordinatedSurface_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/SurfaceUpdateInfo.h b/Source/WebCore/platform/graphics/texmap/coordinated/SurfaceUpdateInfo.h
new file mode 100644
index 000000000..0e749be93
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/SurfaceUpdateInfo.h
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2012 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 SurfaceUpdateInfo_h
+#define SurfaceUpdateInfo_h
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "IntRect.h"
+
+namespace WebCore {
+
+class SurfaceUpdateInfo {
+
+public:
+ SurfaceUpdateInfo() { }
+
+ // The rect to be updated.
+ IntRect updateRect;
+
+ // The id of the update atlas including the shareable bitmap containing the updates.
+ uint32_t atlasID { 0 };
+
+ // The offset in the bitmap where the rendered contents are.
+ IntPoint surfaceOffset;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // SurfaceUpdateInfo_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/Tile.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/Tile.cpp
new file mode 100644
index 000000000..f155d4433
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/Tile.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "Tile.h"
+
+#if USE(COORDINATED_GRAPHICS)
+#include "GraphicsContext.h"
+#include "SurfaceUpdateInfo.h"
+#include "TiledBackingStore.h"
+#include "TiledBackingStoreClient.h"
+
+namespace WebCore {
+
+static const uint32_t InvalidTileID = 0;
+
+Tile::Tile(TiledBackingStore& tiledBackingStore, const Coordinate& tileCoordinate)
+ : m_tiledBackingStore(tiledBackingStore)
+ , m_coordinate(tileCoordinate)
+ , m_rect(tiledBackingStore.tileRectForCoordinate(tileCoordinate))
+ , m_ID(InvalidTileID)
+ , m_dirtyRect(m_rect)
+{
+}
+
+Tile::~Tile()
+{
+ if (m_ID != InvalidTileID)
+ m_tiledBackingStore.client()->removeTile(m_ID);
+}
+
+bool Tile::isDirty() const
+{
+ return !m_dirtyRect.isEmpty();
+}
+
+void Tile::invalidate(const IntRect& dirtyRect)
+{
+ IntRect tileDirtyRect = intersection(dirtyRect, m_rect);
+ if (tileDirtyRect.isEmpty())
+ return;
+
+ m_dirtyRect.unite(tileDirtyRect);
+}
+
+bool Tile::updateBackBuffer()
+{
+ if (!isDirty())
+ return false;
+
+ SurfaceUpdateInfo updateInfo;
+
+ if (!m_tiledBackingStore.client()->paintToSurface(m_dirtyRect.size(), updateInfo.atlasID, updateInfo.surfaceOffset, *this))
+ return false;
+
+ updateInfo.updateRect = m_dirtyRect;
+ updateInfo.updateRect.move(-m_rect.x(), -m_rect.y());
+
+ static uint32_t id = 1;
+ if (m_ID == InvalidTileID) {
+ m_ID = id++;
+ // We may get an invalid ID due to wrap-around on overflow.
+ if (m_ID == InvalidTileID)
+ m_ID = id++;
+ m_tiledBackingStore.client()->createTile(m_ID, m_tiledBackingStore.contentsScale());
+ }
+ m_tiledBackingStore.client()->updateTile(m_ID, updateInfo, m_rect);
+
+ m_dirtyRect = IntRect();
+
+ return true;
+}
+
+void Tile::paintToSurfaceContext(GraphicsContext& context)
+{
+ context.translate(-m_dirtyRect.x(), -m_dirtyRect.y());
+ context.scale(FloatSize(m_tiledBackingStore.contentsScale(), m_tiledBackingStore.contentsScale()));
+ m_tiledBackingStore.client()->tiledBackingStorePaint(context, m_tiledBackingStore.mapToContents(m_dirtyRect));
+}
+
+bool Tile::isReadyToPaint() const
+{
+ return m_ID != InvalidTileID;
+}
+
+void Tile::resize(const IntSize& newSize)
+{
+ m_rect = IntRect(m_rect.location(), newSize);
+ m_dirtyRect = m_rect;
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/Tile.h b/Source/WebCore/platform/graphics/texmap/coordinated/Tile.h
new file mode 100644
index 000000000..0b04d75aa
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/Tile.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010-2011 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 Tile_h
+#define Tile_h
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CoordinatedSurface.h"
+#include "IntPoint.h"
+#include "IntPointHash.h"
+#include "IntRect.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class GraphicsContext;
+class TiledBackingStore;
+
+class Tile : public CoordinatedSurface::Client {
+public:
+ typedef IntPoint Coordinate;
+
+ Tile(TiledBackingStore&, const Coordinate&);
+ ~Tile();
+
+ bool isDirty() const;
+ void invalidate(const IntRect&);
+ bool updateBackBuffer();
+ bool isReadyToPaint() const;
+
+ const Coordinate& coordinate() const { return m_coordinate; }
+ const IntRect& rect() const { return m_rect; }
+ void resize(const IntSize&);
+
+ void paintToSurfaceContext(GraphicsContext&) override;
+
+private:
+ TiledBackingStore& m_tiledBackingStore;
+ Coordinate m_coordinate;
+ IntRect m_rect;
+
+ uint32_t m_ID;
+ IntRect m_dirtyRect;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // Tile_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStore.cpp
new file mode 100644
index 000000000..b6389165a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStore.cpp
@@ -0,0 +1,425 @@
+/*
+ Copyright (C) 2010-2012 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 "TiledBackingStore.h"
+
+#if USE(COORDINATED_GRAPHICS)
+#include "GraphicsContext.h"
+#include "MemoryPressureHandler.h"
+#include "TiledBackingStoreClient.h"
+#include <wtf/CheckedArithmetic.h>
+
+namespace WebCore {
+
+static const int defaultTileDimension = 512;
+
+static IntPoint innerBottomRight(const IntRect& rect)
+{
+ // Actually, the rect does not contain rect.maxX(). Refer to IntRect::contain.
+ return IntPoint(rect.maxX() - 1, rect.maxY() - 1);
+}
+
+TiledBackingStore::TiledBackingStore(TiledBackingStoreClient* client, float contentsScale)
+ : m_client(client)
+ , m_tileSize(defaultTileDimension, defaultTileDimension)
+ , m_coverAreaMultiplier(2.0f)
+ , m_contentsScale(contentsScale)
+ , m_supportsAlpha(false)
+ , m_pendingTileCreation(false)
+{
+}
+
+TiledBackingStore::~TiledBackingStore()
+{
+}
+
+void TiledBackingStore::setTrajectoryVector(const FloatPoint& trajectoryVector)
+{
+ m_pendingTrajectoryVector = trajectoryVector;
+ m_pendingTrajectoryVector.normalize();
+}
+
+void TiledBackingStore::createTilesIfNeeded(const IntRect& unscaledVisibleRect, const IntRect& contentsRect)
+{
+ IntRect scaledContentsRect = mapFromContents(contentsRect);
+ IntRect visibleRect = mapFromContents(unscaledVisibleRect);
+ float coverAreaMultiplier = MemoryPressureHandler::singleton().isUnderMemoryPressure() ? 1.0f : 2.0f;
+
+ bool didChange = m_trajectoryVector != m_pendingTrajectoryVector || m_visibleRect != visibleRect || m_rect != scaledContentsRect || m_coverAreaMultiplier != coverAreaMultiplier;
+ if (didChange || m_pendingTileCreation)
+ createTiles(visibleRect, scaledContentsRect, coverAreaMultiplier);
+}
+
+void TiledBackingStore::invalidate(const IntRect& contentsDirtyRect)
+{
+ IntRect dirtyRect(mapFromContents(contentsDirtyRect));
+ IntRect keepRectFitToTileSize = tileRectForCoordinate(tileCoordinateForPoint(m_keepRect.location()));
+ keepRectFitToTileSize.unite(tileRectForCoordinate(tileCoordinateForPoint(innerBottomRight(m_keepRect))));
+
+ // Only iterate on the part of the rect that we know we might have tiles.
+ IntRect coveredDirtyRect = intersection(dirtyRect, keepRectFitToTileSize);
+ Tile::Coordinate topLeft = tileCoordinateForPoint(coveredDirtyRect.location());
+ Tile::Coordinate bottomRight = tileCoordinateForPoint(innerBottomRight(coveredDirtyRect));
+
+ for (int yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
+ for (int xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
+ Tile* currentTile = m_tiles.get(Tile::Coordinate(xCoordinate, yCoordinate));
+ if (!currentTile)
+ continue;
+ // Pass the full rect to each tile as coveredDirtyRect might not
+ // contain them completely and we don't want partial tile redraws.
+ currentTile->invalidate(dirtyRect);
+ }
+ }
+}
+
+void TiledBackingStore::updateTileBuffers()
+{
+ // FIXME: In single threaded case, tile back buffers could be updated asynchronously
+ // one by one and then swapped to front in one go. This would minimize the time spent
+ // blocking on tile updates.
+ bool updated = false;
+ for (auto& tile : m_tiles.values()) {
+ if (!tile->isDirty())
+ continue;
+
+ updated |= tile->updateBackBuffer();
+ }
+
+ if (updated)
+ m_client->didUpdateTileBuffers();
+}
+
+double TiledBackingStore::tileDistance(const IntRect& viewport, const Tile::Coordinate& tileCoordinate) const
+{
+ if (viewport.intersects(tileRectForCoordinate(tileCoordinate)))
+ return 0;
+
+ IntPoint viewCenter = viewport.location() + IntSize(viewport.width() / 2, viewport.height() / 2);
+ Tile::Coordinate centerCoordinate = tileCoordinateForPoint(viewCenter);
+
+ return std::max(abs(centerCoordinate.y() - tileCoordinate.y()), abs(centerCoordinate.x() - tileCoordinate.x()));
+}
+
+// Returns a ratio between 0.0f and 1.0f of the surface covered by rendered tiles.
+float TiledBackingStore::coverageRatio(const WebCore::IntRect& dirtyRect) const
+{
+ float rectArea = dirtyRect.width() * dirtyRect.height();
+ float coverArea = 0.0f;
+
+ Tile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.location());
+ Tile::Coordinate bottomRight = tileCoordinateForPoint(innerBottomRight(dirtyRect));
+
+ for (int yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
+ for (int xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
+ Tile::Coordinate currentCoordinate(xCoordinate, yCoordinate);
+ Tile* currentTile = m_tiles.get(currentCoordinate);
+ if (currentTile && currentTile->isReadyToPaint()) {
+ IntRect coverRect = intersection(dirtyRect, currentTile->rect());
+ coverArea += coverRect.width() * coverRect.height();
+ }
+ }
+ }
+ return coverArea / rectArea;
+}
+
+bool TiledBackingStore::visibleAreaIsCovered() const
+{
+ return coverageRatio(intersection(m_visibleRect, m_rect)) == 1.0f;
+}
+
+void TiledBackingStore::createTiles(const IntRect& visibleRect, const IntRect& scaledContentsRect, float coverAreaMultiplier)
+{
+ // Update our backing store geometry.
+ const IntRect previousRect = m_rect;
+ m_rect = scaledContentsRect;
+ m_trajectoryVector = m_pendingTrajectoryVector;
+ m_visibleRect = visibleRect;
+ m_coverAreaMultiplier = coverAreaMultiplier;
+
+ if (m_rect.isEmpty()) {
+ setCoverRect(IntRect());
+ setKeepRect(IntRect());
+ return;
+ }
+
+ /* We must compute cover and keep rects using the visibleRect, instead of the rect intersecting the visibleRect with m_rect,
+ * because TBS can be used as a backing store of GraphicsLayer and the visible rect usually does not intersect with m_rect.
+ * In the below case, the intersecting rect is an empty.
+ *
+ * +---------------+
+ * | |
+ * | m_rect |
+ * | +-------|-----------------------+
+ * | | HERE | cover or keep |
+ * +---------------+ rect |
+ * | +---------+ |
+ * | | visible | |
+ * | | rect | |
+ * | +---------+ |
+ * | |
+ * | |
+ * +-------------------------------+
+ *
+ * We must create or keep the tiles in the HERE region.
+ */
+
+ IntRect coverRect;
+ IntRect keepRect;
+ computeCoverAndKeepRect(m_visibleRect, coverRect, keepRect);
+
+ setCoverRect(coverRect);
+ setKeepRect(keepRect);
+
+ if (coverRect.isEmpty())
+ return;
+
+ // Resize tiles at the edge in case the contents size has changed, but only do so
+ // after having dropped tiles outside the keep rect.
+ bool didResizeTiles = false;
+ if (previousRect != m_rect)
+ didResizeTiles = resizeEdgeTiles();
+
+ // Search for the tile position closest to the viewport center that does not yet contain a tile.
+ // Which position is considered the closest depends on the tileDistance function.
+ double shortestDistance = std::numeric_limits<double>::infinity();
+ Vector<Tile::Coordinate> tilesToCreate;
+ unsigned requiredTileCount = 0;
+
+ // Cover areas (in tiles) with minimum distance from the visible rect. If the visible rect is
+ // not covered already it will be covered first in one go, due to the distance being 0 for tiles
+ // inside the visible rect.
+ Tile::Coordinate topLeft = tileCoordinateForPoint(coverRect.location());
+ Tile::Coordinate bottomRight = tileCoordinateForPoint(innerBottomRight(coverRect));
+ for (int yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
+ for (int xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
+ Tile::Coordinate currentCoordinate(xCoordinate, yCoordinate);
+ if (m_tiles.contains(currentCoordinate))
+ continue;
+ ++requiredTileCount;
+ double distance = tileDistance(m_visibleRect, currentCoordinate);
+ if (distance > shortestDistance)
+ continue;
+ if (distance < shortestDistance) {
+ tilesToCreate.clear();
+ shortestDistance = distance;
+ }
+ tilesToCreate.append(currentCoordinate);
+ }
+ }
+
+ // Now construct the tile(s) within the shortest distance.
+ unsigned tilesToCreateCount = tilesToCreate.size();
+ for (unsigned n = 0; n < tilesToCreateCount; ++n) {
+ Tile::Coordinate coordinate = tilesToCreate[n];
+ m_tiles.add(coordinate, std::make_unique<Tile>(*this, coordinate));
+ }
+ requiredTileCount -= tilesToCreateCount;
+
+ // Paint the content of the newly created tiles or resized tiles.
+ if (tilesToCreateCount || didResizeTiles)
+ updateTileBuffers();
+
+ // Re-call createTiles on a timer to cover the visible area with the newest shortest distance.
+ m_pendingTileCreation = requiredTileCount;
+ if (m_pendingTileCreation)
+ m_client->tiledBackingStoreHasPendingTileCreation();
+}
+
+void TiledBackingStore::adjustForContentsRect(IntRect& rect) const
+{
+ IntRect bounds = m_rect;
+ IntSize candidateSize = rect.size();
+
+ rect.intersect(bounds);
+
+ if (rect.size() == candidateSize)
+ return;
+
+ /*
+ * In the following case, there is no intersection of the contents rect and the cover rect.
+ * Thus the latter should not be inflated.
+ *
+ * +---------------+
+ * | m_rect |
+ * +---------------+
+ *
+ * +-------------------------------+
+ * | cover rect |
+ * | +---------+ |
+ * | | visible | |
+ * | | rect | |
+ * | +---------+ |
+ * +-------------------------------+
+ */
+ if (rect.isEmpty())
+ return;
+
+ // Try to create a cover rect of the same size as the candidate, but within content bounds.
+ int pixelsCovered = 0;
+ if (!WTF::safeMultiply(candidateSize.width(), candidateSize.height(), pixelsCovered))
+ pixelsCovered = std::numeric_limits<int>::max();
+
+ if (rect.width() < candidateSize.width())
+ rect.inflateY(((pixelsCovered / rect.width()) - rect.height()) / 2);
+ if (rect.height() < candidateSize.height())
+ rect.inflateX(((pixelsCovered / rect.height()) - rect.width()) / 2);
+
+ rect.intersect(bounds);
+}
+
+void TiledBackingStore::computeCoverAndKeepRect(const IntRect& visibleRect, IntRect& coverRect, IntRect& keepRect) const
+{
+ coverRect = visibleRect;
+ keepRect = visibleRect;
+
+ // If we cover more that the actual viewport we can be smart about which tiles we choose to render.
+ if (m_coverAreaMultiplier > 1) {
+ // The initial cover area covers equally in each direction, according to the coverAreaMultiplier.
+ coverRect.inflateX(visibleRect.width() * (m_coverAreaMultiplier - 1) / 2);
+ coverRect.inflateY(visibleRect.height() * (m_coverAreaMultiplier - 1) / 2);
+ keepRect = coverRect;
+
+ if (m_trajectoryVector != FloatPoint::zero()) {
+ // A null trajectory vector (no motion) means that tiles for the coverArea will be created.
+ // A non-null trajectory vector will shrink the covered rect to visibleRect plus its expansion from its
+ // center toward the cover area edges in the direction of the given vector.
+
+ // E.g. if visibleRect == (10,10)5x5 and coverAreaMultiplier == 3.0:
+ // a (0,0) trajectory vector will create tiles intersecting (5,5)15x15,
+ // a (1,0) trajectory vector will create tiles intersecting (10,10)10x5,
+ // and a (1,1) trajectory vector will create tiles intersecting (10,10)10x10.
+
+ // Multiply the vector by the distance to the edge of the cover area.
+ float trajectoryVectorMultiplier = (m_coverAreaMultiplier - 1) / 2;
+
+ // Unite the visible rect with a "ghost" of the visible rect moved in the direction of the trajectory vector.
+ coverRect = visibleRect;
+ coverRect.move(coverRect.width() * m_trajectoryVector.x() * trajectoryVectorMultiplier, coverRect.height() * m_trajectoryVector.y() * trajectoryVectorMultiplier);
+
+ coverRect.unite(visibleRect);
+ }
+ ASSERT(keepRect.contains(coverRect));
+ }
+
+ adjustForContentsRect(coverRect);
+
+ // The keep rect is an inflated version of the cover rect, inflated in tile dimensions.
+ keepRect.unite(coverRect);
+ keepRect.inflateX(m_tileSize.width() / 2);
+ keepRect.inflateY(m_tileSize.height() / 2);
+ keepRect.intersect(m_rect);
+
+ ASSERT(coverRect.isEmpty() || keepRect.contains(coverRect));
+}
+
+bool TiledBackingStore::resizeEdgeTiles()
+{
+ bool wasResized = false;
+ Vector<Tile::Coordinate> tilesToRemove;
+ for (auto& tile : m_tiles.values()) {
+ Tile::Coordinate tileCoordinate = tile->coordinate();
+ IntRect tileRect = tile->rect();
+ IntRect expectedTileRect = tileRectForCoordinate(tileCoordinate);
+ if (expectedTileRect.isEmpty())
+ tilesToRemove.append(tileCoordinate);
+ else if (expectedTileRect != tileRect) {
+ tile->resize(expectedTileRect.size());
+ wasResized = true;
+ }
+ }
+
+ for (auto& coordinateToRemove : tilesToRemove)
+ m_tiles.remove(coordinateToRemove);
+
+ return wasResized;
+}
+
+void TiledBackingStore::setKeepRect(const IntRect& keepRect)
+{
+ // Drop tiles outside the new keepRect.
+
+ FloatRect keepRectF = keepRect;
+
+ Vector<Tile::Coordinate> toRemove;
+ for (auto& tile : m_tiles.values()) {
+ Tile::Coordinate coordinate = tile->coordinate();
+ FloatRect tileRect = tile->rect();
+ if (!tileRect.intersects(keepRectF))
+ toRemove.append(coordinate);
+ }
+
+ for (auto& coordinateToRemove : toRemove)
+ m_tiles.remove(coordinateToRemove);
+
+ m_keepRect = keepRect;
+}
+
+void TiledBackingStore::removeAllNonVisibleTiles(const IntRect& unscaledVisibleRect, const IntRect& contentsRect)
+{
+ IntRect boundedVisibleRect = mapFromContents(intersection(unscaledVisibleRect, contentsRect));
+ setKeepRect(boundedVisibleRect);
+}
+
+IntRect TiledBackingStore::mapToContents(const IntRect& rect) const
+{
+ return enclosingIntRect(FloatRect(rect.x() / m_contentsScale,
+ rect.y() / m_contentsScale,
+ rect.width() / m_contentsScale,
+ rect.height() / m_contentsScale));
+}
+
+IntRect TiledBackingStore::mapFromContents(const IntRect& rect) const
+{
+ return enclosingIntRect(FloatRect(rect.x() * m_contentsScale,
+ rect.y() * m_contentsScale,
+ rect.width() * m_contentsScale,
+ rect.height() * m_contentsScale));
+}
+
+IntRect TiledBackingStore::tileRectForCoordinate(const Tile::Coordinate& coordinate) const
+{
+ IntRect rect(coordinate.x() * m_tileSize.width(),
+ coordinate.y() * m_tileSize.height(),
+ m_tileSize.width(),
+ m_tileSize.height());
+
+ rect.intersect(m_rect);
+ return rect;
+}
+
+Tile::Coordinate TiledBackingStore::tileCoordinateForPoint(const IntPoint& point) const
+{
+ int x = point.x() / m_tileSize.width();
+ int y = point.y() / m_tileSize.height();
+ return Tile::Coordinate(std::max(x, 0), std::max(y, 0));
+}
+
+void TiledBackingStore::setSupportsAlpha(bool a)
+{
+ if (a == m_supportsAlpha)
+ return;
+ m_supportsAlpha = a;
+ invalidate(m_rect);
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStore.h b/Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStore.h
new file mode 100644
index 000000000..c17f7644d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStore.h
@@ -0,0 +1,109 @@
+/*
+ Copyright (C) 2010-2012 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 TiledBackingStore_h
+#define TiledBackingStore_h
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "FloatPoint.h"
+#include "IntPoint.h"
+#include "IntRect.h"
+#include "Tile.h"
+#include "Timer.h"
+#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class GraphicsContext;
+class TiledBackingStoreClient;
+
+class TiledBackingStore {
+ WTF_MAKE_NONCOPYABLE(TiledBackingStore); WTF_MAKE_FAST_ALLOCATED;
+public:
+ TiledBackingStore(TiledBackingStoreClient*, float contentsScale = 1.f);
+ ~TiledBackingStore();
+
+ TiledBackingStoreClient* client() { return m_client; }
+
+ void setTrajectoryVector(const FloatPoint&);
+ void createTilesIfNeeded(const IntRect& unscaledVisibleRect, const IntRect& contentsRect);
+
+ float contentsScale() { return m_contentsScale; }
+
+ void updateTileBuffers();
+
+ void invalidate(const IntRect& dirtyRect);
+
+ IntRect mapToContents(const IntRect&) const;
+ IntRect mapFromContents(const IntRect&) const;
+
+ IntRect tileRectForCoordinate(const Tile::Coordinate&) const;
+ Tile::Coordinate tileCoordinateForPoint(const IntPoint&) const;
+ double tileDistance(const IntRect& viewport, const Tile::Coordinate&) const;
+
+ IntRect coverRect() const { return m_coverRect; }
+ bool visibleAreaIsCovered() const;
+ void removeAllNonVisibleTiles(const IntRect& unscaledVisibleRect, const IntRect& contentsRect);
+
+ void setSupportsAlpha(bool);
+
+private:
+ void createTiles(const IntRect& visibleRect, const IntRect& scaledContentsRect, float coverAreaMultiplier);
+ void computeCoverAndKeepRect(const IntRect& visibleRect, IntRect& coverRect, IntRect& keepRect) const;
+
+ bool resizeEdgeTiles();
+ void setCoverRect(const IntRect& rect) { m_coverRect = rect; }
+ void setKeepRect(const IntRect&);
+
+ float coverageRatio(const IntRect&) const;
+ void adjustForContentsRect(IntRect&) const;
+
+ void paintCheckerPattern(GraphicsContext*, const IntRect&, const Tile::Coordinate&);
+
+private:
+ TiledBackingStoreClient* m_client;
+
+ typedef HashMap<Tile::Coordinate, std::unique_ptr<Tile>> TileMap;
+ TileMap m_tiles;
+
+ IntSize m_tileSize;
+ float m_coverAreaMultiplier;
+
+ FloatPoint m_trajectoryVector;
+ FloatPoint m_pendingTrajectoryVector;
+ IntRect m_visibleRect;
+
+ IntRect m_coverRect;
+ IntRect m_keepRect;
+ IntRect m_rect;
+
+ float m_contentsScale;
+
+ bool m_supportsAlpha;
+ bool m_pendingTileCreation;
+
+ friend class Tile;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStoreClient.h b/Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStoreClient.h
new file mode 100644
index 000000000..61936ff9c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/TiledBackingStoreClient.h
@@ -0,0 +1,49 @@
+/*
+ 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 TiledBackingStoreClient_h
+#define TiledBackingStoreClient_h
+
+#include "CoordinatedSurface.h"
+
+namespace WebCore {
+
+#if USE(COORDINATED_GRAPHICS)
+
+class GraphicsContext;
+class SurfaceUpdateInfo;
+
+class TiledBackingStoreClient {
+public:
+ virtual ~TiledBackingStoreClient() { }
+ virtual void tiledBackingStorePaint(GraphicsContext&, const IntRect&) = 0;
+ virtual void didUpdateTileBuffers() = 0;
+ virtual void tiledBackingStoreHasPendingTileCreation() = 0;
+
+ virtual void createTile(uint32_t tileID, float) = 0;
+ virtual void updateTile(uint32_t tileID, const SurfaceUpdateInfo&, const IntRect&) = 0;
+ virtual void removeTile(uint32_t tileID) = 0;
+ virtual bool paintToSurface(const IntSize&, uint32_t& atlasID, IntPoint&, CoordinatedSurface::Client&) = 0;
+};
+
+#endif
+
+}
+
+#endif