64eb901758bd4eae8a9487ba1dc019672a9e5aa5
[WebKit-https.git] / Source / WebKit / gtk / WebCoreSupport / AcceleratedCompositingContextGL.cpp
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_GL)
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 "TextureMapperGL.h"
31 #include "TextureMapperLayer.h"
32 #include "webkitwebviewprivate.h"
33 #include <GL/gl.h>
34 #include <cairo.h>
35 #include <gdk/gdk.h>
36 #include <gtk/gtk.h>
37
38 #if defined(GDK_WINDOWING_X11)
39 #define Region XRegion
40 #define Font XFont
41 #define Cursor XCursor
42 #define Screen XScreen
43 #include <gdk/gdkx.h>
44 #endif
45
46 using namespace WebCore;
47
48 namespace WebKit {
49
50 AcceleratedCompositingContext::AcceleratedCompositingContext(WebKitWebView* webView)
51     : m_webView(webView)
52     , m_syncTimerCallbackId(0)
53     , m_rootTextureMapperLayer(0)
54 {
55 }
56
57 AcceleratedCompositingContext::~AcceleratedCompositingContext()
58 {
59     if (m_syncTimerCallbackId)
60         g_source_remove(m_syncTimerCallbackId);
61 }
62
63 bool AcceleratedCompositingContext::enabled()
64 {
65     return m_rootTextureMapperLayer && m_textureMapper;
66 }
67
68 GLContext* AcceleratedCompositingContext::glContext()
69 {
70     if (m_context)
71         return m_context.get();
72
73 #if defined(GDK_WINDOWING_X11)
74     // FIXME: Gracefully account for situations where we do not have a realized window.
75     GdkWindow* gdkWindow = gtk_widget_get_window(GTK_WIDGET(m_webView));
76     if (gdkWindow && gdk_window_has_native(gdkWindow))
77         m_context = GLContext::createContextForWindow(GDK_WINDOW_XID(gdkWindow), GLContext::sharingContext());
78 #endif
79
80     return m_context.get();
81 }
82
83 bool AcceleratedCompositingContext::renderLayersToWindow(cairo_t*, const IntRect& clipRect)
84 {
85     if (!enabled())
86         return false;
87
88     GLContext* context = glContext();
89     if (!context)
90         return false;
91
92     if (!context->makeContextCurrent())
93         return false;
94
95     GtkAllocation allocation;
96     gtk_widget_get_allocation(GTK_WIDGET(m_webView), &allocation);
97     glViewport(0, 0, allocation.width, allocation.height);
98
99     m_textureMapper->beginPainting();
100     m_rootTextureMapperLayer->paint();
101     m_textureMapper->endPainting();
102
103     context->swapBuffers();
104     return true;
105 }
106
107 void AcceleratedCompositingContext::attachRootGraphicsLayer(GraphicsLayer* graphicsLayer)
108 {
109     if (!graphicsLayer) {
110         m_rootGraphicsLayer.clear();
111         m_rootTextureMapperLayer = 0;
112         m_context.clear();
113         return;
114     }
115
116     m_rootGraphicsLayer = GraphicsLayer::create(this);
117     m_rootTextureMapperLayer = toTextureMapperLayer(m_rootGraphicsLayer.get());
118     m_rootGraphicsLayer->addChild(graphicsLayer);
119     m_rootGraphicsLayer->setDrawsContent(true);
120     m_rootGraphicsLayer->setMasksToBounds(false);
121     m_rootGraphicsLayer->setNeedsDisplay();
122     m_rootGraphicsLayer->setSize(core(m_webView)->mainFrame()->view()->frameRect().size());
123
124     GLContext* context = glContext();
125     if (!context)
126         return;
127
128     // The context needs to be active when creating the texture mapper. It's fine to
129     // avoid calling swapBuffers here, because it will just initialize shaders.
130     if (!context->makeContextCurrent())
131         return;
132
133     GtkAllocation allocation;
134     gtk_widget_get_allocation(GTK_WIDGET(m_webView), &allocation);
135     glViewport(0, 0, allocation.width, allocation.height);
136
137     m_textureMapper = TextureMapperGL::create();
138     m_rootTextureMapperLayer->setTextureMapper(m_textureMapper.get());
139     m_rootGraphicsLayer->syncCompositingStateForThisLayerOnly();
140 }
141
142 void AcceleratedCompositingContext::scheduleRootLayerRepaint(const IntRect& rect)
143 {
144     if (!m_rootGraphicsLayer)
145         return;
146     if (rect.isEmpty()) {
147         m_rootGraphicsLayer->setNeedsDisplay();
148         return;
149     }
150     m_rootGraphicsLayer->setNeedsDisplayInRect(rect);
151 }
152
153 void AcceleratedCompositingContext::resizeRootLayer(const IntSize& size)
154 {
155     if (!m_rootGraphicsLayer)
156         return;
157     m_rootGraphicsLayer->setSize(size);
158     m_rootGraphicsLayer->syncCompositingStateForThisLayerOnly();
159 }
160
161 static gboolean syncLayersTimeoutCallback(AcceleratedCompositingContext* context)
162 {
163     context->syncLayersTimeout();
164     return FALSE;
165 }
166
167 void AcceleratedCompositingContext::markForSync()
168 {
169     if (m_syncTimerCallbackId)
170         return;
171
172     // We use a GLib timer because otherwise GTK+ event handling during
173     // dragging can starve WebCore timers, which have a lower priority.
174     m_syncTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, 0, reinterpret_cast<GSourceFunc>(syncLayersTimeoutCallback), this, 0);
175 }
176
177 void AcceleratedCompositingContext::syncLayersNow()
178 {
179     if (m_rootGraphicsLayer)
180         m_rootGraphicsLayer->syncCompositingStateForThisLayerOnly();
181
182     core(m_webView)->mainFrame()->view()->syncCompositingStateIncludingSubframes();
183 }
184
185 void AcceleratedCompositingContext::syncLayersTimeout()
186 {
187     m_syncTimerCallbackId = 0;
188     syncLayersNow();
189     if (!m_rootGraphicsLayer)
190         return;
191
192     if (toTextureMapperLayer(m_rootGraphicsLayer.get())->descendantsOrSelfHaveRunningAnimations())
193         m_syncTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, 1000.0 / 60.0, reinterpret_cast<GSourceFunc>(syncLayersTimeoutCallback), this, 0);
194
195     renderLayersToWindow(0, IntRect());
196 }
197
198 void AcceleratedCompositingContext::notifyAnimationStarted(const GraphicsLayer*, double time)
199 {
200
201 }
202 void AcceleratedCompositingContext::notifySyncRequired(const GraphicsLayer*)
203 {
204
205 }
206
207 void AcceleratedCompositingContext::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& rectToPaint)
208 {
209     cairo_t* cr = context.platformContext()->cr();
210     copyRectFromCairoSurfaceToContext(m_webView->priv->backingStore->cairoSurface(), cr,
211                                       IntSize(), rectToPaint);
212 }
213
214 bool AcceleratedCompositingContext::showDebugBorders(const GraphicsLayer*) const
215 {
216     return false;
217 }
218
219 bool AcceleratedCompositingContext::showRepaintCounter(const GraphicsLayer*) const
220 {
221     return false;
222 }
223
224 } // namespace WebKit
225
226 #endif // USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER_GL)