| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> | 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
| 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 | 277 |
| 278 if (m_context->is3d()) { | 278 if (m_context->is3d()) { |
| 279 updateExternallyAllocatedMemory(); | 279 updateExternallyAllocatedMemory(); |
| 280 } | 280 } |
| 281 | 281 |
| 282 LayoutObject* layoutObject = this->layoutObject(); | 282 LayoutObject* layoutObject = this->layoutObject(); |
| 283 if (layoutObject && m_context->is2d() && | 283 if (layoutObject && m_context->is2d() && |
| 284 !m_context->creationAttributes().alpha()) { | 284 !m_context->creationAttributes().alpha()) { |
| 285 // In the alpha false case, canvas is initially opaque even though there is | 285 // In the alpha false case, canvas is initially opaque even though there is |
| 286 // no ImageBuffer, so we need to trigger an invalidation. | 286 // no ImageBuffer, so we need to trigger an invalidation. |
| 287 didDraw(FloatRect(0, 0, size().width(), size().height())); | 287 didDraw(); |
| 288 } | 288 } |
| 289 | 289 |
| 290 setNeedsCompositingUpdate(); | 290 setNeedsCompositingUpdate(); |
| 291 | 291 |
| 292 return m_context.get(); | 292 return m_context.get(); |
| 293 } | 293 } |
| 294 | 294 |
| 295 bool HTMLCanvasElement::shouldBeDirectComposited() const { | 295 bool HTMLCanvasElement::shouldBeDirectComposited() const { |
| 296 return (m_context && m_context->isAccelerated()) || | 296 return (m_context && m_context->isComposited()) || |
| 297 (hasImageBuffer() && buffer()->isExpensiveToPaint()) || | 297 (hasImageBuffer() && buffer()->isExpensiveToPaint()) || |
| 298 (!!m_surfaceLayerBridge); | 298 (!!m_surfaceLayerBridge); |
| 299 } | 299 } |
| 300 | 300 |
| 301 bool HTMLCanvasElement::isPaintable() const { | 301 bool HTMLCanvasElement::isPaintable() const { |
| 302 return (m_context && m_context->isPaintable()) || | 302 return (m_context && m_context->isPaintable()) || |
| 303 ImageBuffer::canCreateImageBuffer(size()); | 303 ImageBuffer::canCreateImageBuffer(size()); |
| 304 } | 304 } |
| 305 | 305 |
| 306 bool HTMLCanvasElement::isAccelerated() const { | 306 bool HTMLCanvasElement::isAccelerated() const { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 319 FloatRect inflatedRect = rect; | 319 FloatRect inflatedRect = rect; |
| 320 inflatedRect.inflate(1); | 320 inflatedRect.inflate(1); |
| 321 m_dirtyRect.unite(inflatedRect); | 321 m_dirtyRect.unite(inflatedRect); |
| 322 } else { | 322 } else { |
| 323 m_dirtyRect.unite(rect); | 323 m_dirtyRect.unite(rect); |
| 324 } | 324 } |
| 325 if (m_context && m_context->is2d() && hasImageBuffer()) | 325 if (m_context && m_context->is2d() && hasImageBuffer()) |
| 326 buffer()->didDraw(rect); | 326 buffer()->didDraw(rect); |
| 327 } | 327 } |
| 328 | 328 |
| 329 void HTMLCanvasElement::didDraw() { |
| 330 didDraw(FloatRect(0, 0, size().width(), size().height())); |
| 331 } |
| 332 |
| 329 void HTMLCanvasElement::finalizeFrame() { | 333 void HTMLCanvasElement::finalizeFrame() { |
| 330 if (hasImageBuffer()) | 334 if (hasImageBuffer()) |
| 331 m_imageBuffer->finalizeFrame(); | 335 m_imageBuffer->finalizeFrame(); |
| 332 | 336 |
| 333 // If the canvas is visible, notifying listeners is taken | 337 // If the canvas is visible, notifying listeners is taken |
| 334 // care of in the in doDeferredPaintInvalidation, which allows | 338 // care of in the in doDeferredPaintInvalidation, which allows |
| 335 // the frame to be grabbed prior to compositing, which is | 339 // the frame to be grabbed prior to compositing, which is |
| 336 // critically important because compositing may clear the canvas's | 340 // critically important because compositing may clear the canvas's |
| 337 // image. (e.g. WebGL context with preserveDrawingBuffer=false). | 341 // image. (e.g. WebGL context with preserveDrawingBuffer=false). |
| 338 // If the canvas is not visible, doDeferredPaintInvalidation | 342 // If the canvas is not visible, doDeferredPaintInvalidation |
| 339 // will not get called, so we need to take care of business here. | 343 // will not get called, so we need to take care of business here. |
| 340 if (!m_didNotifyListenersForCurrentFrame) | 344 if (!m_didNotifyListenersForCurrentFrame) |
| 341 notifyListenersCanvasChanged(); | 345 notifyListenersCanvasChanged(); |
| 342 m_didNotifyListenersForCurrentFrame = false; | 346 m_didNotifyListenersForCurrentFrame = false; |
| 343 } | 347 } |
| 344 | 348 |
| 345 void HTMLCanvasElement::didDisableAcceleration() { | 349 void HTMLCanvasElement::didDisableAcceleration() { |
| 346 // We must force a paint invalidation on the canvas even if it's | 350 // We must force a paint invalidation on the canvas even if it's |
| 347 // content did not change because it layer was destroyed. | 351 // content did not change because it layer was destroyed. |
| 348 didDraw(FloatRect(0, 0, size().width(), size().height())); | 352 didDraw(); |
| 349 } | 353 } |
| 350 | 354 |
| 351 void HTMLCanvasElement::restoreCanvasMatrixClipStack( | 355 void HTMLCanvasElement::restoreCanvasMatrixClipStack( |
| 352 PaintCanvas* canvas) const { | 356 PaintCanvas* canvas) const { |
| 353 if (m_context) | 357 if (m_context) |
| 354 m_context->restoreCanvasMatrixClipStack(canvas); | 358 m_context->restoreCanvasMatrixClipStack(canvas); |
| 355 } | 359 } |
| 356 | 360 |
| 357 void HTMLCanvasElement::doDeferredPaintInvalidation() { | 361 void HTMLCanvasElement::doDeferredPaintInvalidation() { |
| 358 DCHECK(!m_dirtyRect.isEmpty()); | 362 DCHECK(!m_dirtyRect.isEmpty()); |
| 359 if (m_context->is2d()) { | 363 if (m_context->is2d()) { |
| 360 FloatRect srcRect(0, 0, size().width(), size().height()); | 364 FloatRect srcRect(0, 0, size().width(), size().height()); |
| 361 m_dirtyRect.intersect(srcRect); | 365 m_dirtyRect.intersect(srcRect); |
| 362 LayoutBox* lb = layoutBox(); | 366 LayoutBox* lb = layoutBox(); |
| 363 FloatRect invalidationRect; | 367 FloatRect invalidationRect; |
| 364 if (lb) { | 368 if (lb) { |
| 365 FloatRect mappedDirtyRect = | 369 FloatRect mappedDirtyRect = |
| 366 mapRect(m_dirtyRect, srcRect, FloatRect(lb->contentBoxRect())); | 370 mapRect(m_dirtyRect, srcRect, FloatRect(lb->contentBoxRect())); |
| 367 if (m_context->isAccelerated()) { | 371 if (m_context->isComposited()) { |
| 368 // Accelerated 2D canvases need the dirty rect to be expressed relative | 372 // Accelerated 2D canvases need the dirty rect to be expressed relative |
| 369 // to the content box, as opposed to the layout box. | 373 // to the content box, as opposed to the layout box. |
| 370 mappedDirtyRect.move(-lb->contentBoxOffset()); | 374 mappedDirtyRect.move(-lb->contentBoxOffset()); |
| 371 } | 375 } |
| 372 invalidationRect = mappedDirtyRect; | 376 invalidationRect = mappedDirtyRect; |
| 373 } else { | 377 } else { |
| 374 invalidationRect = m_dirtyRect; | 378 invalidationRect = m_dirtyRect; |
| 375 } | 379 } |
| 380 |
| 381 if (m_dirtyRect.isEmpty()) |
| 382 return; |
| 383 |
| 376 if (hasImageBuffer()) { | 384 if (hasImageBuffer()) { |
| 377 m_imageBuffer->doPaintInvalidation(invalidationRect); | 385 m_imageBuffer->doPaintInvalidation(invalidationRect); |
| 378 } | 386 } |
| 379 } | 387 } |
| 380 | 388 |
| 381 if (m_dirtyRect.isEmpty()) | 389 if (m_context->getContextType() == |
| 382 return; | 390 CanvasRenderingContext::ContextImageBitmap && |
| 391 m_context->platformLayer()) { |
| 392 m_context->platformLayer()->invalidate(); |
| 393 } |
| 383 | 394 |
| 384 notifyListenersCanvasChanged(); | 395 notifyListenersCanvasChanged(); |
| 385 m_didNotifyListenersForCurrentFrame = true; | 396 m_didNotifyListenersForCurrentFrame = true; |
| 386 | 397 |
| 387 // Propagate the m_dirtyRect accumulated so far to the compositor | 398 // Propagate the m_dirtyRect accumulated so far to the compositor |
| 388 // before restarting with a blank dirty rect. | 399 // before restarting with a blank dirty rect. |
| 389 FloatRect srcRect(0, 0, size().width(), size().height()); | 400 FloatRect srcRect(0, 0, size().width(), size().height()); |
| 390 | 401 |
| 391 LayoutBox* ro = layoutBox(); | 402 LayoutBox* ro = layoutBox(); |
| 392 // Canvas content updates do not need to be propagated as | 403 // Canvas content updates do not need to be propagated as |
| 393 // paint invalidations if the canvas is accelerated, since | 404 // paint invalidations if the canvas is composited separately, since |
| 394 // the canvas contents are sent separately through a texture layer. | 405 // the canvas contents are sent separately through a texture layer. |
| 395 if (ro && (!m_context || !m_context->isAccelerated())) { | 406 if (ro && (!m_context || !m_context->isComposited())) { |
| 396 // If ro->contentBoxRect() is larger than srcRect the canvas's image is | 407 // If ro->contentBoxRect() is larger than srcRect the canvas's image is |
| 397 // being stretched, so we need to account for color bleeding caused by the | 408 // being stretched, so we need to account for color bleeding caused by the |
| 398 // interpollation filter. | 409 // interpollation filter. |
| 399 if (ro->contentBoxRect().width() > srcRect.width() || | 410 if (ro->contentBoxRect().width() > srcRect.width() || |
| 400 ro->contentBoxRect().height() > srcRect.height()) { | 411 ro->contentBoxRect().height() > srcRect.height()) { |
| 401 m_dirtyRect.inflate(0.5); | 412 m_dirtyRect.inflate(0.5); |
| 402 } | 413 } |
| 403 | 414 |
| 404 m_dirtyRect.intersect(srcRect); | 415 m_dirtyRect.intersect(srcRect); |
| 405 LayoutRect mappedDirtyRect(enclosingIntRect( | 416 LayoutRect mappedDirtyRect(enclosingIntRect( |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 if (hadImageBuffer) | 504 if (hadImageBuffer) |
| 494 layoutObject->setShouldDoFullPaintInvalidation(); | 505 layoutObject->setShouldDoFullPaintInvalidation(); |
| 495 } | 506 } |
| 496 } | 507 } |
| 497 } | 508 } |
| 498 | 509 |
| 499 bool HTMLCanvasElement::paintsIntoCanvasBuffer() const { | 510 bool HTMLCanvasElement::paintsIntoCanvasBuffer() const { |
| 500 if (placeholderFrame()) | 511 if (placeholderFrame()) |
| 501 return false; | 512 return false; |
| 502 DCHECK(m_context); | 513 DCHECK(m_context); |
| 503 if (!m_context->isAccelerated()) | 514 if (!m_context->isComposited()) |
| 504 return true; | 515 return true; |
| 505 if (layoutBox() && layoutBox()->hasAcceleratedCompositing()) | 516 if (layoutBox() && layoutBox()->hasAcceleratedCompositing()) |
| 506 return false; | 517 return false; |
| 507 | 518 |
| 508 return true; | 519 return true; |
| 509 } | 520 } |
| 510 | 521 |
| 511 void HTMLCanvasElement::notifyListenersCanvasChanged() { | 522 void HTMLCanvasElement::notifyListenersCanvasChanged() { |
| 512 if (m_listeners.size() == 0) | 523 if (m_listeners.size() == 0) |
| 513 return; | 524 return; |
| (...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1281 renderingContext()->paintRenderingResultsToCanvas(BackBuffer); | 1292 renderingContext()->paintRenderingResultsToCanvas(BackBuffer); |
| 1282 if (hasImageBuffer()) { | 1293 if (hasImageBuffer()) { |
| 1283 skImage = buffer()->newSkImageSnapshot(hint, reason); | 1294 skImage = buffer()->newSkImageSnapshot(hint, reason); |
| 1284 } else { | 1295 } else { |
| 1285 skImage = createTransparentSkImage(size()); | 1296 skImage = createTransparentSkImage(size()); |
| 1286 } | 1297 } |
| 1287 } else { | 1298 } else { |
| 1288 if (ExpensiveCanvasHeuristicParameters:: | 1299 if (ExpensiveCanvasHeuristicParameters:: |
| 1289 DisableAccelerationToAvoidReadbacks && | 1300 DisableAccelerationToAvoidReadbacks && |
| 1290 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled() && | 1301 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled() && |
| 1291 hint == PreferNoAcceleration && m_context->isAccelerated() && | 1302 hint == PreferNoAcceleration && hasImageBuffer() && |
| 1292 hasImageBuffer()) { | 1303 buffer()->isAccelerated()) { |
| 1293 buffer()->disableAcceleration(); | 1304 buffer()->disableAcceleration(); |
| 1294 } | 1305 } |
| 1295 RefPtr<Image> image = renderingContext()->getImage(hint, reason); | 1306 RefPtr<Image> image = renderingContext()->getImage(hint, reason); |
| 1296 if (image) { | 1307 if (image) { |
| 1297 skImage = image->imageForCurrentFrame(); | 1308 skImage = image->imageForCurrentFrame(); |
| 1298 } else { | 1309 } else { |
| 1299 skImage = createTransparentSkImage(size()); | 1310 skImage = createTransparentSkImage(size()); |
| 1300 } | 1311 } |
| 1301 } | 1312 } |
| 1302 | 1313 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1462 // Creates a placeholder layer first before Surface is created. | 1473 // Creates a placeholder layer first before Surface is created. |
| 1463 m_surfaceLayerBridge->createSolidColorLayer(); | 1474 m_surfaceLayerBridge->createSolidColorLayer(); |
| 1464 } | 1475 } |
| 1465 } | 1476 } |
| 1466 | 1477 |
| 1467 void HTMLCanvasElement::OnWebLayerReplaced() { | 1478 void HTMLCanvasElement::OnWebLayerReplaced() { |
| 1468 setNeedsCompositingUpdate(); | 1479 setNeedsCompositingUpdate(); |
| 1469 } | 1480 } |
| 1470 | 1481 |
| 1471 } // namespace blink | 1482 } // namespace blink |
| OLD | NEW |