1/* 2 * Copyright (C) 2012 Igalia, S.L. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19#include "config.h" 20#include "AcceleratedCompositingContext.h" 21 22#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER_CAIRO) 23 24#include "CairoUtilities.h" 25#include "Chrome.h" 26#include "ChromeClientGtk.h" 27#include "Frame.h" 28#include "FrameView.h" 29#include "PlatformContextCairo.h" 30#include "TextureMapperImageBuffer.h" 31#include "TextureMapperLayer.h" 32#include "webkitwebviewprivate.h" 33#include <cairo.h> 34#include <gdk/gdk.h> 35#include <gtk/gtk.h> 36 37using namespace WebCore; 38 39namespace WebKit { 40 41AcceleratedCompositingContext::AcceleratedCompositingContext(WebKitWebView* webView) 42 : m_webView(webView) 43 , m_syncTimerCallbackId(0) 44 , m_rootTextureMapperLayer(0) 45{ 46} 47 48AcceleratedCompositingContext::~AcceleratedCompositingContext() 49{ 50 if (m_syncTimerCallbackId) 51 g_source_remove(m_syncTimerCallbackId); 52} 53 54bool AcceleratedCompositingContext::enabled() 55{ 56 return m_rootTextureMapperLayer && m_textureMapper; 57} 58 59bool AcceleratedCompositingContext::renderLayersToWindow(cairo_t* cr, const IntRect& clipRect) 60{ 61 if (!cr || !enabled()) 62 return false; 63 64 GraphicsContext context(cr); 65 m_textureMapper->setGraphicsContext(&context); 66 67 m_textureMapper->beginPainting(); 68 m_rootTextureMapperLayer->paint(); 69 m_textureMapper->endPainting(); 70 71 return true; 72} 73 74void AcceleratedCompositingContext::attachRootGraphicsLayer(GraphicsLayer* graphicsLayer) 75{ 76 if (!graphicsLayer) { 77 m_rootGraphicsLayer.clear(); 78 m_rootTextureMapperLayer = 0; 79 return; 80 } 81 82 m_rootGraphicsLayer = GraphicsLayer::create(this); 83 m_rootTextureMapperLayer = toTextureMapperLayer(m_rootGraphicsLayer.get()); 84 m_rootGraphicsLayer->addChild(graphicsLayer); 85 m_rootGraphicsLayer->setDrawsContent(true); 86 m_rootGraphicsLayer->setMasksToBounds(false); 87 m_rootGraphicsLayer->setNeedsDisplay(); 88 m_rootGraphicsLayer->setSize(core(m_webView)->mainFrame()->view()->frameRect().size()); 89 90 m_textureMapper = TextureMapperImageBuffer::create(); 91 m_rootTextureMapperLayer->setTextureMapper(m_textureMapper.get()); 92 m_rootGraphicsLayer->flushCompositingStateForThisLayerOnly(); 93} 94 95void AcceleratedCompositingContext::scheduleRootLayerRepaint(const IntRect& rect) 96{ 97 if (!m_rootGraphicsLayer) 98 return; 99 if (rect.isEmpty()) { 100 m_rootGraphicsLayer->setNeedsDisplay(); 101 return; 102 } 103 m_rootGraphicsLayer->setNeedsDisplayInRect(rect); 104 105 gtk_widget_queue_draw_area(GTK_WIDGET(m_webView), rect.x(), rect.y(), rect.width(), rect.height()); 106} 107 108void AcceleratedCompositingContext::resizeRootLayer(const IntSize& size) 109{ 110 if (!m_rootGraphicsLayer) 111 return; 112 m_rootGraphicsLayer->setSize(size); 113 m_rootGraphicsLayer->flushCompositingStateForThisLayerOnly(); 114} 115 116static gboolean syncLayersTimeoutCallback(AcceleratedCompositingContext* context) 117{ 118 context->syncLayersTimeout(); 119 return FALSE; 120} 121 122void AcceleratedCompositingContext::markForSync() 123{ 124 if (m_syncTimerCallbackId) 125 return; 126 127 // We use a GLib timer because otherwise GTK+ event handling during 128 // dragging can starve WebCore timers, which have a lower priority. 129 m_syncTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, 0, reinterpret_cast<GSourceFunc>(syncLayersTimeoutCallback), this, 0); 130} 131 132void AcceleratedCompositingContext::syncLayersNow() 133{ 134 if (core(m_webView)->mainFrame()->view()->needsLayout()) 135 core(m_webView)->mainFrame()->view()->layout(); 136 137 if (m_rootGraphicsLayer) 138 m_rootGraphicsLayer->flushCompositingStateForThisLayerOnly(); 139 140 core(m_webView)->mainFrame()->view()->flushCompositingStateIncludingSubframes(); 141} 142 143void AcceleratedCompositingContext::syncLayersTimeout() 144{ 145 m_syncTimerCallbackId = 0; 146 syncLayersNow(); 147 if (!m_rootGraphicsLayer) 148 return; 149 150 // FIXME: Invalidate just the animations rectangles. 151 gtk_widget_queue_draw(GTK_WIDGET(m_webView)); 152 153 if (toTextureMapperLayer(m_rootGraphicsLayer.get())->descendantsOrSelfHaveRunningAnimations()) 154 m_syncTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, 1000.0 / 60.0, reinterpret_cast<GSourceFunc>(syncLayersTimeoutCallback), this, 0); 155} 156 157void AcceleratedCompositingContext::notifyAnimationStarted(const GraphicsLayer*, double time) 158{ 159 160} 161void AcceleratedCompositingContext::notifyFlushRequired(const GraphicsLayer*) 162{ 163 164} 165 166void AcceleratedCompositingContext::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& rectToPaint) 167{ 168 cairo_t* cr = context.platformContext()->cr(); 169 copyRectFromCairoSurfaceToContext(m_webView->priv->backingStore->cairoSurface(), cr, IntSize(), rectToPaint); 170} 171 172} // namespace WebKit 173 174#endif // USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER_CAIRO) 175