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 "LayerCompositingThread.h" 40#include "LayerMessage.h" 41#include "RenderLayerBacking.h" 42#include "TransformationMatrix.h" 43 44#include <BlackBerryPlatformGraphics.h> 45#include <wtf/CurrentTime.h> 46 47namespace WebCore { 48 49using namespace std; 50 51PassRefPtr<LayerWebKitThread> LayerWebKitThread::create(LayerType type, GraphicsLayerBlackBerry* owner) 52{ 53 return adoptRef(new LayerWebKitThread(type, owner)); 54} 55 56LayerWebKitThread::LayerWebKitThread(LayerType type, GraphicsLayerBlackBerry* owner) 57 : LayerData(type) 58 , m_owner(owner) 59 , m_superlayer(0) 60 , m_contents(0) 61 , m_isDrawable(false) 62 , m_isMask(false) 63 , m_animationsChanged(false) 64 , m_clearOverrideOnCommit(false) 65#if ENABLE(CSS_FILTERS) 66 , m_filtersChanged(false) 67#endif 68 , m_didStartAnimations(false) 69{ 70 if (type == Layer) 71 m_tiler = LayerTiler::create(this); 72 m_layerCompositingThread = LayerCompositingThread::create(type, m_tiler.get()); 73} 74 75LayerWebKitThread::~LayerWebKitThread() 76{ 77 if (m_tiler) 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 removeAll(m_sublayers); 86 removeAll(m_overlays); 87} 88 89void LayerWebKitThread::paintContents(BlackBerry::Platform::Graphics::Buffer* buffer, const IntRect& contentsRect, double scale) 90{ 91 if (!drawsContent() && !contents()) 92 return; 93 94 if (!buffer) 95 return; 96 97 IntRect untransformedContentsRect = contentsRect; 98 FloatRect clipRect = contentsRect; 99 if (scale != 1.0) { 100 TransformationMatrix matrix; 101 matrix.scale(1.0 / scale); 102 untransformedContentsRect = matrix.mapRect(contentsRect); 103 clipRect = matrix.mapRect(clipRect); 104 105 // We extract from the contentsRect but draw a slightly larger region than 106 // we were told to, in order to avoid pixels being rendered only partially. 107 const int atLeastOneDevicePixel = static_cast<int>(ceilf(1.0 / scale)); 108 untransformedContentsRect.inflate(atLeastOneDevicePixel); 109 } 110 111 PlatformGraphicsContext* platformContext = lockBufferDrawable(buffer); 112 GraphicsContext graphicsContext(platformContext); 113 if (contents()) { 114 // Images needs to be centered and will be scaled to fit the bounds on the compositing thread 115 if (!contents()->size().isEmpty()) 116 graphicsContext.drawImage(contents(), ColorSpaceDeviceRGB, IntPoint(0, 0)); 117 } else { 118 graphicsContext.translate(-contentsRect.x(), -contentsRect.y()); 119 graphicsContext.scale(FloatSize(scale, scale)); 120 graphicsContext.clip(clipRect); 121 m_owner->paintGraphicsLayerContents(graphicsContext, untransformedContentsRect); 122 } 123 124 releaseBufferDrawable(buffer); 125} 126 127void LayerWebKitThread::updateTextureContentsIfNeeded() 128{ 129 if (m_tiler) 130 m_tiler->updateTextureContentsIfNeeded(m_isMask ? 1.0 : contentsScale()); 131} 132 133void LayerWebKitThread::commitPendingTextureUploads() 134{ 135 layerCompositingThread()->commitPendingTextureUploads(); 136} 137 138void LayerWebKitThread::setContents(Image* contents) 139{ 140 // Check if the image has changed. 141 if (m_contents == contents) { 142 // Set needs display for animated images. 143 if (contents) 144 setNeedsDisplay(); 145 return; 146 } 147 m_contents = contents; 148 setNeedsTexture(m_isDrawable && (this->contents() || drawsContent() || pluginView())); 149 150 if (m_contents) 151 setNeedsDisplay(); 152 else 153 setNeedsCommit(); 154 155 // If this layer contains a bitmap image it isn't rerendered at different scale (it is resolution independent) 156 m_contentsResolutionIndependent = static_cast<bool>(m_contents); 157} 158 159void LayerWebKitThread::setDrawable(bool isDrawable) 160{ 161 if (m_isDrawable == isDrawable) 162 return; 163 164 m_isDrawable = isDrawable; 165 166 setNeedsTexture(m_isDrawable && (drawsContent() || contents() || pluginView() || mediaPlayer())); 167 setNeedsCommit(); 168} 169 170void LayerWebKitThread::setNeedsCommit() 171{ 172 // Call notifyFlushRequired(), which in this implementation plumbs through to 173 // call scheduleRootLayerCommit() on the WebView, which will cause us to commit 174 // changes done on the WebKit thread for display on the Compositing thread. 175 if (m_owner) 176 m_owner->notifyFlushRequired(); 177} 178 179void LayerWebKitThread::notifyAnimationsStarted(double time) 180{ 181 if (m_didStartAnimations) { 182 m_didStartAnimations = false; 183 if (m_owner) 184 m_owner->notifyAnimationStarted(time); 185 } 186 187 size_t listSize = m_sublayers.size(); 188 for (size_t i = 0; i < listSize; ++i) 189 m_sublayers[i]->notifyAnimationsStarted(time); 190 191 listSize = m_overlays.size(); 192 for (size_t i = 0; i < listSize; ++i) 193 m_overlays[i]->notifyAnimationsStarted(time); 194} 195 196void LayerWebKitThread::commitOnWebKitThread(double scale) 197{ 198 // Updating texture contents require the latest visibility info. 199 updateTextureContents(scale); 200} 201 202bool LayerWebKitThread::startAnimations(double time) 203{ 204 bool didStartAnimations = false; 205 for (size_t i = 0; i < m_runningAnimations.size(); ++i) { 206 if (!m_runningAnimations[i]->startTime()) { 207 m_runningAnimations[i]->setStartTime(time); 208 m_didStartAnimations = didStartAnimations = true; 209 } 210 } 211 212 size_t listSize = m_sublayers.size(); 213 for (size_t i = 0; i < listSize; ++i) 214 didStartAnimations |= m_sublayers[i]->startAnimations(time); 215 216 listSize = m_overlays.size(); 217 for (size_t i = 0; i < listSize; ++i) 218 didStartAnimations |= m_overlays[i]->startAnimations(time); 219 220 return didStartAnimations; 221} 222 223void LayerWebKitThread::updateTextureContents(double scale) 224{ 225 if (m_contentsScale != scale) { 226 m_contentsScale = scale; 227 228 // Only web content can redraw at the new scale. 229 // Canvas, images, video etc can't. 230 if (drawsContent()) 231 setNeedsDisplay(); 232 } 233 234 updateTextureContentsIfNeeded(); 235 236 if (includeVisibility()) { 237 // The RenderLayerBacking cast looks unsafe given that there are two classes 238 // derived from GraphicsLayerClient but this code is only reachable for 239 // things that produce RenderLayerBacking derivatives; i.e., plugins and media. 240 RenderLayer* renderLayer(static_cast<RenderLayerBacking*>(m_owner->client())->owningLayer()); 241 bool isVisible(renderLayer->hasVisibleContent() || renderLayer->hasVisibleDescendant()); 242 if (m_isVisible != isVisible) { 243 m_isVisible = isVisible; 244 setNeedsCommit(); 245 } 246 } 247 248 size_t listSize = m_sublayers.size(); 249 for (size_t i = 0; i < listSize; ++i) 250 m_sublayers[i]->updateTextureContents(scale); 251 252 listSize = m_overlays.size(); 253 for (size_t i = 0; i < listSize; ++i) 254 m_overlays[i]->updateTextureContents(scale); 255 256 if (maskLayer()) 257 maskLayer()->updateTextureContents(scale); 258 259 if (replicaLayer()) 260 replicaLayer()->updateTextureContents(scale); 261} 262 263void LayerWebKitThread::commitOnCompositingThread() 264{ 265 FloatPoint oldPosition = m_position; 266 m_position += m_absoluteOffset; 267 // Copy the base variables from this object into m_layerCompositingThread 268 replicate(m_layerCompositingThread.get()); 269#if ENABLE(CSS_FILTERS) 270 if (m_filtersChanged) { 271 m_filtersChanged = false; 272 m_layerCompositingThread->setFilterOperationsChanged(true); 273 } 274#endif 275 if (m_animationsChanged) { 276 m_layerCompositingThread->setRunningAnimations(m_runningAnimations); 277 m_layerCompositingThread->setSuspendedAnimations(m_suspendedAnimations); 278 m_animationsChanged = false; 279 } 280 if (m_clearOverrideOnCommit) { 281 m_layerCompositingThread->clearOverride(); 282 m_clearOverrideOnCommit = false; 283 } 284 m_position = oldPosition; 285 updateLayerHierarchy(); 286 287 commitPendingTextureUploads(); 288 289 size_t listSize = m_sublayers.size(); 290 for (size_t i = 0; i < listSize; ++i) 291 m_sublayers[i]->commitOnCompositingThread(); 292 293 listSize = m_overlays.size(); 294 for (size_t i = 0; i < listSize; ++i) 295 m_overlays[i]->commitOnCompositingThread(); 296 297 if (maskLayer()) { 298 maskLayer()->commitOnCompositingThread(); 299 layerCompositingThread()->setMaskLayer(maskLayer()->layerCompositingThread()); 300 } else 301 layerCompositingThread()->setMaskLayer(0); 302 303 if (replicaLayer()) { 304 replicaLayer()->commitOnCompositingThread(); 305 layerCompositingThread()->setReplicaLayer(replicaLayer()->layerCompositingThread()); 306 } else 307 layerCompositingThread()->setReplicaLayer(0); 308} 309 310void LayerWebKitThread::addSublayer(PassRefPtr<LayerWebKitThread> sublayer) 311{ 312 insert(m_sublayers, sublayer, m_sublayers.size()); 313} 314 315void LayerWebKitThread::addOverlay(PassRefPtr<LayerWebKitThread> overlay) 316{ 317 insert(m_overlays, overlay, m_overlays.size()); 318} 319 320void LayerWebKitThread::insert(Vector<RefPtr<LayerWebKitThread> >& list, PassRefPtr<LayerWebKitThread> sublayer, size_t index) 321{ 322 sublayer->removeFromSuperlayer(); 323 index = min(index, list.size()); 324 sublayer->setSuperlayer(this); 325 list.insert(index, sublayer); 326 327 setNeedsCommit(); 328} 329 330void LayerWebKitThread::removeFromSuperlayer() 331{ 332 if (m_superlayer) 333 m_superlayer->removeSublayerOrOverlay(this); 334} 335 336void LayerWebKitThread::removeSublayerOrOverlay(LayerWebKitThread* sublayer) 337{ 338 remove(m_sublayers, sublayer); 339 remove(m_overlays, sublayer); 340} 341 342void LayerWebKitThread::remove(Vector<RefPtr<LayerWebKitThread> >& vector, LayerWebKitThread* sublayer) 343{ 344 size_t foundIndex = vector.find(sublayer); 345 if (foundIndex == notFound) 346 return; 347 348 sublayer->setSuperlayer(0); 349 vector.remove(foundIndex); 350 351 setNeedsCommit(); 352} 353 354void LayerWebKitThread::replaceSublayer(LayerWebKitThread* reference, PassRefPtr<LayerWebKitThread> newLayer) 355{ 356 ASSERT_ARG(reference, reference); 357 ASSERT_ARG(reference, reference->superlayer() == this); 358 359 if (reference == newLayer) 360 return; 361 362 size_t referenceIndex = m_sublayers.find(reference); 363 if (referenceIndex == notFound) { 364 ASSERT_NOT_REACHED(); 365 return; 366 } 367 368 reference->removeFromSuperlayer(); 369 370 if (newLayer) { 371 newLayer->removeFromSuperlayer(); 372 insertSublayer(newLayer, referenceIndex); 373 } 374} 375 376void LayerWebKitThread::setBounds(const IntSize& size) 377{ 378 if (m_bounds == size) 379 return; 380 381 bool firstResize = !m_bounds.width() && !m_bounds.height() && size.width() && size.height(); 382 383 m_bounds = size; 384 385 boundsChanged(); 386 387 if (firstResize) 388 setNeedsDisplay(); 389 else 390 setNeedsCommit(); 391} 392 393void LayerWebKitThread::setFrame(const FloatRect& rect) 394{ 395 if (rect == m_frame) 396 return; 397 398 m_frame = rect; 399 setNeedsDisplay(); 400} 401 402#if ENABLE(CSS_FILTERS) 403bool LayerWebKitThread::filtersCanBeComposited(const FilterOperations& filters) 404{ 405 // There is work associated with compositing filters, even if there are zero filters, 406 // so if there are no filters, claim we can't composite them. 407 if (!filters.size()) 408 return false; 409 410 for (unsigned i = 0; i < filters.size(); ++i) { 411 const FilterOperation* filterOperation = filters.at(i); 412 switch (filterOperation->getOperationType()) { 413 case FilterOperation::REFERENCE: 414#if ENABLE(CSS_SHADERS) 415 case FilterOperation::CUSTOM: 416#endif 417 return false; 418 default: 419 break; 420 } 421 } 422 423 return true; 424} 425#endif 426 427const LayerWebKitThread* LayerWebKitThread::rootLayer() const 428{ 429 const LayerWebKitThread* layer = this; 430 LayerWebKitThread* superlayer = layer->superlayer(); 431 432 while (superlayer) { 433 layer = superlayer; 434 superlayer = superlayer->superlayer(); 435 } 436 return layer; 437} 438 439void LayerWebKitThread::removeAll(Vector<RefPtr<LayerWebKitThread> >& vector) 440{ 441 if (!vector.size()) 442 return; 443 444 while (vector.size()) { 445 RefPtr<LayerWebKitThread> layer = vector[0].get(); 446 ASSERT(layer->superlayer() == this); 447 layer->removeFromSuperlayer(); 448 } 449 450 setNeedsCommit(); 451} 452 453void LayerWebKitThread::setSublayers(const Vector<RefPtr<LayerWebKitThread> >& sublayers) 454{ 455 if (sublayers == m_sublayers) 456 return; 457 458 removeAllSublayers(); 459 size_t listSize = sublayers.size(); 460 for (size_t i = 0; i < listSize; ++i) 461 addSublayer(sublayers[i]); 462} 463 464void LayerWebKitThread::setNeedsDisplayInRect(const FloatRect& dirtyRect) 465{ 466 if (m_tiler) 467 m_tiler->setNeedsDisplay(dirtyRect); 468 setNeedsCommit(); // FIXME: Replace this with a more targeted message for dirty rect handling with plugin content? 469} 470 471void LayerWebKitThread::setNeedsDisplay() 472{ 473 if (m_tiler) 474 m_tiler->setNeedsDisplay(); 475 setNeedsCommit(); // FIXME: Replace this with a more targeted message for dirty rect handling with plugin content? 476} 477 478void LayerWebKitThread::updateLayerHierarchy() 479{ 480 m_layerCompositingThread->setSuperlayer(superlayer() ? superlayer()->m_layerCompositingThread.get() : 0); 481 482 Vector<RefPtr<LayerCompositingThread> > sublayers; 483 size_t listSize = m_overlays.size(); 484 for (size_t i = 0; i < listSize; ++i) 485 sublayers.append(m_overlays[i]->m_layerCompositingThread.get()); 486 listSize = m_sublayers.size(); 487 for (size_t i = 0; i < listSize; ++i) 488 sublayers.append(m_sublayers[i]->m_layerCompositingThread.get()); 489 m_layerCompositingThread->setSublayers(sublayers); 490} 491 492void LayerWebKitThread::setIsMask(bool isMask) 493{ 494 m_isMask = isMask; 495 if (isMask && m_tiler) 496 m_tiler->setNeedsBacking(true); 497} 498 499void LayerWebKitThread::setRunningAnimations(const Vector<RefPtr<LayerAnimation> >& animations) 500{ 501 m_runningAnimations = animations; 502 m_animationsChanged = true; 503 setNeedsCommit(); 504} 505 506void LayerWebKitThread::setSuspendedAnimations(const Vector<RefPtr<LayerAnimation> >& animations) 507{ 508 m_suspendedAnimations = animations; 509 m_animationsChanged = true; 510 setNeedsCommit(); 511} 512 513void LayerWebKitThread::releaseLayerResources() 514{ 515 deleteTextures(); 516 517 size_t listSize = m_sublayers.size(); 518 for (size_t i = 0; i < listSize; ++i) 519 m_sublayers[i]->releaseLayerResources(); 520 521 listSize = m_overlays.size(); 522 for (size_t i = 0; i < listSize; ++i) 523 m_overlays[i]->releaseLayerResources(); 524 525 if (maskLayer()) 526 maskLayer()->releaseLayerResources(); 527 528 if (replicaLayer()) 529 replicaLayer()->releaseLayerResources(); 530} 531 532IntRect LayerWebKitThread::mapFromTransformed(const IntRect& contentsRect, double scale) 533{ 534 IntRect untransformedContentsRect = contentsRect; 535 536 if (scale != 1.0) { 537 TransformationMatrix matrix; 538 matrix.scale(1.0 / scale); 539 untransformedContentsRect = matrix.mapRect(contentsRect); 540 541 // We extract from the contentsRect but draw a slightly larger region than 542 // we were told to, in order to avoid pixels being rendered only partially. 543 const int atLeastOneDevicePixel = static_cast<int>(ceilf(1.0 / scale)); 544 untransformedContentsRect.inflate(atLeastOneDevicePixel); 545 } 546 547 return untransformedContentsRect; 548} 549 550} 551 552#endif // USE(ACCELERATED_COMPOSITING) 553