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 |