1/* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32#include "config.h" 33 34#if USE(ACCELERATED_COMPOSITING) 35#include "LayerRendererChromium.h" 36 37#include "Canvas2DLayerChromium.h" 38#include "Extensions3DChromium.h" 39#include "FloatQuad.h" 40#include "GeometryBinding.h" 41#include "GraphicsContext3D.h" 42#include "LayerChromium.h" 43#include "LayerTexture.h" 44#include "NotImplemented.h" 45#include "TextStream.h" 46#include "TextureManager.h" 47#include "TraceEvent.h" 48#include "WebGLLayerChromium.h" 49#include "cc/CCLayerImpl.h" 50#if USE(SKIA) 51#include "NativeImageSkia.h" 52#include "PlatformContextSkia.h" 53#elif USE(CG) 54#include <CoreGraphics/CGBitmapContext.h> 55#endif 56 57namespace WebCore { 58 59// FIXME: Make this limit adjustable and give it a useful value. 60static size_t textureMemoryLimitBytes = 64 * 1024 * 1024; 61 62static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top) 63{ 64 float deltaX = right - left; 65 float deltaY = top - bottom; 66 TransformationMatrix ortho; 67 if (!deltaX || !deltaY) 68 return ortho; 69 ortho.setM11(2.0f / deltaX); 70 ortho.setM41(-(right + left) / deltaX); 71 ortho.setM22(2.0f / deltaY); 72 ortho.setM42(-(top + bottom) / deltaY); 73 74 // Z component of vertices is always set to zero as we don't use the depth buffer 75 // while drawing. 76 ortho.setM33(0); 77 78 return ortho; 79} 80 81// Returns true if the matrix has no rotation, skew or perspective components to it. 82static bool isScaleOrTranslation(const TransformationMatrix& m) 83{ 84 return !m.m12() && !m.m13() && !m.m14() 85 && !m.m21() && !m.m23() && !m.m24() 86 && !m.m31() && !m.m32() && !m.m43() 87 && m.m44(); 88 89} 90 91bool LayerRendererChromium::compareLayerZ(const RefPtr<CCLayerImpl>& a, const RefPtr<CCLayerImpl>& b) 92{ 93 return a->drawDepth() < b->drawDepth(); 94} 95 96PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint) 97{ 98 if (!context) 99 return 0; 100 101 RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context, contentPaint))); 102 if (!layerRenderer->hardwareCompositing()) 103 return 0; 104 105 return layerRenderer.release(); 106} 107 108LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context, 109 PassOwnPtr<TilePaintInterface> contentPaint) 110 : m_viewportScrollPosition(IntPoint(-1, -1)) 111 , m_rootLayer(0) 112 , m_rootLayerContentPaint(contentPaint) 113 , m_currentShader(0) 114 , m_currentRenderSurface(0) 115 , m_offscreenFramebufferId(0) 116 , m_compositeOffscreen(false) 117 , m_context(context) 118 , m_childContextsWereCopied(false) 119 , m_contextSupportsLatch(false) 120 , m_defaultRenderSurface(0) 121{ 122 m_contextSupportsLatch = m_context->getExtensions()->supports("GL_CHROMIUM_latch"); 123 m_hardwareCompositing = initializeSharedObjects(); 124 m_rootLayerContentTiler = LayerTilerChromium::create(this, IntSize(256, 256), LayerTilerChromium::NoBorderTexels); 125 ASSERT(m_rootLayerContentTiler); 126 127 m_headsUpDisplay = CCHeadsUpDisplay::create(this); 128} 129 130LayerRendererChromium::~LayerRendererChromium() 131{ 132 m_headsUpDisplay.clear(); // Explicitly destroy the HUD before the TextureManager dies. 133 cleanupSharedObjects(); 134} 135 136GraphicsContext3D* LayerRendererChromium::context() 137{ 138 return m_context.get(); 139} 140 141void LayerRendererChromium::debugGLCall(GraphicsContext3D* context, const char* command, const char* file, int line) 142{ 143 unsigned long error = context->getError(); 144 if (error != GraphicsContext3D::NO_ERROR) 145 LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast<int>(error)); 146} 147 148void LayerRendererChromium::useShader(unsigned programId) 149{ 150 if (programId != m_currentShader) { 151 GLC(m_context.get(), m_context->useProgram(programId)); 152 m_currentShader = programId; 153 } 154} 155 156void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect) 157{ 158 m_rootLayerContentTiler->invalidateRect(dirtyRect); 159} 160 161void LayerRendererChromium::updateRootLayerContents() 162{ 163 TRACE_EVENT("LayerRendererChromium::updateRootLayerContents", this, 0); 164 m_rootLayerContentTiler->update(*m_rootLayerContentPaint, m_viewportVisibleRect); 165} 166 167void LayerRendererChromium::drawRootLayer() 168{ 169 TransformationMatrix scroll; 170 scroll.translate(-m_viewportVisibleRect.x(), -m_viewportVisibleRect.y()); 171 172 m_rootLayerContentTiler->uploadCanvas(); 173 m_rootLayerContentTiler->draw(m_viewportVisibleRect, scroll, 1.0f); 174} 175 176void LayerRendererChromium::setViewport(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition) 177{ 178 bool visibleRectChanged = m_viewportVisibleRect.size() != visibleRect.size(); 179 180 m_viewportVisibleRect = visibleRect; 181 m_viewportContentRect = contentRect; 182 m_viewportScrollPosition = scrollPosition; 183 184 if (visibleRectChanged) { 185 // Reset the current render surface to force an update of the viewport and 186 // projection matrix next time useRenderSurface is called. 187 m_currentRenderSurface = 0; 188 m_rootLayerContentTiler->invalidateEntireLayer(); 189 } 190} 191 192void LayerRendererChromium::updateAndDrawLayers() 193{ 194 ASSERT(m_hardwareCompositing); 195 196 if (!m_rootLayer) 197 return; 198 199 updateRootLayerContents(); 200 201 // Recheck that we still have a root layer. This may become null if 202 // compositing gets turned off during a paint operation. 203 if (!m_rootLayer) 204 return; 205 206 LayerList renderSurfaceLayerList; 207 208 updateLayers(renderSurfaceLayerList); 209 210 // Before drawLayers: 211 if (hardwareCompositing() && m_contextSupportsLatch) { 212 // FIXME: The multithreaded compositor case will not work as long as 213 // copyTexImage2D resolves to the parent texture, because the main 214 // thread can execute WebGL calls on the child context at any time, 215 // potentially clobbering the parent texture that is being renderered 216 // by the compositor thread. 217 if (m_childContextsWereCopied) { 218 Extensions3DChromium* parentExt = static_cast<Extensions3DChromium*>(m_context->getExtensions()); 219 // For each child context: 220 // glWaitLatch(Offscreen->Compositor); 221 ChildContextMap::iterator i = m_childContexts.begin(); 222 for (; i != m_childContexts.end(); ++i) { 223 Extensions3DChromium* childExt = static_cast<Extensions3DChromium*>(i->first->getExtensions()); 224 GC3Duint latchId; 225 childExt->getChildToParentLatchCHROMIUM(&latchId); 226 parentExt->waitLatchCHROMIUM(latchId); 227 } 228 } 229 // Reset to false to indicate that we have consumed the dirty child 230 // contexts' parent textures. (This is only useful when the compositor 231 // is multithreaded.) 232 m_childContextsWereCopied = false; 233 } 234 235 drawLayers(renderSurfaceLayerList); 236 237 m_textureManager->unprotectAllTextures(); 238 239 // After drawLayers: 240 if (hardwareCompositing() && m_contextSupportsLatch) { 241 Extensions3DChromium* parentExt = static_cast<Extensions3DChromium*>(m_context->getExtensions()); 242 // For each child context: 243 // glSetLatch(Compositor->Offscreen); 244 ChildContextMap::iterator i = m_childContexts.begin(); 245 for (; i != m_childContexts.end(); ++i) { 246 Extensions3DChromium* childExt = static_cast<Extensions3DChromium*>(i->first->getExtensions()); 247 GC3Duint latchId; 248 childExt->getParentToChildLatchCHROMIUM(&latchId); 249 parentExt->setLatchCHROMIUM(latchId); 250 } 251 } 252 253 if (isCompositingOffscreen()) 254 copyOffscreenTextureToDisplay(); 255} 256 257void LayerRendererChromium::updateLayers(LayerList& renderSurfaceLayerList) 258{ 259 TRACE_EVENT("LayerRendererChromium::updateLayers", this, 0); 260 m_rootLayer->createCCLayerImplIfNeeded(); 261 CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl(); 262 263 if (!rootDrawLayer->renderSurface()) 264 rootDrawLayer->createRenderSurface(); 265 ASSERT(rootDrawLayer->renderSurface()); 266 267 rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), m_viewportVisibleRect.size()); 268 269 IntRect rootScissorRect(m_viewportVisibleRect); 270 // The scissorRect should not include the scroll offset. 271 rootScissorRect.move(-m_viewportScrollPosition.x(), -m_viewportScrollPosition.y()); 272 rootDrawLayer->setScissorRect(rootScissorRect); 273 274 m_defaultRenderSurface = rootDrawLayer->renderSurface(); 275 276 renderSurfaceLayerList.append(rootDrawLayer); 277 278 TransformationMatrix identityMatrix; 279 m_defaultRenderSurface->m_layerList.clear(); 280 // Unfortunately, updatePropertiesAndRenderSurfaces() currently both updates the layers and updates the draw state 281 // (transforms, etc). It'd be nicer if operations on the presentation layers happened later, but the draw 282 // transforms are needed by large layers to determine visibility. Tiling will fix this by eliminating the 283 // concept of a large content layer. 284 updatePropertiesAndRenderSurfaces(m_rootLayer.get(), identityMatrix, renderSurfaceLayerList, m_defaultRenderSurface->m_layerList); 285 286 paintLayerContents(renderSurfaceLayerList); 287 288 // FIXME: Before updateCompositorResourcesRecursive, when the compositor runs in 289 // its own thread, and when the copyTexImage2D bug is fixed, insert 290 // a glWaitLatch(Compositor->Offscreen) on all child contexts here instead 291 // of after updateCompositorResourcesRecursive. 292 // Also uncomment the glSetLatch(Compositor->Offscreen) code in addChildContext. 293// if (hardwareCompositing() && m_contextSupportsLatch) { 294// // For each child context: 295// // glWaitLatch(Compositor->Offscreen); 296// ChildContextMap::iterator i = m_childContexts.begin(); 297// for (; i != m_childContexts.end(); ++i) { 298// Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(i->first->getExtensions()); 299// GC3Duint childToParentLatchId, parentToChildLatchId; 300// ext->getParentToChildLatchCHROMIUM(&parentToChildLatchId); 301// ext->waitLatchCHROMIUM(parentToChildLatchId); 302// } 303// } 304 305 updateCompositorResourcesRecursive(m_rootLayer.get()); 306 307 // After updateCompositorResourcesRecursive, set/wait latches for all child 308 // contexts. This will prevent the compositor from using any of the child 309 // parent textures while WebGL commands are executing from javascript *and* 310 // while the final parent texture is being blit'd. copyTexImage2D 311 // uses the parent texture as a temporary resolve buffer, so that's why the 312 // waitLatch is below, to block the compositor from using the parent texture 313 // until the next WebGL SwapBuffers (or copyTextureToParentTexture for 314 // Canvas2D). 315 if (hardwareCompositing() && m_contextSupportsLatch) { 316 m_childContextsWereCopied = true; 317 // For each child context: 318 // glSetLatch(Offscreen->Compositor); 319 // glWaitLatch(Compositor->Offscreen); 320 ChildContextMap::iterator i = m_childContexts.begin(); 321 for (; i != m_childContexts.end(); ++i) { 322 Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(i->first->getExtensions()); 323 GC3Duint childToParentLatchId, parentToChildLatchId; 324 ext->getParentToChildLatchCHROMIUM(&parentToChildLatchId); 325 ext->getChildToParentLatchCHROMIUM(&childToParentLatchId); 326 ext->setLatchCHROMIUM(childToParentLatchId); 327 ext->waitLatchCHROMIUM(parentToChildLatchId); 328 } 329 } 330} 331 332void LayerRendererChromium::paintLayerContents(const LayerList& renderSurfaceLayerList) 333{ 334 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { 335 CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get(); 336 RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface(); 337 ASSERT(renderSurface); 338 339 // Render surfaces whose drawable area has zero width or height 340 // will have no layers associated with them and should be skipped. 341 if (!renderSurface->m_layerList.size()) 342 continue; 343 344 LayerList& layerList = renderSurface->m_layerList; 345 ASSERT(layerList.size()); 346 for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) { 347 CCLayerImpl* ccLayerImpl = layerList[layerIndex].get(); 348 349 // Layers that start a new render surface will be painted when the render 350 // surface's list is processed. 351 if (ccLayerImpl->renderSurface() && ccLayerImpl->renderSurface() != renderSurface) 352 continue; 353 354 LayerChromium* layer = ccLayerImpl->owner(); 355 if (layer->bounds().isEmpty()) 356 continue; 357 358 const IntRect targetSurfaceRect = layer->ccLayerImpl()->scissorRect(); 359 360 if (layer->drawsContent()) 361 layer->paintContentsIfDirty(targetSurfaceRect); 362 if (layer->maskLayer() && layer->maskLayer()->drawsContent()) 363 layer->maskLayer()->paintContentsIfDirty(targetSurfaceRect); 364 if (layer->replicaLayer() && layer->replicaLayer()->drawsContent()) 365 layer->replicaLayer()->paintContentsIfDirty(targetSurfaceRect); 366 if (layer->replicaLayer() && layer->replicaLayer()->maskLayer() && layer->replicaLayer()->maskLayer()->drawsContent()) 367 layer->replicaLayer()->maskLayer()->paintContentsIfDirty(targetSurfaceRect); 368 } 369 } 370} 371 372void LayerRendererChromium::drawLayers(const LayerList& renderSurfaceLayerList) 373{ 374 TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0); 375 CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl(); 376 makeContextCurrent(); 377 378 // The GL viewport covers the entire visible area, including the scrollbars. 379 GLC(m_context.get(), m_context->viewport(0, 0, m_viewportVisibleRect.width(), m_viewportVisibleRect.height())); 380 381 // Bind the common vertex attributes used for drawing all the layers. 382 m_sharedGeometry->prepareForDraw(); 383 384 // FIXME: These calls can be made once, when the compositor context is initialized. 385 GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST)); 386 GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE)); 387 388 // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType. 389 GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND)); 390 391 useRenderSurface(m_defaultRenderSurface); 392 393 // Clear to blue to make it easier to spot unrendered regions. 394 m_context->clearColor(0, 0, 1, 1); 395 m_context->colorMask(true, true, true, true); 396 m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); 397 // Mask out writes to alpha channel: subpixel antialiasing via Skia results in invalid 398 // zero alpha values on text glyphs. The root layer is always opaque. 399 m_context->colorMask(true, true, true, false); 400 401 drawRootLayer(); 402 403 // Re-enable color writes to layers, which may be partially transparent. 404 m_context->colorMask(true, true, true, true); 405 406 GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND)); 407 GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); 408 GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST)); 409 410 // Update the contents of the render surfaces. We traverse the array from 411 // back to front to guarantee that nested render surfaces get rendered in the 412 // correct order. 413 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { 414 CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get(); 415 ASSERT(renderSurfaceLayer->renderSurface()); 416 417 // Render surfaces whose drawable area has zero width or height 418 // will have no layers associated with them and should be skipped. 419 if (!renderSurfaceLayer->renderSurface()->m_layerList.size()) 420 continue; 421 422 if (useRenderSurface(renderSurfaceLayer->renderSurface())) { 423 if (renderSurfaceLayer != rootDrawLayer) { 424 GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); 425 GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0)); 426 GLC(m_context.get(), m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT)); 427 GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST)); 428 } 429 430 LayerList& layerList = renderSurfaceLayer->renderSurface()->m_layerList; 431 ASSERT(layerList.size()); 432 for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) 433 drawLayer(layerList[layerIndex].get(), renderSurfaceLayer->renderSurface()); 434 } 435 } 436 437 if (m_headsUpDisplay->enabled()) { 438 GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND)); 439 GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); 440 GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); 441 useRenderSurface(m_defaultRenderSurface); 442 m_headsUpDisplay->draw(); 443 } 444 445 GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); 446 GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND)); 447} 448 449void LayerRendererChromium::finish() 450{ 451 TRACE_EVENT("LayerRendererChromium::finish", this, 0); 452 m_context->finish(); 453} 454 455void LayerRendererChromium::present() 456{ 457 TRACE_EVENT("LayerRendererChromium::present", this, 0); 458 // We're done! Time to swapbuffers! 459 460 // Note that currently this has the same effect as swapBuffers; we should 461 // consider exposing a different entry point on GraphicsContext3D. 462 m_context->prepareTexture(); 463 464 m_headsUpDisplay->onPresent(); 465} 466 467void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer) 468{ 469 m_rootLayer = layer; 470 if (m_rootLayer) 471 m_rootLayer->setLayerRenderer(this); 472 m_rootLayerContentTiler->invalidateEntireLayer(); 473} 474 475void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect) 476{ 477 ASSERT(rect.maxX() <= m_viewportVisibleRect.width() && rect.maxY() <= m_viewportVisibleRect.height()); 478 479 if (!pixels) 480 return; 481 482 makeContextCurrent(); 483 484 GLC(m_context.get(), m_context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(), 485 GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels)); 486} 487 488// FIXME: This method should eventually be replaced by a proper texture manager. 489unsigned LayerRendererChromium::createLayerTexture() 490{ 491 unsigned textureId = 0; 492 GLC(m_context.get(), textureId = m_context->createTexture()); 493 GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); 494 // Do basic linear filtering on resize. 495 GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); 496 GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); 497 // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE. 498 GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); 499 GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); 500 return textureId; 501} 502 503void LayerRendererChromium::deleteLayerTexture(unsigned textureId) 504{ 505 if (!textureId) 506 return; 507 508 GLC(m_context.get(), m_context->deleteTexture(textureId)); 509} 510 511// Returns true if any part of the layer falls within the visibleRect 512bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const TransformationMatrix& matrix, const IntRect& visibleRect) 513{ 514 // Form the matrix used by the shader to map the corners of the layer's 515 // bounds into clip space. 516 TransformationMatrix renderMatrix = matrix; 517 renderMatrix.scale3d(layer->bounds().width(), layer->bounds().height(), 1); 518 renderMatrix = m_projectionMatrix * renderMatrix; 519 520 FloatRect layerRect(-0.5, -0.5, 1, 1); 521 FloatRect mappedRect = renderMatrix.mapRect(layerRect); 522 523 // The layer is visible if it intersects any part of a rectangle whose origin 524 // is at (-1, -1) and size is 2x2. 525 return mappedRect.intersects(FloatRect(-1, -1, 2, 2)); 526} 527 528// Recursively walks the layer tree starting at the given node and computes all the 529// necessary transformations, scissor rectangles, render surfaces, etc. 530void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* layer, const TransformationMatrix& parentMatrix, LayerList& renderSurfaceLayerList, LayerList& layerList) 531{ 532 // Make sure we have CCLayerImpls for this subtree. 533 layer->createCCLayerImplIfNeeded(); 534 layer->setLayerRenderer(this); 535 if (layer->maskLayer()) { 536 layer->maskLayer()->createCCLayerImplIfNeeded(); 537 layer->maskLayer()->setLayerRenderer(this); 538 } 539 if (layer->replicaLayer()) { 540 layer->replicaLayer()->createCCLayerImplIfNeeded(); 541 layer->replicaLayer()->setLayerRenderer(this); 542 } 543 if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { 544 layer->replicaLayer()->maskLayer()->createCCLayerImplIfNeeded(); 545 layer->replicaLayer()->maskLayer()->setLayerRenderer(this); 546 } 547 548 CCLayerImpl* drawLayer = layer->ccLayerImpl(); 549 // Currently we're calling pushPropertiesTo() twice - once here and once in updateCompositorResourcesRecursive(). 550 // We should only call pushPropertiesTo() in commit, but because we rely on the draw layer state to update 551 // RenderSurfaces and we rely on RenderSurfaces being up to date in order to paint contents we have 552 // to update the draw layers twice. 553 // FIXME: Remove this call once layer updates no longer depend on render surfaces. 554 layer->pushPropertiesTo(drawLayer); 555 556 // Compute the new matrix transformation that will be applied to this layer and 557 // all its sublayers. It's important to remember that the layer's position 558 // is the position of the layer's anchor point. Also, the coordinate system used 559 // assumes that the origin is at the lower left even though the coordinates the browser 560 // gives us for the layers are for the upper left corner. The Y flip happens via 561 // the orthographic projection applied at render time. 562 // The transformation chain for the layer is (using the Matrix x Vector order): 563 // M = M[p] * Tr[l] * M[l] * Tr[c] 564 // Where M[p] is the parent matrix passed down to the function 565 // Tr[l] is the translation matrix locating the layer's anchor point 566 // Tr[c] is the translation offset between the anchor point and the center of the layer 567 // M[l] is the layer's matrix (applied at the anchor point) 568 // This transform creates a coordinate system whose origin is the center of the layer. 569 // Note that the final matrix used by the shader for the layer is P * M * S . This final product 570 // is computed in drawTexturedQuad(). 571 // Where: P is the projection matrix 572 // M is the layer's matrix computed above 573 // S is the scale adjustment (to scale up to the layer size) 574 IntSize bounds = drawLayer->bounds(); 575 FloatPoint anchorPoint = drawLayer->anchorPoint(); 576 FloatPoint position = drawLayer->position(); 577 578 // Offset between anchor point and the center of the quad. 579 float centerOffsetX = (0.5 - anchorPoint.x()) * bounds.width(); 580 float centerOffsetY = (0.5 - anchorPoint.y()) * bounds.height(); 581 582 TransformationMatrix layerLocalTransform; 583 // LT = Tr[l] 584 layerLocalTransform.translate3d(position.x(), position.y(), drawLayer->anchorPointZ()); 585 // LT = Tr[l] * M[l] 586 layerLocalTransform.multiply(drawLayer->transform()); 587 // LT = Tr[l] * M[l] * Tr[c] 588 layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -drawLayer->anchorPointZ()); 589 590 TransformationMatrix combinedTransform = parentMatrix; 591 combinedTransform = combinedTransform.multiply(layerLocalTransform); 592 593 FloatRect layerRect(-0.5 * drawLayer->bounds().width(), -0.5 * drawLayer->bounds().height(), drawLayer->bounds().width(), drawLayer->bounds().height()); 594 IntRect transformedLayerRect; 595 596 // The layer and its descendants render on a new RenderSurface if any of 597 // these conditions hold: 598 // 1. The layer clips its descendants and its transform is not a simple translation. 599 // 2. If the layer has opacity != 1 and does not have a preserves-3d transform style. 600 // 3. The layer uses a mask 601 // 4. The layer has a replica (used for reflections) 602 // If a layer preserves-3d then we don't create a RenderSurface for it to avoid flattening 603 // out its children. The opacity value of the children layers is multiplied by the opacity 604 // of their parent. 605 bool useSurfaceForClipping = drawLayer->masksToBounds() && !isScaleOrTranslation(combinedTransform); 606 bool useSurfaceForOpacity = drawLayer->opacity() != 1 && !drawLayer->preserves3D(); 607 bool useSurfaceForMasking = drawLayer->maskLayer(); 608 bool useSurfaceForReflection = drawLayer->replicaLayer(); 609 if (useSurfaceForMasking || useSurfaceForReflection || ((useSurfaceForClipping || useSurfaceForOpacity) && drawLayer->descendantsDrawsContent())) { 610 RenderSurfaceChromium* renderSurface = drawLayer->renderSurface(); 611 if (!renderSurface) 612 renderSurface = drawLayer->createRenderSurface(); 613 614 // The origin of the new surface is the upper left corner of the layer. 615 TransformationMatrix drawTransform; 616 drawTransform.translate3d(0.5 * bounds.width(), 0.5 * bounds.height(), 0); 617 drawLayer->setDrawTransform(drawTransform); 618 619 transformedLayerRect = IntRect(0, 0, bounds.width(), bounds.height()); 620 621 // Layer's opacity will be applied when drawing the render surface. 622 renderSurface->m_drawOpacity = drawLayer->opacity(); 623 if (drawLayer->superlayer() && drawLayer->superlayer()->preserves3D()) 624 renderSurface->m_drawOpacity *= drawLayer->superlayer()->drawOpacity(); 625 drawLayer->setDrawOpacity(1); 626 627 TransformationMatrix layerOriginTransform = combinedTransform; 628 layerOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0); 629 renderSurface->m_originTransform = layerOriginTransform; 630 if (layerOriginTransform.isInvertible() && drawLayer->superlayer()) { 631 TransformationMatrix parentToLayer = layerOriginTransform.inverse(); 632 633 drawLayer->setScissorRect(parentToLayer.mapRect(drawLayer->superlayer()->scissorRect())); 634 } else 635 drawLayer->setScissorRect(IntRect()); 636 637 // The render surface scissor rect is the scissor rect that needs to 638 // be applied before drawing the render surface onto its containing 639 // surface and is therefore expressed in the superlayer's coordinate system. 640 renderSurface->m_scissorRect = drawLayer->superlayer() ? drawLayer->superlayer()->scissorRect() : drawLayer->scissorRect(); 641 642 renderSurface->m_layerList.clear(); 643 644 if (drawLayer->maskLayer()) { 645 renderSurface->m_maskLayer = drawLayer->maskLayer(); 646 drawLayer->maskLayer()->setTargetRenderSurface(renderSurface); 647 } else 648 renderSurface->m_maskLayer = 0; 649 650 if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->maskLayer()) 651 drawLayer->replicaLayer()->maskLayer()->setTargetRenderSurface(renderSurface); 652 653 renderSurfaceLayerList.append(drawLayer); 654 } else { 655 // DT = M[p] * LT 656 drawLayer->setDrawTransform(combinedTransform); 657 transformedLayerRect = enclosingIntRect(drawLayer->drawTransform().mapRect(layerRect)); 658 659 drawLayer->setDrawOpacity(drawLayer->opacity()); 660 661 if (drawLayer->superlayer()) { 662 if (drawLayer->superlayer()->preserves3D()) 663 drawLayer->setDrawOpacity(drawLayer->drawOpacity() * drawLayer->superlayer()->drawOpacity()); 664 665 // Layers inherit the scissor rect from their superlayer. 666 drawLayer->setScissorRect(drawLayer->superlayer()->scissorRect()); 667 668 drawLayer->setTargetRenderSurface(drawLayer->superlayer()->targetRenderSurface()); 669 } 670 671 if (layer != m_rootLayer) 672 drawLayer->clearRenderSurface(); 673 674 if (drawLayer->masksToBounds()) { 675 IntRect scissor = drawLayer->scissorRect(); 676 scissor.intersect(transformedLayerRect); 677 drawLayer->setScissorRect(scissor); 678 } 679 } 680 681 if (drawLayer->renderSurface()) 682 drawLayer->setTargetRenderSurface(drawLayer->renderSurface()); 683 else { 684 ASSERT(drawLayer->superlayer()); 685 drawLayer->setTargetRenderSurface(drawLayer->superlayer()->targetRenderSurface()); 686 } 687 688 // drawableContentRect() is always stored in the coordinate system of the 689 // RenderSurface the layer draws into. 690 if (drawLayer->drawsContent()) 691 drawLayer->setDrawableContentRect(transformedLayerRect); 692 else 693 drawLayer->setDrawableContentRect(IntRect()); 694 695 TransformationMatrix sublayerMatrix = drawLayer->drawTransform(); 696 697 // Flatten to 2D if the layer doesn't preserve 3D. 698 if (!drawLayer->preserves3D()) { 699 sublayerMatrix.setM13(0); 700 sublayerMatrix.setM23(0); 701 sublayerMatrix.setM31(0); 702 sublayerMatrix.setM32(0); 703 sublayerMatrix.setM33(1); 704 sublayerMatrix.setM34(0); 705 sublayerMatrix.setM43(0); 706 } 707 708 // Apply the sublayer transform at the center of the layer. 709 sublayerMatrix.multiply(drawLayer->sublayerTransform()); 710 711 // The origin of the sublayers is the top left corner of the layer, not the 712 // center. The matrix passed down to the sublayers is therefore: 713 // M[s] = M * Tr[-center] 714 sublayerMatrix.translate3d(-bounds.width() * 0.5, -bounds.height() * 0.5, 0); 715 716 // Compute the depth value of the center of the layer which will be used when 717 // sorting the layers for the preserves-3d property. 718 const TransformationMatrix& layerDrawMatrix = drawLayer->renderSurface() ? drawLayer->renderSurface()->m_drawTransform : drawLayer->drawTransform(); 719 if (drawLayer->superlayer()) { 720 if (!drawLayer->superlayer()->preserves3D()) 721 drawLayer->setDrawDepth(drawLayer->superlayer()->drawDepth()); 722 else 723 drawLayer->setDrawDepth(layerDrawMatrix.m43()); 724 } else 725 drawLayer->setDrawDepth(0); 726 727 LayerList& descendants = (drawLayer->renderSurface() ? drawLayer->renderSurface()->m_layerList : layerList); 728 descendants.append(drawLayer); 729 unsigned thisLayerIndex = descendants.size() - 1; 730 731 const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); 732 for (size_t i = 0; i < sublayers.size(); ++i) { 733 sublayers[i]->createCCLayerImplIfNeeded(); 734 CCLayerImpl* sublayer = sublayers[i]->ccLayerImpl(); 735 updatePropertiesAndRenderSurfaces(sublayers[i].get(), sublayerMatrix, renderSurfaceLayerList, descendants); 736 737 if (sublayer->renderSurface()) { 738 RenderSurfaceChromium* sublayerRenderSurface = sublayer->renderSurface(); 739 IntRect drawableContentRect = drawLayer->drawableContentRect(); 740 drawableContentRect.unite(enclosingIntRect(sublayerRenderSurface->drawableContentRect())); 741 drawLayer->setDrawableContentRect(drawableContentRect); 742 descendants.append(sublayer); 743 } else { 744 IntRect drawableContentRect = drawLayer->drawableContentRect(); 745 drawableContentRect.unite(sublayer->drawableContentRect()); 746 drawLayer->setDrawableContentRect(drawableContentRect); 747 } 748 } 749 750 if (drawLayer->masksToBounds() || useSurfaceForMasking) { 751 IntRect drawableContentRect = drawLayer->drawableContentRect(); 752 drawableContentRect.intersect(transformedLayerRect); 753 drawLayer->setDrawableContentRect(drawableContentRect); 754 } 755 756 if (drawLayer->renderSurface() && layer != m_rootLayer) { 757 RenderSurfaceChromium* renderSurface = drawLayer->renderSurface(); 758 renderSurface->m_contentRect = drawLayer->drawableContentRect(); 759 FloatPoint surfaceCenter = renderSurface->contentRectCenter(); 760 761 // Restrict the RenderSurface size to the portion that's visible. 762 FloatSize centerOffsetDueToClipping; 763 764 // Don't clip if the layer is reflected as the reflection shouldn't be 765 // clipped. 766 if (!drawLayer->replicaLayer()) { 767 renderSurface->m_contentRect.intersect(drawLayer->scissorRect()); 768 FloatPoint clippedSurfaceCenter = renderSurface->contentRectCenter(); 769 centerOffsetDueToClipping = clippedSurfaceCenter - surfaceCenter; 770 } 771 772 // The RenderSurface backing texture cannot exceed the maximum supported 773 // texture size. 774 renderSurface->m_contentRect.setWidth(std::min(renderSurface->m_contentRect.width(), m_maxTextureSize)); 775 renderSurface->m_contentRect.setHeight(std::min(renderSurface->m_contentRect.height(), m_maxTextureSize)); 776 777 if (renderSurface->m_contentRect.isEmpty()) 778 renderSurface->m_layerList.clear(); 779 780 // Since the layer starts a new render surface we need to adjust its 781 // scissor rect to be expressed in the new surface's coordinate system. 782 drawLayer->setScissorRect(drawLayer->drawableContentRect()); 783 784 // Adjust the origin of the transform to be the center of the render surface. 785 renderSurface->m_drawTransform = renderSurface->m_originTransform; 786 renderSurface->m_drawTransform.translate3d(surfaceCenter.x() + centerOffsetDueToClipping.width(), surfaceCenter.y() + centerOffsetDueToClipping.height(), 0); 787 788 // Compute the transformation matrix used to draw the replica of the render 789 // surface. 790 if (drawLayer->replicaLayer()) { 791 renderSurface->m_replicaDrawTransform = renderSurface->m_originTransform; 792 renderSurface->m_replicaDrawTransform.translate3d(drawLayer->replicaLayer()->position().x(), drawLayer->replicaLayer()->position().y(), 0); 793 renderSurface->m_replicaDrawTransform.multiply(drawLayer->replicaLayer()->transform()); 794 renderSurface->m_replicaDrawTransform.translate3d(surfaceCenter.x() - anchorPoint.x() * bounds.width(), surfaceCenter.y() - anchorPoint.y() * bounds.height(), 0); 795 } 796 } 797 798 // If preserves-3d then sort all the descendants by the Z coordinate of their 799 // center. If the preserves-3d property is also set on the superlayer then 800 // skip the sorting as the superlayer will sort all the descendants anyway. 801 if (drawLayer->preserves3D() && (!drawLayer->superlayer() || !drawLayer->superlayer()->preserves3D())) 802 std::stable_sort(&descendants.at(thisLayerIndex), descendants.end(), compareLayerZ); 803} 804 805void LayerRendererChromium::updateCompositorResourcesRecursive(LayerChromium* layer) 806{ 807 const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); 808 for (size_t i = 0; i < sublayers.size(); ++i) 809 updateCompositorResourcesRecursive(sublayers[i].get()); 810 811 if (layer->bounds().isEmpty()) 812 return; 813 814 CCLayerImpl* drawLayer = layer->ccLayerImpl(); 815 816 if (drawLayer->drawsContent()) 817 drawLayer->updateCompositorResources(); 818 if (drawLayer->maskLayer() && drawLayer->maskLayer()->drawsContent()) 819 drawLayer->maskLayer()->updateCompositorResources(); 820 if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->drawsContent()) 821 drawLayer->replicaLayer()->updateCompositorResources(); 822 if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->maskLayer() && drawLayer->replicaLayer()->maskLayer()->drawsContent()) 823 drawLayer->replicaLayer()->maskLayer()->updateCompositorResources(); 824 825 layer->pushPropertiesTo(drawLayer); 826} 827 828void LayerRendererChromium::setCompositeOffscreen(bool compositeOffscreen) 829{ 830 if (m_compositeOffscreen == compositeOffscreen) 831 return; 832 833 m_compositeOffscreen = compositeOffscreen; 834 835 if (!m_compositeOffscreen && m_rootLayer) 836 m_rootLayer->ccLayerImpl()->clearRenderSurface(); 837} 838 839LayerTexture* LayerRendererChromium::getOffscreenLayerTexture() 840{ 841 return m_compositeOffscreen ? m_rootLayer->ccLayerImpl()->renderSurface()->m_contentsTexture.get() : 0; 842} 843 844void LayerRendererChromium::copyOffscreenTextureToDisplay() 845{ 846 if (m_compositeOffscreen) { 847 makeContextCurrent(); 848 849 useRenderSurface(0); 850 m_defaultRenderSurface->m_drawTransform.makeIdentity(); 851 m_defaultRenderSurface->m_drawTransform.translate3d(0.5 * m_defaultRenderSurface->m_contentRect.width(), 852 0.5 * m_defaultRenderSurface->m_contentRect.height(), 0); 853 m_defaultRenderSurface->m_drawOpacity = 1; 854 m_defaultRenderSurface->draw(m_defaultRenderSurface->m_contentRect); 855 } 856} 857 858bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurface) 859{ 860 if (m_currentRenderSurface == renderSurface) 861 return true; 862 863 m_currentRenderSurface = renderSurface; 864 865 if ((renderSurface == m_defaultRenderSurface && !m_compositeOffscreen) || (!renderSurface && m_compositeOffscreen)) { 866 GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); 867 if (renderSurface) 868 setDrawViewportRect(renderSurface->m_contentRect, true); 869 else 870 setDrawViewportRect(m_defaultRenderSurface->m_contentRect, true); 871 return true; 872 } 873 874 GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId)); 875 876 if (!renderSurface->prepareContentsTexture()) 877 return false; 878 879 renderSurface->m_contentsTexture->framebufferTexture2D(); 880 881#if !defined ( NDEBUG ) 882 if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { 883 ASSERT_NOT_REACHED(); 884 return false; 885 } 886#endif 887 888 setDrawViewportRect(renderSurface->m_contentRect, false); 889 return true; 890} 891 892void LayerRendererChromium::drawLayer(CCLayerImpl* layer, RenderSurfaceChromium* targetSurface) 893{ 894 if (layer->renderSurface() && layer->renderSurface() != targetSurface) { 895 layer->renderSurface()->draw(layer->getDrawRect()); 896 return; 897 } 898 899 if (!layer->drawsContent()) 900 return; 901 902 if (layer->bounds().isEmpty()) { 903 layer->unreserveContentsTexture(); 904 return; 905 } 906 907 setScissorToRect(layer->scissorRect()); 908 909 // Check if the layer falls within the visible bounds of the page. 910 IntRect layerRect = layer->getDrawRect(); 911 bool isLayerVisible = layer->scissorRect().intersects(layerRect); 912 if (!isLayerVisible) { 913 layer->unreserveContentsTexture(); 914 return; 915 } 916 917 // FIXME: Need to take into account the commulative render surface transforms all the way from 918 // the default render surface in order to determine visibility. 919 TransformationMatrix combinedDrawMatrix = (layer->targetRenderSurface() ? layer->targetRenderSurface()->drawTransform().multiply(layer->drawTransform()) : layer->drawTransform()); 920 921 if (!layer->doubleSided()) { 922 FloatRect layerRect(FloatPoint(0, 0), FloatSize(layer->bounds())); 923 FloatQuad mappedLayer = combinedDrawMatrix.mapQuad(FloatQuad(layerRect)); 924 FloatSize horizontalDir = mappedLayer.p2() - mappedLayer.p1(); 925 FloatSize verticalDir = mappedLayer.p4() - mappedLayer.p1(); 926 FloatPoint3D xAxis(horizontalDir.width(), horizontalDir.height(), 0); 927 FloatPoint3D yAxis(verticalDir.width(), verticalDir.height(), 0); 928 FloatPoint3D zAxis = xAxis.cross(yAxis); 929 if (zAxis.z() < 0) { 930 layer->unreserveContentsTexture(); 931 return; 932 } 933 } 934 935 layer->draw(layer->scissorRect()); 936 937 // Draw the debug border if there is one. 938 layer->drawDebugBorder(); 939} 940 941// Sets the scissor region to the given rectangle. The coordinate system for the 942// scissorRect has its origin at the top left corner of the current visible rect. 943void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect) 944{ 945 IntRect contentRect = (m_currentRenderSurface ? m_currentRenderSurface->m_contentRect : m_defaultRenderSurface->m_contentRect); 946 947 // The scissor coordinates must be supplied in viewport space so we need to offset 948 // by the relative position of the top left corner of the current render surface. 949 int scissorX = scissorRect.x() - contentRect.x(); 950 // When rendering to the default render surface we're rendering upside down so the top 951 // of the GL scissor is the bottom of our layer. 952 // But, if rendering to offscreen texture, we reverse our sense of 'upside down'. 953 int scissorY; 954 if (m_currentRenderSurface == m_defaultRenderSurface && !m_compositeOffscreen) 955 scissorY = m_currentRenderSurface->m_contentRect.height() - (scissorRect.maxY() - m_currentRenderSurface->m_contentRect.y()); 956 else 957 scissorY = scissorRect.y() - contentRect.y(); 958 GLC(m_context.get(), m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height())); 959} 960 961bool LayerRendererChromium::makeContextCurrent() 962{ 963 m_context->makeContextCurrent(); 964 return true; 965} 966 967// Checks whether a given size is within the maximum allowed texture size range. 968bool LayerRendererChromium::checkTextureSize(const IntSize& textureSize) 969{ 970 if (textureSize.width() > m_maxTextureSize || textureSize.height() > m_maxTextureSize) 971 return false; 972 return true; 973} 974 975// Sets the coordinate range of content that ends being drawn onto the target render surface. 976// The target render surface is assumed to have an origin at 0, 0 and the width and height of 977// of the drawRect. 978void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY) 979{ 980 if (flipY) 981 m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y()); 982 else 983 m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY()); 984 GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height())); 985} 986 987 988 989void LayerRendererChromium::resizeOnscreenContent(const IntSize& size) 990{ 991 if (m_context) 992 m_context->reshape(size.width(), size.height()); 993} 994 995bool LayerRendererChromium::initializeSharedObjects() 996{ 997 makeContextCurrent(); 998 999 // Get the max texture size supported by the system. 1000 m_maxTextureSize = 0; 1001 GLC(m_context.get(), m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize)); 1002 1003 // Create an FBO for doing offscreen rendering. 1004 GLC(m_context.get(), m_offscreenFramebufferId = m_context->createFramebuffer()); 1005 1006 m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get())); 1007 m_borderProgram = adoptPtr(new LayerChromium::BorderProgram(m_context.get())); 1008 m_headsUpDisplayProgram = adoptPtr(new CCHeadsUpDisplay::Program(m_context.get())); 1009 m_canvasLayerProgram = adoptPtr(new CCCanvasLayerImpl::Program(m_context.get())); 1010 m_videoLayerRGBAProgram = adoptPtr(new CCVideoLayerImpl::RGBAProgram(m_context.get())); 1011 m_videoLayerYUVProgram = adoptPtr(new CCVideoLayerImpl::YUVProgram(m_context.get())); 1012 m_pluginLayerProgram = adoptPtr(new CCPluginLayerImpl::Program(m_context.get())); 1013 m_renderSurfaceProgram = adoptPtr(new RenderSurfaceChromium::Program(m_context.get())); 1014 m_renderSurfaceMaskProgram = adoptPtr(new RenderSurfaceChromium::MaskProgram(m_context.get())); 1015 m_tilerProgram = adoptPtr(new LayerTilerChromium::Program(m_context.get())); 1016 1017 if (!m_sharedGeometry->initialized() || !m_borderProgram->initialized() 1018 || !m_canvasLayerProgram->initialized() 1019 || !m_headsUpDisplayProgram->initialized() 1020 || !m_videoLayerRGBAProgram->initialized() || !m_videoLayerYUVProgram->initialized() 1021 || !m_pluginLayerProgram->initialized() || !m_renderSurfaceProgram->initialized() 1022 || !m_renderSurfaceMaskProgram->initialized() || !m_tilerProgram->initialized()) { 1023 LOG_ERROR("Compositor failed to initialize shaders. Falling back to software."); 1024 cleanupSharedObjects(); 1025 return false; 1026 } 1027 1028 m_textureManager = TextureManager::create(m_context.get(), textureMemoryLimitBytes, m_maxTextureSize); 1029 return true; 1030} 1031 1032void LayerRendererChromium::cleanupSharedObjects() 1033{ 1034 makeContextCurrent(); 1035 1036 m_sharedGeometry.clear(); 1037 m_borderProgram.clear(); 1038 m_canvasLayerProgram.clear(); 1039 m_headsUpDisplayProgram.clear(); 1040 m_videoLayerRGBAProgram.clear(); 1041 m_videoLayerYUVProgram.clear(); 1042 m_pluginLayerProgram.clear(); 1043 m_renderSurfaceProgram.clear(); 1044 m_renderSurfaceMaskProgram.clear(); 1045 m_tilerProgram.clear(); 1046 if (m_offscreenFramebufferId) 1047 GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId)); 1048 1049 // Clear tilers before the texture manager, as they have references to textures. 1050 m_rootLayerContentTiler.clear(); 1051 1052 m_textureManager.clear(); 1053} 1054 1055String LayerRendererChromium::layerTreeAsText() const 1056{ 1057 TextStream ts; 1058 if (m_rootLayer.get()) { 1059 ts << m_rootLayer->layerTreeAsText(); 1060 ts << "RenderSurfaces:\n"; 1061 dumpRenderSurfaces(ts, 1, m_rootLayer.get()); 1062 } 1063 return ts.release(); 1064} 1065 1066void LayerRendererChromium::addChildContext(GraphicsContext3D* ctx) 1067{ 1068 if (!ctx->getExtensions()->supports("GL_CHROMIUM_latch")) 1069 return; 1070 1071 // This is a ref-counting map, because some contexts are shared by multiple 1072 // layers (specifically, Canvas2DLayerChromium). 1073 1074 // Insert the ctx with a count of 1, or return the existing iterator. 1075 std::pair<ChildContextMap::iterator, bool> insert_result = m_childContexts.add(ctx, 1); 1076 if (!insert_result.second) { 1077 // Already present in map, so increment. 1078 ++insert_result.first->second; 1079 } else { 1080// FIXME(jbates): when compositor is multithreaded and copyTexImage2D bug is fixed, 1081// uncomment this block: 1082// // This is a new child context - set the parentToChild latch so that it 1083// // can continue past its first wait latch. 1084// Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(ctx->getExtensions()); 1085// GC3Duint latchId; 1086// ext->getParentToChildLatchCHROMIUM(&latchId); 1087// ext->setLatchCHROMIUM(0, latchId); 1088 } 1089} 1090 1091void LayerRendererChromium::removeChildContext(GraphicsContext3D* ctx) 1092{ 1093 if (!ctx->getExtensions()->supports("GL_CHROMIUM_latch")) 1094 return; 1095 1096 ChildContextMap::iterator i = m_childContexts.find(ctx); 1097 if (i != m_childContexts.end()) { 1098 if (--i->second <= 0) { 1099 // Count reached zero, so remove from map. 1100 m_childContexts.remove(i); 1101 } 1102 } else { 1103 // error 1104 ASSERT(0 && "m_childContexts map has mismatched add/remove calls"); 1105 } 1106} 1107 1108void LayerRendererChromium::dumpRenderSurfaces(TextStream& ts, int indent, LayerChromium* layer) const 1109{ 1110 if (layer->ccLayerImpl()->renderSurface()) 1111 layer->ccLayerImpl()->renderSurface()->dumpSurface(ts, indent); 1112 1113 for (size_t i = 0; i < layer->getSublayers().size(); ++i) 1114 dumpRenderSurfaces(ts, indent, layer->getSublayers()[i].get()); 1115} 1116 1117} // namespace WebCore 1118 1119#endif // USE(ACCELERATED_COMPOSITING) 1120