55136bba5b4e498eca17f1c079a2b4974d90666b
[WebKit-https.git] / Source / WebCore / platform / graphics / blackberry / LayerWebKitThread.cpp
1 /*
2  * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
3  * Copyright (C) 2010 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33
34 #if USE(ACCELERATED_COMPOSITING)
35
36 #include "LayerWebKitThread.h"
37
38 #include "GraphicsContext.h"
39 #include "InstrumentedPlatformCanvas.h"
40 #include "LayerCompositingThread.h"
41 #include "LayerMessage.h"
42 #include "PlatformContextSkia.h"
43 #include "RenderLayerBacking.h"
44 #include "TransformationMatrix.h"
45
46 #include <BlackBerryPlatformGraphics.h>
47 #include <wtf/CurrentTime.h>
48
49 namespace WebCore {
50
51 using namespace std;
52
53 PassRefPtr<LayerWebKitThread> LayerWebKitThread::create(LayerType type, GraphicsLayerBlackBerry* owner)
54 {
55     return adoptRef(new LayerWebKitThread(type, owner));
56 }
57
58 LayerWebKitThread::LayerWebKitThread(LayerType type, GraphicsLayerBlackBerry* owner)
59     : LayerData(type)
60     , m_owner(owner)
61     , m_superlayer(0)
62     , m_contents(0)
63     , m_scale(1.0)
64     , m_isDrawable(false)
65     , m_isMask(false)
66 {
67     m_tiler = LayerTiler::create(this);
68     m_layerCompositingThread = LayerCompositingThread::create(type, m_tiler);
69 }
70
71 LayerWebKitThread::~LayerWebKitThread()
72 {
73     m_layerCompositingThread->clearAnimations();
74
75     if (m_frontBufferLock)
76         pthread_mutex_destroy(m_frontBufferLock);
77
78     m_tiler->layerWebKitThreadDestroyed();
79
80     // Our superlayer should be holding a reference to us so there should be no
81     // way for us to be destroyed while we still have a superlayer.
82     ASSERT(!superlayer());
83
84     // Remove the superlayer reference from all sublayers.
85     removeAllSublayers();
86 }
87
88 SkBitmap LayerWebKitThread::paintContents(const IntRect& contentsRect, double scale, bool* isSolidColor, Color* color)
89 {
90     // Don't try to allocate image data bigger than this. This should be big
91     // enough to accomodate a huge iScroll use case.
92     // FIXME: This is a hack to work around a crash bug on maps.bing.com where
93     // a (visually empty) layer becomes too big.
94     static const int maximumBitmapSizeInBytes = 40 * 1024 * 1024;
95     static const int bytesPerPixel = 4;
96
97     if (isSolidColor)
98         *isSolidColor = false;
99
100     if (contentsRect.width() * contentsRect.height() * bytesPerPixel > maximumBitmapSizeInBytes)
101         return SkBitmap();
102
103     SkBitmap bitmap;
104
105     // Keep the canvas alive until we're done extracting its pixels
106     OwnPtr<InstrumentedPlatformCanvas> canvas;
107
108     if (drawsContent()) { // Layer contents must be drawn into a canvas.
109         IntRect untransformedContentsRect = contentsRect;
110
111         canvas = adoptPtr(new InstrumentedPlatformCanvas(contentsRect.width(), contentsRect.height(), false, 0));
112         PlatformContextSkia skiaContext(canvas.get());
113
114         GraphicsContext graphicsContext(&skiaContext);
115         graphicsContext.translate(-contentsRect.x(), -contentsRect.y());
116
117         if (scale != 1.0) {
118             TransformationMatrix matrix;
119             matrix.scale(1.0 / scale);
120             untransformedContentsRect = matrix.mapRect(contentsRect);
121
122             // We extract from the contentsRect but draw a slightly larger region than
123             // we were told to, in order to avoid pixels being rendered only partially.
124             const int atLeastOneDevicePixel = static_cast<int>(ceilf(1.0 / scale));
125             untransformedContentsRect.inflate(atLeastOneDevicePixel);
126
127             graphicsContext.scale(FloatSize(scale, scale));
128         }
129
130         // RenderLayerBacking doesn't always clip, so we need to do this by ourselves.
131         graphicsContext.clip(untransformedContentsRect);
132         m_owner->paintGraphicsLayerContents(graphicsContext, untransformedContentsRect);
133
134         bitmap = canvas->getDevice()->accessBitmap(false);
135         if (isSolidColor) {
136             *isSolidColor = canvas->isSolidColor();
137             if (color)
138                 *color = canvas->solidColor();
139         }
140     }
141
142     ASSERT(!bitmap.isNull());
143
144     // FIXME: do we need to support more image configurations?
145     ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
146     if (bitmap.config() != SkBitmap::kARGB_8888_Config)
147         return SkBitmap();
148
149     return bitmap;
150 }
151
152 bool LayerWebKitThread::contentsVisible(const IntRect& contentsRect) const
153 {
154     if (!m_owner)
155         return false;
156
157     return m_owner->contentsVisible(contentsRect);
158 }
159
160 void LayerWebKitThread::createFrontBufferLock()
161 {
162     pthread_mutexattr_t mutexAttributes;
163     pthread_mutexattr_init(&mutexAttributes);
164     m_frontBufferLock = new pthread_mutex_t;
165     pthread_mutex_init(m_frontBufferLock, &mutexAttributes);
166 }
167
168 void LayerWebKitThread::updateTextureContentsIfNeeded()
169 {
170     m_tiler->updateTextureContentsIfNeeded(m_isMask ? 1.0 : contentsScale());
171 }
172
173 void LayerWebKitThread::setContents(Image* contents)
174 {
175     // Check if the image has changed.
176     if (m_contents == contents)
177         return;
178     m_contents = contents;
179     setNeedsTexture(m_isDrawable && (this->contents() || drawsContent() || pluginView()));
180
181     if (m_contents)
182         setNeedsDisplay();
183     else
184         setNeedsCommit();
185 }
186
187 void LayerWebKitThread::setDrawable(bool isDrawable)
188 {
189     if (m_isDrawable == isDrawable)
190         return;
191
192     m_isDrawable = isDrawable;
193
194     setNeedsTexture(m_isDrawable && (drawsContent() || contents() || pluginView() || mediaPlayer() || canvas()));
195     setNeedsCommit();
196 }
197
198 void LayerWebKitThread::setNeedsCommit()
199 {
200     // Call notifySyncRequired(), which in this implementation plumbs through to
201     // call scheduleRootLayerCommit() on the WebView, which will cause us to commit
202     // changes done on the WebKit thread for display on the Compositing thread.
203     if (m_owner)
204         m_owner->notifySyncRequired();
205 }
206
207 void LayerWebKitThread::notifyAnimationStarted(double time)
208 {
209     if (m_owner)
210         m_owner->notifyAnimationStarted(time);
211 }
212
213 void LayerWebKitThread::commitOnWebKitThread(double scale)
214 {
215     // Updating texture contents require the latest visibility info.
216     updateTextureContents(scale);
217
218     // Make sure all animations are started at the same time
219     // to avoid showing animations out-of-sync.
220     // Do this after updating texture contents, because that can be a slow
221     // operation.
222     startAnimations(currentTime());
223 }
224
225 void LayerWebKitThread::startAnimations(double time)
226 {
227     for (size_t i = 0; i < m_runningAnimations.size(); ++i) {
228         if (!m_runningAnimations[i]->startTime()) {
229             m_runningAnimations[i]->setStartTime(time);
230             notifyAnimationStarted(time);
231         }
232     }
233
234     size_t listSize = m_sublayers.size();
235     for (size_t i = 0; i < listSize; i++)
236         m_sublayers[i]->startAnimations(time);
237 }
238
239 void LayerWebKitThread::updateTextureContents(double scale)
240 {
241     if (m_scale != scale) {
242         m_scale = scale;
243
244         // Only web content can redraw at the new scale.
245         // Canvas, images, video etc can't.
246         if (drawsContent())
247             setNeedsDisplay();
248     }
249
250     updateTextureContentsIfNeeded();
251
252     if (includeVisibility()) {
253         // The RenderLayerBacking cast looks unsafe given that there are two classes
254         // derived from GraphicsLayerClient but this code is only reachable for
255         // things that produce RenderLayerBacking derivatives; i.e., plugins and media.
256         RenderLayer* renderLayer(static_cast<RenderLayerBacking*>(m_owner->client())->owningLayer());
257         bool isVisible(renderLayer->hasVisibleContent() || renderLayer->hasVisibleDescendant());
258         if (m_isVisible != isVisible) {
259             m_isVisible = isVisible;
260             setNeedsCommit();
261         }
262     }
263
264     size_t listSize = m_sublayers.size();
265     for (size_t i = 0; i < listSize; i++)
266         m_sublayers[i]->updateTextureContents(scale);
267
268     if (maskLayer())
269         maskLayer()->updateTextureContents(scale);
270
271     if (replicaLayer())
272         replicaLayer()->updateTextureContents(scale);
273 }
274
275 void LayerWebKitThread::commitOnCompositingThread()
276 {
277     FloatPoint oldPosition = m_position;
278     m_position += m_absoluteOffset;
279     // Copy the base variables from this object into m_layerCompositingThread
280     replicate(m_layerCompositingThread.get());
281     m_position = oldPosition;
282     updateLayerHierarchy();
283     m_tiler->commitPendingTextureUploads();
284
285     size_t listSize = m_sublayers.size();
286     for (size_t i = 0; i < listSize; i++)
287         m_sublayers[i]->commitOnCompositingThread();
288
289     if (maskLayer()) {
290         maskLayer()->commitOnCompositingThread();
291         layerCompositingThread()->setMaskLayer(maskLayer()->layerCompositingThread());
292     } else
293         layerCompositingThread()->setMaskLayer(0);
294
295     if (replicaLayer()) {
296         replicaLayer()->commitOnCompositingThread();
297         layerCompositingThread()->setReplicaLayer(replicaLayer()->layerCompositingThread());
298     } else
299         layerCompositingThread()->setReplicaLayer(0);
300 }
301
302 void LayerWebKitThread::addSublayer(PassRefPtr<LayerWebKitThread> sublayer)
303 {
304     insertSublayer(sublayer, numSublayers());
305 }
306
307 void LayerWebKitThread::insertSublayer(PassRefPtr<LayerWebKitThread> sublayer, size_t index)
308 {
309     sublayer->removeFromSuperlayer();
310     index = min(index, m_sublayers.size());
311     sublayer->setSuperlayer(this);
312     m_sublayers.insert(index, sublayer);
313
314     setNeedsCommit();
315 }
316
317 void LayerWebKitThread::removeFromSuperlayer()
318 {
319     if (m_superlayer)
320         m_superlayer->removeSublayer(this);
321 }
322
323 void LayerWebKitThread::removeSublayer(LayerWebKitThread* sublayer)
324 {
325     int foundIndex = indexOfSublayer(sublayer);
326     if (foundIndex == -1)
327         return;
328
329     sublayer->setSuperlayer(0);
330     m_sublayers.remove(foundIndex);
331
332     setNeedsCommit();
333 }
334
335 void LayerWebKitThread::replaceSublayer(LayerWebKitThread* reference, PassRefPtr<LayerWebKitThread> newLayer)
336 {
337     ASSERT_ARG(reference, reference);
338     ASSERT_ARG(reference, reference->superlayer() == this);
339
340     if (reference == newLayer)
341         return;
342
343     int referenceIndex = indexOfSublayer(reference);
344     if (referenceIndex == -1) {
345         ASSERT_NOT_REACHED();
346         return;
347     }
348
349     reference->removeFromSuperlayer();
350
351     if (newLayer) {
352         newLayer->removeFromSuperlayer();
353         insertSublayer(newLayer, referenceIndex);
354     }
355 }
356
357 int LayerWebKitThread::indexOfSublayer(const LayerWebKitThread* reference)
358 {
359     for (size_t i = 0; i < m_sublayers.size(); i++) {
360         if (m_sublayers[i] == reference)
361             return i;
362     }
363     return -1;
364 }
365
366 void LayerWebKitThread::setBounds(const IntSize& size)
367 {
368     if (m_bounds == size)
369         return;
370
371     bool firstResize = !m_bounds.width() && !m_bounds.height() && size.width() && size.height();
372
373     m_bounds = size;
374
375     boundsChanged();
376
377     if (firstResize)
378         setNeedsDisplay();
379     else
380         setNeedsCommit();
381 }
382
383 void LayerWebKitThread::setFrame(const FloatRect& rect)
384 {
385     if (rect == m_frame)
386       return;
387
388     m_frame = rect;
389     setNeedsDisplay();
390 }
391
392 const LayerWebKitThread* LayerWebKitThread::rootLayer() const
393 {
394     const LayerWebKitThread* layer = this;
395     LayerWebKitThread* superlayer = layer->superlayer();
396
397     while (superlayer) {
398         layer = superlayer;
399         superlayer = superlayer->superlayer();
400     }
401     return layer;
402 }
403
404 void LayerWebKitThread::removeAllSublayers()
405 {
406     while (m_sublayers.size()) {
407         RefPtr<LayerWebKitThread> layer = m_sublayers[0].get();
408         ASSERT(layer->superlayer());
409         layer->removeFromSuperlayer();
410     }
411     setNeedsCommit();
412 }
413
414 void LayerWebKitThread::setSublayers(const Vector<RefPtr<LayerWebKitThread> >& sublayers)
415 {
416     if (sublayers == m_sublayers)
417         return;
418
419     removeAllSublayers();
420     size_t listSize = sublayers.size();
421     for (size_t i = 0; i < listSize; i++)
422         addSublayer(sublayers[i]);
423 }
424
425 void LayerWebKitThread::setNeedsDisplayInRect(const FloatRect& dirtyRect)
426 {
427     m_tiler->setNeedsDisplay(dirtyRect);
428     setNeedsCommit(); // FIXME: Replace this with a more targeted message for dirty rect handling with plugin content?
429 }
430
431 void LayerWebKitThread::setNeedsDisplay()
432 {
433     m_tiler->setNeedsDisplay();
434     setNeedsCommit(); // FIXME: Replace this with a more targeted message for dirty rect handling with plugin content?
435 }
436
437 void LayerWebKitThread::updateLayerHierarchy()
438 {
439     m_layerCompositingThread->setSuperlayer(superlayer() ? superlayer()->m_layerCompositingThread.get() : 0);
440
441     Vector<RefPtr<LayerCompositingThread> > sublayers;
442     size_t listSize = m_sublayers.size();
443     for (size_t i = 0; i < listSize; i++)
444         sublayers.append(m_sublayers[i]->m_layerCompositingThread.get());
445     m_layerCompositingThread->setSublayers(sublayers);
446 }
447
448 void LayerWebKitThread::setIsMask(bool isMask)
449 {
450     m_isMask = isMask;
451     if (isMask)
452         m_tiler->disableTiling(true);
453 }
454
455 }
456
457 #endif // USE(ACCELERATED_COMPOSITING)