AcceleratedCompositingContextClutter.cpp [plain text]
#include "config.h"
#include "AcceleratedCompositingContext.h"
#if USE(ACCELERATED_COMPOSITING) && USE(CLUTTER)
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsLayer.h"
#include "GraphicsLayerActor.h"
#include "NotImplemented.h"
#include "Settings.h"
#include "webkitwebviewprivate.h"
#include <clutter-gtk/clutter-gtk.h>
#include <clutter/clutter.h>
using namespace WebCore;
namespace WebKit {
AcceleratedCompositingContext::AcceleratedCompositingContext(WebKitWebView* webView)
: m_webView(webView)
, m_layerFlushTimerCallbackId(0)
, m_rootLayerEmbedder(0)
{
}
void AcceleratedCompositingContext::initialize()
{
if (m_rootLayer)
return;
GtkAllocation allocation;
gtk_widget_get_allocation(GTK_WIDGET(m_webView), &allocation);
IntSize pageSize(allocation.width, allocation.height);
m_rootLayer = GraphicsLayer::create(0, this);
m_rootLayer->setDrawsContent(false);
m_rootLayer->setSize(pageSize);
m_nonCompositedContentLayer = GraphicsLayer::create(0, this);
m_nonCompositedContentLayer->setDrawsContent(true);
m_nonCompositedContentLayer->setContentsOpaque(!m_webView->priv->transparent);
m_nonCompositedContentLayer->setSize(pageSize);
if (core(m_webView)->settings()->acceleratedDrawingEnabled())
m_nonCompositedContentLayer->setAcceleratesDrawing(true);
#ifndef NDEBUG
m_rootLayer->setName("Root layer");
m_nonCompositedContentLayer->setName("Non-composited content");
#endif
m_rootLayer->addChild(m_nonCompositedContentLayer.get());
m_nonCompositedContentLayer->setNeedsDisplay();
scheduleLayerFlush();
}
AcceleratedCompositingContext::~AcceleratedCompositingContext()
{
if (m_layerFlushTimerCallbackId)
g_source_remove(m_layerFlushTimerCallbackId);
}
bool AcceleratedCompositingContext::enabled()
{
return m_rootLayer;
}
bool AcceleratedCompositingContext::renderLayersToWindow(cairo_t*, const IntRect& clipRect)
{
notImplemented();
return true;
}
void AcceleratedCompositingContext::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
{
if (!graphicsLayer) {
gtk_container_remove(GTK_CONTAINER(m_webView), m_rootLayerEmbedder);
m_rootLayerEmbedder = 0;
m_rootLayer = nullptr;
m_nonCompositedContentLayer = nullptr;
return;
}
if (!m_rootLayerEmbedder) {
m_rootLayerEmbedder = gtk_clutter_embed_new();
gtk_container_add(GTK_CONTAINER(m_webView), m_rootLayerEmbedder);
GtkAllocation allocation;
gtk_widget_get_allocation(GTK_WIDGET(m_webView), &allocation);
gtk_widget_size_allocate(GTK_WIDGET(m_rootLayerEmbedder), &allocation);
gtk_widget_show(m_rootLayerEmbedder);
}
initialize();
m_nonCompositedContentLayer->removeAllChildren();
m_nonCompositedContentLayer->addChild(graphicsLayer);
if (graphicsLayer) {
ClutterColor stageColor = { 0xFF, 0xFF, 0xFF, 0xFF };
ClutterActor* stage = gtk_clutter_embed_get_stage(GTK_CLUTTER_EMBED(m_rootLayerEmbedder));
clutter_actor_set_background_color(stage, &stageColor);
clutter_actor_add_child(stage, m_rootLayer->platformLayer());
}
scheduleLayerFlush();
}
void AcceleratedCompositingContext::setNonCompositedContentsNeedDisplay(const IntRect& rect)
{
if (!m_rootLayer)
return;
if (rect.isEmpty()) {
m_rootLayer->setNeedsDisplay();
return;
}
m_nonCompositedContentLayer->setNeedsDisplayInRect(rect);
scheduleLayerFlush();
}
void AcceleratedCompositingContext::resizeRootLayer(const IntSize& newSize)
{
if (!m_rootLayerEmbedder)
return;
if (m_rootLayer->size() == newSize)
return;
GtkAllocation allocation;
allocation.x = 0;
allocation.y = 0;
allocation.width = newSize.width();
allocation.height = newSize.height();
gtk_widget_size_allocate(GTK_WIDGET(m_rootLayerEmbedder), &allocation);
m_rootLayer->setSize(newSize);
FloatSize oldSize = m_nonCompositedContentLayer->size();
m_nonCompositedContentLayer->setSize(newSize);
if (newSize.width() > oldSize.width()) {
float height = std::min(static_cast<float>(newSize.height()), oldSize.height());
m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(oldSize.width(), 0, newSize.width() - oldSize.width(), height));
}
if (newSize.height() > oldSize.height())
m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(0, oldSize.height(), newSize.width(), newSize.height() - oldSize.height()));
m_nonCompositedContentLayer->setNeedsDisplayInRect(IntRect(IntPoint(), newSize));
scheduleLayerFlush();
}
void AcceleratedCompositingContext::scrollNonCompositedContents(const IntRect& scrollRect, const IntSize& scrollOffset)
{
m_nonCompositedContentLayer->setNeedsDisplayInRect(scrollRect);
scheduleLayerFlush();
}
gboolean AcceleratedCompositingContext::layerFlushTimerFiredCallback(AcceleratedCompositingContext* context)
{
context->flushAndRenderLayers();
return FALSE;
}
void AcceleratedCompositingContext::scheduleLayerFlush()
{
if (m_layerFlushTimerCallbackId)
return;
m_layerFlushTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, 0, reinterpret_cast<GSourceFunc>(layerFlushTimerFiredCallback), this, 0);
}
bool AcceleratedCompositingContext::flushPendingLayerChanges()
{
if (m_rootLayer) {
m_rootLayer->flushCompositingStateForThisLayerOnly();
m_nonCompositedContentLayer->flushCompositingStateForThisLayerOnly();
}
return core(m_webView)->mainFrame()->view()->flushCompositingStateIncludingSubframes();
}
void AcceleratedCompositingContext::flushAndRenderLayers()
{
m_layerFlushTimerCallbackId = 0;
if (!enabled())
return;
Frame* frame = core(m_webView)->mainFrame();
if (!frame || !frame->contentRenderer() || !frame->view())
return;
frame->view()->updateLayoutAndStyleIfNeededRecursive();
if (!flushPendingLayerChanges())
return;
}
void AcceleratedCompositingContext::notifyAnimationStarted(const WebCore::GraphicsLayer*, double time)
{
notImplemented();
}
void AcceleratedCompositingContext::notifyFlushRequired(const WebCore::GraphicsLayer*)
{
notImplemented();
}
void AcceleratedCompositingContext::paintContents(const WebCore::GraphicsLayer*, WebCore::GraphicsContext& context, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect& rectToPaint)
{
context.save();
context.clip(rectToPaint);
core(m_webView)->mainFrame()->view()->paint(&context, rectToPaint);
context.restore();
}
}
#endif // USE(ACCELERATED_COMPOSITING) && USE(CLUTTER)