Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp

Issue 2849463005: Refactor ImageBuffer to make OffscreenCanvas match HTMLCanvasElement (Closed)
Patch Set: x Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 DidDraw(); 288 DidDraw();
289 } 289 }
290 290
291 SetNeedsCompositingUpdate(); 291 SetNeedsCompositingUpdate();
292 292
293 return context_.Get(); 293 return context_.Get();
294 } 294 }
295 295
296 bool HTMLCanvasElement::ShouldBeDirectComposited() const { 296 bool HTMLCanvasElement::ShouldBeDirectComposited() const {
297 return (context_ && context_->IsComposited()) || 297 return (context_ && context_->IsComposited()) ||
298 (HasImageBuffer() && Buffer()->IsExpensiveToPaint()) || 298 (GetImageBuffer() && GetImageBuffer()->IsExpensiveToPaint()) ||
299 (!!surface_layer_bridge_); 299 (!!surface_layer_bridge_);
300 } 300 }
301 301
302 bool HTMLCanvasElement::IsPaintable() const { 302 bool HTMLCanvasElement::IsPaintable() const {
303 return (context_ && context_->IsPaintable()) || 303 return (context_ && context_->IsPaintable()) ||
304 ImageBuffer::CanCreateImageBuffer(Size()); 304 ImageBuffer::CanCreateImageBuffer(Size());
305 } 305 }
306 306
307 bool HTMLCanvasElement::IsAccelerated() const { 307 bool HTMLCanvasElement::IsAccelerated() const {
308 return context_ && context_->IsAccelerated(); 308 return context_ && context_->IsAccelerated();
309 } 309 }
310 310
311 void HTMLCanvasElement::DidDraw(const FloatRect& rect) { 311 void HTMLCanvasElement::DidDraw(const FloatRect& rect) {
312 if (rect.IsEmpty()) 312 if (rect.IsEmpty())
313 return; 313 return;
314 image_buffer_is_clear_ = false; 314 image_buffer_is_clear_ = false;
315 ClearCopiedImage(); 315 ClearCopiedImage();
316 if (GetLayoutObject()) 316 if (GetLayoutObject())
317 GetLayoutObject()->SetMayNeedPaintInvalidation(); 317 GetLayoutObject()->SetMayNeedPaintInvalidation();
318 if (Is2d() && context_->ShouldAntialias() && GetPage() && 318 if (Is2d() && context_->ShouldAntialias() && GetPage() &&
319 GetPage()->DeviceScaleFactorDeprecated() > 1.0f) { 319 GetPage()->DeviceScaleFactorDeprecated() > 1.0f) {
320 FloatRect inflated_rect = rect; 320 FloatRect inflated_rect = rect;
321 inflated_rect.Inflate(1); 321 inflated_rect.Inflate(1);
322 dirty_rect_.Unite(inflated_rect); 322 dirty_rect_.Unite(inflated_rect);
323 } else { 323 } else {
324 dirty_rect_.Unite(rect); 324 dirty_rect_.Unite(rect);
325 } 325 }
326 if (Is2d() && HasImageBuffer()) 326 if (Is2d() && GetImageBuffer())
327 Buffer()->DidDraw(rect); 327 GetImageBuffer()->DidDraw(rect);
328 } 328 }
329 329
330 void HTMLCanvasElement::DidDraw() { 330 void HTMLCanvasElement::DidDraw() {
331 DidDraw(FloatRect(0, 0, Size().Width(), Size().Height())); 331 DidDraw(FloatRect(0, 0, Size().Width(), Size().Height()));
332 } 332 }
333 333
334 void HTMLCanvasElement::FinalizeFrame() { 334 void HTMLCanvasElement::FinalizeFrame() {
335 if (HasImageBuffer()) 335 if (GetImageBuffer())
336 image_buffer_->FinalizeFrame(); 336 image_buffer_->FinalizeFrame();
337 337
338 // If the canvas is visible, notifying listeners is taken 338 // If the canvas is visible, notifying listeners is taken
339 // care of in the in doDeferredPaintInvalidation, which allows 339 // care of in the in doDeferredPaintInvalidation, which allows
340 // the frame to be grabbed prior to compositing, which is 340 // the frame to be grabbed prior to compositing, which is
341 // critically important because compositing may clear the canvas's 341 // critically important because compositing may clear the canvas's
342 // image. (e.g. WebGL context with preserveDrawingBuffer=false). 342 // image. (e.g. WebGL context with preserveDrawingBuffer=false).
343 // If the canvas is not visible, doDeferredPaintInvalidation 343 // If the canvas is not visible, doDeferredPaintInvalidation
344 // will not get called, so we need to take care of business here. 344 // will not get called, so we need to take care of business here.
345 if (!did_notify_listeners_for_current_frame_) 345 if (!did_notify_listeners_for_current_frame_)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 mapped_dirty_rect.Move(-lb->ContentBoxOffset()); 380 mapped_dirty_rect.Move(-lb->ContentBoxOffset());
381 } 381 }
382 invalidation_rect = mapped_dirty_rect; 382 invalidation_rect = mapped_dirty_rect;
383 } else { 383 } else {
384 invalidation_rect = dirty_rect_; 384 invalidation_rect = dirty_rect_;
385 } 385 }
386 386
387 if (dirty_rect_.IsEmpty()) 387 if (dirty_rect_.IsEmpty())
388 return; 388 return;
389 389
390 if (HasImageBuffer()) { 390 if (GetImageBuffer()) {
391 image_buffer_->DoPaintInvalidation(invalidation_rect); 391 image_buffer_->DoPaintInvalidation(invalidation_rect);
392 } 392 }
393 } 393 }
394 394
395 if (context_->GetContextType() == 395 if (context_->GetContextType() ==
396 CanvasRenderingContext::kContextImageBitmap && 396 CanvasRenderingContext::kContextImageBitmap &&
397 context_->PlatformLayer()) { 397 context_->PlatformLayer()) {
398 context_->PlatformLayer()->Invalidate(); 398 context_->PlatformLayer()->Invalidate();
399 } 399 }
400 400
(...skipping 24 matching lines...) Expand all
425 // FIXME: is this invalidation using the correct compositing state? 425 // FIXME: is this invalidation using the correct compositing state?
426 DisableCompositingQueryAsserts disabler; 426 DisableCompositingQueryAsserts disabler;
427 ro->InvalidatePaintRectangle(mapped_dirty_rect); 427 ro->InvalidatePaintRectangle(mapped_dirty_rect);
428 } 428 }
429 dirty_rect_ = FloatRect(); 429 dirty_rect_ = FloatRect();
430 430
431 num_frames_since_last_rendering_mode_switch_++; 431 num_frames_since_last_rendering_mode_switch_++;
432 if (RuntimeEnabledFeatures:: 432 if (RuntimeEnabledFeatures::
433 enableCanvas2dDynamicRenderingModeSwitchingEnabled() && 433 enableCanvas2dDynamicRenderingModeSwitchingEnabled() &&
434 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) { 434 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) {
435 if (Is2d() && HasImageBuffer() && Buffer()->IsAccelerated() && 435 if (Is2d() && GetImageBuffer() && GetImageBuffer()->IsAccelerated() &&
436 num_frames_since_last_rendering_mode_switch_ >= 436 num_frames_since_last_rendering_mode_switch_ >=
437 ExpensiveCanvasHeuristicParameters::kMinFramesBeforeSwitch && 437 ExpensiveCanvasHeuristicParameters::kMinFramesBeforeSwitch &&
438 !pending_rendering_mode_switch_) { 438 !pending_rendering_mode_switch_) {
439 if (!context_->IsAccelerationOptimalForCanvasContent()) { 439 if (!context_->IsAccelerationOptimalForCanvasContent()) {
440 // The switch must be done asynchronously in order to avoid switching 440 // The switch must be done asynchronously in order to avoid switching
441 // during the paint invalidation step. 441 // during the paint invalidation step.
442 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask( 442 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask(
443 BLINK_FROM_HERE, 443 BLINK_FROM_HERE,
444 WTF::Bind( 444 WTF::Bind(
445 [](WeakPtr<ImageBuffer> buffer) { 445 [](WeakPtr<ImageBuffer> buffer) {
446 if (buffer) { 446 if (buffer) {
447 buffer->DisableAcceleration(); 447 buffer->DisableAcceleration();
448 } 448 }
449 }, 449 },
450 image_buffer_->weak_ptr_factory_.CreateWeakPtr())); 450 image_buffer_->weak_ptr_factory_.CreateWeakPtr()));
451 num_frames_since_last_rendering_mode_switch_ = 0; 451 num_frames_since_last_rendering_mode_switch_ = 0;
452 pending_rendering_mode_switch_ = true; 452 pending_rendering_mode_switch_ = true;
453 } 453 }
454 } 454 }
455 } 455 }
456 456
457 if (pending_rendering_mode_switch_ && Buffer() && 457 if (pending_rendering_mode_switch_ && GetOrCreateImageBuffer() &&
458 !Buffer()->IsAccelerated()) { 458 !GetOrCreateImageBuffer()->IsAccelerated()) {
459 pending_rendering_mode_switch_ = false; 459 pending_rendering_mode_switch_ = false;
460 } 460 }
461 461
462 DCHECK(dirty_rect_.IsEmpty()); 462 DCHECK(dirty_rect_.IsEmpty());
463 } 463 }
464 464
465 void HTMLCanvasElement::Reset() { 465 void HTMLCanvasElement::Reset() {
466 if (ignore_reset_) 466 if (ignore_reset_)
467 return; 467 return;
468 468
469 dirty_rect_ = FloatRect(); 469 dirty_rect_ = FloatRect();
470 470
471 bool ok; 471 bool ok;
472 bool had_image_buffer = HasImageBuffer(); 472 bool had_image_buffer = GetImageBuffer();
473 473
474 int w = getAttribute(widthAttr).ToInt(&ok); 474 int w = getAttribute(widthAttr).ToInt(&ok);
475 if (!ok || w < 0) 475 if (!ok || w < 0)
476 w = kDefaultWidth; 476 w = kDefaultWidth;
477 477
478 int h = getAttribute(heightAttr).ToInt(&ok); 478 int h = getAttribute(heightAttr).ToInt(&ok);
479 if (!ok || h < 0) 479 if (!ok || h < 0)
480 h = kDefaultHeight; 480 h = kDefaultHeight;
481 481
482 if (Is2d()) 482 if (Is2d())
483 context_->Reset(); 483 context_->Reset();
484 484
485 IntSize old_size = Size(); 485 IntSize old_size = Size();
486 IntSize new_size(w, h); 486 IntSize new_size(w, h);
487 487
488 // If the size of an existing buffer matches, we can just clear it instead of 488 // If the size of an existing buffer matches, we can just clear it instead of
489 // reallocating. This optimization is only done for 2D canvases for now. 489 // reallocating. This optimization is only done for 2D canvases for now.
490 if (had_image_buffer && old_size == new_size && Is2d() && 490 if (had_image_buffer && old_size == new_size && Is2d() &&
491 !Buffer()->IsRecording()) { 491 !GetOrCreateImageBuffer()->IsRecording()) {
492 if (!image_buffer_is_clear_) { 492 if (!image_buffer_is_clear_) {
493 image_buffer_is_clear_ = true; 493 image_buffer_is_clear_ = true;
494 context_->clearRect(0, 0, width(), height()); 494 context_->clearRect(0, 0, width(), height());
495 } 495 }
496 return; 496 return;
497 } 497 }
498 498
499 SetSurfaceSize(new_size); 499 SetSurfaceSize(new_size);
500 500
501 if (Is3d() && old_size != Size()) 501 if (Is3d() && old_size != Size())
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 return; 565 return;
566 566
567 const ComputedStyle* style = EnsureComputedStyle(); 567 const ComputedStyle* style = EnsureComputedStyle();
568 SkFilterQuality filter_quality = 568 SkFilterQuality filter_quality =
569 (style && style->ImageRendering() == kImageRenderingPixelated) 569 (style && style->ImageRendering() == kImageRenderingPixelated)
570 ? kNone_SkFilterQuality 570 ? kNone_SkFilterQuality
571 : kLow_SkFilterQuality; 571 : kLow_SkFilterQuality;
572 572
573 if (Is3d()) { 573 if (Is3d()) {
574 context_->SetFilterQuality(filter_quality); 574 context_->SetFilterQuality(filter_quality);
575 } else if (HasImageBuffer()) { 575 } else if (GetImageBuffer()) {
576 image_buffer_->SetFilterQuality(filter_quality); 576 image_buffer_->SetFilterQuality(filter_quality);
577 } 577 }
578 578
579 if (HasImageBuffer() && !image_buffer_is_clear_) 579 if (GetImageBuffer() && !image_buffer_is_clear_)
580 PaintTiming::From(GetDocument()).MarkFirstContentfulPaint(); 580 PaintTiming::From(GetDocument()).MarkFirstContentfulPaint();
581 581
582 if (!PaintsIntoCanvasBuffer() && !GetDocument().Printing()) 582 if (!PaintsIntoCanvasBuffer() && !GetDocument().Printing())
583 return; 583 return;
584 584
585 if (PlaceholderFrame()) { 585 if (PlaceholderFrame()) {
586 DCHECK(GetDocument().Printing()); 586 DCHECK(GetDocument().Printing());
587 context.DrawImage(PlaceholderFrame().Get(), PixelSnappedIntRect(r)); 587 context.DrawImage(PlaceholderFrame().Get(), PixelSnappedIntRect(r));
588 return; 588 return;
589 } 589 }
590 590
591 // TODO(junov): Paint is currently only implemented by ImageBitmap contexts. 591 // TODO(junov): Paint is currently only implemented by ImageBitmap contexts.
592 // We could improve the abstraction by making all context types paint 592 // We could improve the abstraction by making all context types paint
593 // themselves (implement paint()). 593 // themselves (implement paint()).
594 if (context_->Paint(context, PixelSnappedIntRect(r))) 594 if (context_->Paint(context, PixelSnappedIntRect(r)))
595 return; 595 return;
596 596
597 context_->PaintRenderingResultsToCanvas(kFrontBuffer); 597 context_->PaintRenderingResultsToCanvas(kFrontBuffer);
598 if (HasImageBuffer()) { 598 if (GetImageBuffer()) {
599 if (!context.ContextDisabled()) { 599 if (!context.ContextDisabled()) {
600 SkBlendMode composite_operator = 600 SkBlendMode composite_operator =
601 !context_ || context_->CreationAttributes().alpha() 601 !context_ || context_->CreationAttributes().alpha()
602 ? SkBlendMode::kSrcOver 602 ? SkBlendMode::kSrcOver
603 : SkBlendMode::kSrc; 603 : SkBlendMode::kSrc;
604 Buffer()->Draw(context, PixelSnappedIntRect(r), 0, composite_operator); 604 GetImageBuffer()->Draw(context, PixelSnappedIntRect(r), 0,
605 composite_operator);
605 } 606 }
606 } else { 607 } else {
607 // When alpha is false, we should draw to opaque black. 608 // When alpha is false, we should draw to opaque black.
608 if (!context_->CreationAttributes().alpha()) 609 if (!context_->CreationAttributes().alpha())
609 context.FillRect(FloatRect(r), Color(0, 0, 0)); 610 context.FillRect(FloatRect(r), Color(0, 0, 0));
610 } 611 }
611 612
612 if (Is3d() && PaintsIntoCanvasBuffer()) 613 if (Is3d() && PaintsIntoCanvasBuffer())
613 context_->MarkLayerComposited(); 614 context_->MarkLayerComposited();
614 } 615 }
615 616
616 bool HTMLCanvasElement::Is3d() const { 617 bool HTMLCanvasElement::Is3d() const {
617 return context_ && context_->Is3d(); 618 return context_ && context_->Is3d();
618 } 619 }
619 620
620 bool HTMLCanvasElement::Is2d() const { 621 bool HTMLCanvasElement::Is2d() const {
621 return context_ && context_->Is2d(); 622 return context_ && context_->Is2d();
622 } 623 }
623 624
624 bool HTMLCanvasElement::IsAnimated2d() const { 625 bool HTMLCanvasElement::IsAnimated2d() const {
625 return Is2d() && HasImageBuffer() && image_buffer_->WasDrawnToAfterSnapshot(); 626 return Is2d() && GetImageBuffer() &&
627 GetImageBuffer()->WasDrawnToAfterSnapshot();
626 } 628 }
627 629
628 void HTMLCanvasElement::SetSurfaceSize(const IntSize& size) { 630 void HTMLCanvasElement::SetSurfaceSize(const IntSize& size) {
629 size_ = size; 631 size_ = size;
630 did_fail_to_create_image_buffer_ = false; 632 did_fail_to_create_image_buffer_ = false;
631 DiscardImageBuffer(); 633 DiscardImageBuffer();
632 ClearCopiedImage(); 634 ClearCopiedImage();
633 if (Is2d() && context_->isContextLost()) { 635 if (Is2d() && context_->isContextLost()) {
634 context_->DidSetSurfaceSize(); 636 context_->DidSetSurfaceSize();
635 } 637 }
636 } 638 }
637 639
638 const AtomicString HTMLCanvasElement::ImageSourceURL() const { 640 const AtomicString HTMLCanvasElement::ImageSourceURL() const {
639 return AtomicString( 641 return AtomicString(
640 ToDataURLInternal(ImageEncoderUtils::kDefaultMimeType, 0, kFrontBuffer)); 642 ToDataURLInternal(ImageEncoderUtils::kDefaultMimeType, 0, kFrontBuffer));
641 } 643 }
642 644
643 void HTMLCanvasElement::PrepareSurfaceForPaintingIfNeeded() const { 645 void HTMLCanvasElement::PrepareSurfaceForPaintingIfNeeded() {
644 DCHECK(Is2d()); // This function is called by the 2d context 646 DCHECK(Is2d()); // This function is called by the 2d context
645 if (Buffer()) 647 if (GetOrCreateImageBuffer())
646 image_buffer_->PrepareSurfaceForPaintingIfNeeded(); 648 image_buffer_->PrepareSurfaceForPaintingIfNeeded();
647 } 649 }
648 650
649 ImageData* HTMLCanvasElement::ToImageData(SourceDrawingBuffer source_buffer, 651 ImageData* HTMLCanvasElement::ToImageData(SourceDrawingBuffer source_buffer,
650 SnapshotReason reason) const { 652 SnapshotReason reason) const {
651 ImageData* image_data; 653 ImageData* image_data;
652 if (Is3d()) { 654 if (Is3d()) {
653 // Get non-premultiplied data because of inaccurate premultiplied alpha 655 // Get non-premultiplied data because of inaccurate premultiplied alpha
654 // conversion of buffer()->toDataURL(). 656 // conversion of buffer()->toDataURL().
655 image_data = context_->PaintRenderingResultsToImageData(source_buffer); 657 image_data = context_->PaintRenderingResultsToImageData(source_buffer);
656 if (image_data) 658 if (image_data)
657 return image_data; 659 return image_data;
658 660
659 context_->PaintRenderingResultsToCanvas(source_buffer); 661 context_->PaintRenderingResultsToCanvas(source_buffer);
660 image_data = ImageData::Create(size_); 662 image_data = ImageData::Create(size_);
661 if (image_data && HasImageBuffer()) { 663 if (image_data && GetImageBuffer()) {
662 sk_sp<SkImage> snapshot = 664 sk_sp<SkImage> snapshot =
663 Buffer()->NewSkImageSnapshot(kPreferNoAcceleration, reason); 665 GetImageBuffer()->NewSkImageSnapshot(kPreferNoAcceleration, reason);
664 if (snapshot) { 666 if (snapshot) {
665 SkImageInfo image_info = SkImageInfo::Make( 667 SkImageInfo image_info = SkImageInfo::Make(
666 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); 668 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType);
667 snapshot->readPixels(image_info, image_data->data()->Data(), 669 snapshot->readPixels(image_info, image_data->data()->Data(),
668 image_info.minRowBytes(), 0, 0); 670 image_info.minRowBytes(), 0, 0);
669 } 671 }
670 } 672 }
671 return image_data; 673 return image_data;
672 } 674 }
673 675
674 image_data = ImageData::Create(size_); 676 image_data = ImageData::Create(size_);
675 677
676 if ((!context_ || !image_data) && !PlaceholderFrame()) 678 if ((!context_ || !image_data) && !PlaceholderFrame())
677 return image_data; 679 return image_data;
678 680
679 DCHECK(Is2d() || PlaceholderFrame()); 681 DCHECK(Is2d() || PlaceholderFrame());
680 sk_sp<SkImage> snapshot; 682 sk_sp<SkImage> snapshot;
681 if (HasImageBuffer()) { 683 if (GetImageBuffer()) {
682 snapshot = Buffer()->NewSkImageSnapshot(kPreferNoAcceleration, reason); 684 snapshot =
685 GetImageBuffer()->NewSkImageSnapshot(kPreferNoAcceleration, reason);
683 } else if (PlaceholderFrame()) { 686 } else if (PlaceholderFrame()) {
684 DCHECK(PlaceholderFrame()->OriginClean()); 687 DCHECK(PlaceholderFrame()->OriginClean());
685 snapshot = PlaceholderFrame()->ImageForCurrentFrame(); 688 snapshot = PlaceholderFrame()->ImageForCurrentFrame();
686 } 689 }
687 690
688 if (snapshot) { 691 if (snapshot) {
689 SkImageInfo image_info = SkImageInfo::Make( 692 SkImageInfo image_info = SkImageInfo::Make(
690 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); 693 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType);
691 snapshot->readPixels(image_info, image_data->data()->Data(), 694 snapshot->readPixels(image_info, image_data->data()->Data(),
692 image_info.minRowBytes(), 0, 0); 695 image_info.minRowBytes(), 0, 0);
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 checked_externally_allocated_memory.ValueOrDefault( 1090 checked_externally_allocated_memory.ValueOrDefault(
1088 std::numeric_limits<intptr_t>::max()); 1091 std::numeric_limits<intptr_t>::max());
1089 1092
1090 // Subtracting two intptr_t that are known to be positive will never 1093 // Subtracting two intptr_t that are known to be positive will never
1091 // underflow. 1094 // underflow.
1092 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( 1095 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
1093 externally_allocated_memory - externally_allocated_memory_); 1096 externally_allocated_memory - externally_allocated_memory_);
1094 externally_allocated_memory_ = externally_allocated_memory; 1097 externally_allocated_memory_ = externally_allocated_memory;
1095 } 1098 }
1096 1099
1097 PaintCanvas* HTMLCanvasElement::DrawingCanvas() const { 1100 PaintCanvas* HTMLCanvasElement::DrawingCanvas() {
1098 return Buffer() ? image_buffer_->Canvas() : nullptr; 1101 return GetOrCreateImageBuffer() ? GetImageBuffer()->Canvas() : nullptr;
1099 } 1102 }
1100 1103
1101 void HTMLCanvasElement::DisableDeferral(DisableDeferralReason reason) const { 1104 void HTMLCanvasElement::DisableDeferral(DisableDeferralReason reason) {
1102 if (Buffer()) 1105 if (GetOrCreateImageBuffer())
1103 image_buffer_->DisableDeferral(reason); 1106 image_buffer_->DisableDeferral(reason);
1104 } 1107 }
1105 1108
1106 PaintCanvas* HTMLCanvasElement::ExistingDrawingCanvas() const { 1109 PaintCanvas* HTMLCanvasElement::ExistingDrawingCanvas() const {
1107 if (!HasImageBuffer()) 1110 if (!GetImageBuffer())
1108 return nullptr; 1111 return nullptr;
1109 1112
1110 return image_buffer_->Canvas(); 1113 return image_buffer_->Canvas();
1111 } 1114 }
1112 1115
1113 ImageBuffer* HTMLCanvasElement::Buffer() const { 1116 ImageBuffer* HTMLCanvasElement::GetOrCreateImageBuffer() {
1114 DCHECK(context_); 1117 DCHECK(context_);
1115 DCHECK(context_->GetContextType() != 1118 DCHECK(context_->GetContextType() !=
1116 CanvasRenderingContext::kContextImageBitmap); 1119 CanvasRenderingContext::kContextImageBitmap);
1117 if (!HasImageBuffer() && !did_fail_to_create_image_buffer_) 1120 if (!image_buffer_ && !did_fail_to_create_image_buffer_)
1118 const_cast<HTMLCanvasElement*>(this)->CreateImageBuffer(); 1121 CreateImageBuffer();
1119 return image_buffer_.get(); 1122 return image_buffer_.get();
1120 } 1123 }
1121 1124
1122 void HTMLCanvasElement::CreateImageBufferUsingSurfaceForTesting( 1125 void HTMLCanvasElement::CreateImageBufferUsingSurfaceForTesting(
1123 std::unique_ptr<ImageBufferSurface> surface) { 1126 std::unique_ptr<ImageBufferSurface> surface) {
1124 DiscardImageBuffer(); 1127 DiscardImageBuffer();
1125 SetIntegralAttribute(widthAttr, surface->size().Width()); 1128 SetIntegralAttribute(widthAttr, surface->size().Width());
1126 SetIntegralAttribute(heightAttr, surface->size().Height()); 1129 SetIntegralAttribute(heightAttr, surface->size().Height());
1127 CreateImageBufferInternal(std::move(surface)); 1130 CreateImageBufferInternal(std::move(surface));
1128 } 1131 }
1129 1132
1130 void HTMLCanvasElement::EnsureUnacceleratedImageBuffer() { 1133 void HTMLCanvasElement::EnsureUnacceleratedImageBuffer() {
1131 DCHECK(context_); 1134 DCHECK(context_);
1132 if ((HasImageBuffer() && !image_buffer_->IsAccelerated()) || 1135 if ((GetImageBuffer() && !GetImageBuffer()->IsAccelerated()) ||
1133 did_fail_to_create_image_buffer_) 1136 did_fail_to_create_image_buffer_)
1134 return; 1137 return;
1135 DiscardImageBuffer(); 1138 DiscardImageBuffer();
1136 OpacityMode opacity_mode = 1139 OpacityMode opacity_mode =
1137 context_->CreationAttributes().alpha() ? kNonOpaque : kOpaque; 1140 context_->CreationAttributes().alpha() ? kNonOpaque : kOpaque;
1138 image_buffer_ = ImageBuffer::Create(Size(), opacity_mode); 1141 image_buffer_ = ImageBuffer::Create(Size(), opacity_mode);
1139 did_fail_to_create_image_buffer_ = !image_buffer_; 1142 did_fail_to_create_image_buffer_ = !image_buffer_;
1140 } 1143 }
1141 1144
1142 PassRefPtr<Image> HTMLCanvasElement::CopiedImage( 1145 PassRefPtr<Image> HTMLCanvasElement::CopiedImage(
1143 SourceDrawingBuffer source_buffer, 1146 SourceDrawingBuffer source_buffer,
1144 AccelerationHint hint, 1147 AccelerationHint hint,
1145 SnapshotReason snapshot_reason) const { 1148 SnapshotReason snapshot_reason) {
1146 if (!IsPaintable()) 1149 if (!IsPaintable())
1147 return nullptr; 1150 return nullptr;
1148 if (!context_) 1151 if (!context_)
1149 return CreateTransparentImage(Size()); 1152 return CreateTransparentImage(Size());
1150 1153
1151 if (context_->GetContextType() == 1154 if (context_->GetContextType() ==
1152 CanvasRenderingContext::kContextImageBitmap) { 1155 CanvasRenderingContext::kContextImageBitmap) {
1153 RefPtr<Image> image = context_->GetImage(hint, snapshot_reason); 1156 RefPtr<Image> image = context_->GetImage(hint, snapshot_reason);
1157 // TODO(fserb): return image?
1154 if (image) 1158 if (image)
1155 return context_->GetImage(hint, snapshot_reason); 1159 return context_->GetImage(hint, snapshot_reason);
1156 // Special case: transferFromImageBitmap is not yet called. 1160 // Special case: transferFromImageBitmap is not yet called.
1157 sk_sp<SkSurface> surface = 1161 sk_sp<SkSurface> surface =
1158 SkSurface::MakeRasterN32Premul(width(), height()); 1162 SkSurface::MakeRasterN32Premul(width(), height());
1159 return StaticBitmapImage::Create(surface->makeImageSnapshot()); 1163 return StaticBitmapImage::Create(surface->makeImageSnapshot());
1160 } 1164 }
1161 1165
1162 bool need_to_update = !copied_image_; 1166 bool need_to_update = !copied_image_;
1163 // The concept of SourceDrawingBuffer is valid on only WebGL. 1167 // The concept of SourceDrawingBuffer is valid on only WebGL.
1164 if (context_->Is3d()) 1168 if (context_->Is3d())
1165 need_to_update |= context_->PaintRenderingResultsToCanvas(source_buffer); 1169 need_to_update |= context_->PaintRenderingResultsToCanvas(source_buffer);
1166 if (need_to_update && Buffer()) { 1170 if (need_to_update && GetOrCreateImageBuffer()) {
1167 copied_image_ = Buffer()->NewImageSnapshot(hint, snapshot_reason); 1171 copied_image_ = GetImageBuffer()->NewImageSnapshot(hint, snapshot_reason);
1168 UpdateExternallyAllocatedMemory(); 1172 UpdateExternallyAllocatedMemory();
1169 } 1173 }
1170 return copied_image_; 1174 return copied_image_;
1171 } 1175 }
1172 1176
1173 void HTMLCanvasElement::DiscardImageBuffer() { 1177 void HTMLCanvasElement::DiscardImageBuffer() {
1174 image_buffer_.reset(); 1178 image_buffer_.reset();
1175 dirty_rect_ = FloatRect(); 1179 dirty_rect_ = FloatRect();
1176 UpdateExternallyAllocatedMemory(); 1180 UpdateExternallyAllocatedMemory();
1177 } 1181 }
1178 1182
1179 void HTMLCanvasElement::ClearCopiedImage() { 1183 void HTMLCanvasElement::ClearCopiedImage() {
1180 if (copied_image_) { 1184 if (copied_image_) {
1181 copied_image_.Clear(); 1185 copied_image_.Clear();
1182 UpdateExternallyAllocatedMemory(); 1186 UpdateExternallyAllocatedMemory();
1183 } 1187 }
1184 } 1188 }
1185 1189
1186 AffineTransform HTMLCanvasElement::BaseTransform() const { 1190 AffineTransform HTMLCanvasElement::BaseTransform() const {
1187 DCHECK(HasImageBuffer() && !did_fail_to_create_image_buffer_); 1191 DCHECK(GetImageBuffer() && !did_fail_to_create_image_buffer_);
1188 return image_buffer_->BaseTransform(); 1192 return image_buffer_->BaseTransform();
1189 } 1193 }
1190 1194
1191 void HTMLCanvasElement::PageVisibilityChanged() { 1195 void HTMLCanvasElement::PageVisibilityChanged() {
1192 if (!context_) 1196 if (!context_)
1193 return; 1197 return;
1194 1198
1195 bool hidden = !GetPage()->IsPageVisible(); 1199 bool hidden = !GetPage()->IsPageVisible();
1196 context_->SetIsHidden(hidden); 1200 context_->SetIsHidden(hidden);
1197 if (hidden) { 1201 if (hidden) {
(...skipping 17 matching lines...) Expand all
1215 1219
1216 void HTMLCanvasElement::DidMoveToNewDocument(Document& old_document) { 1220 void HTMLCanvasElement::DidMoveToNewDocument(Document& old_document) {
1217 ContextLifecycleObserver::SetContext(&GetDocument()); 1221 ContextLifecycleObserver::SetContext(&GetDocument());
1218 PageVisibilityObserver::SetContext(GetDocument().GetPage()); 1222 PageVisibilityObserver::SetContext(GetDocument().GetPage());
1219 HTMLElement::DidMoveToNewDocument(old_document); 1223 HTMLElement::DidMoveToNewDocument(old_document);
1220 } 1224 }
1221 1225
1222 void HTMLCanvasElement::WillDrawImageTo2DContext(CanvasImageSource* source) { 1226 void HTMLCanvasElement::WillDrawImageTo2DContext(CanvasImageSource* source) {
1223 if (ExpensiveCanvasHeuristicParameters::kEnableAccelerationToAvoidReadbacks && 1227 if (ExpensiveCanvasHeuristicParameters::kEnableAccelerationToAvoidReadbacks &&
1224 SharedGpuContext::AllowSoftwareToAcceleratedCanvasUpgrade() && 1228 SharedGpuContext::AllowSoftwareToAcceleratedCanvasUpgrade() &&
1225 source->IsAccelerated() && !Buffer()->IsAccelerated() && 1229 source->IsAccelerated() && !GetOrCreateImageBuffer()->IsAccelerated() &&
1226 ShouldAccelerate(kIgnoreResourceLimitCriteria)) { 1230 ShouldAccelerate(kIgnoreResourceLimitCriteria)) {
1227 OpacityMode opacity_mode = 1231 OpacityMode opacity_mode =
1228 context_->CreationAttributes().alpha() ? kNonOpaque : kOpaque; 1232 context_->CreationAttributes().alpha() ? kNonOpaque : kOpaque;
1229 int msaa_sample_count = 0; 1233 int msaa_sample_count = 0;
1230 std::unique_ptr<ImageBufferSurface> surface = 1234 std::unique_ptr<ImageBufferSurface> surface =
1231 CreateAcceleratedImageBufferSurface(opacity_mode, &msaa_sample_count); 1235 CreateAcceleratedImageBufferSurface(opacity_mode, &msaa_sample_count);
1232 if (surface) { 1236 if (surface) {
1233 Buffer()->SetSurface(std::move(surface)); 1237 GetOrCreateImageBuffer()->SetSurface(std::move(surface));
1234 SetNeedsCompositingUpdate(); 1238 SetNeedsCompositingUpdate();
1235 } 1239 }
1236 } 1240 }
1237 } 1241 }
1238 1242
1239 PassRefPtr<Image> HTMLCanvasElement::GetSourceImageForCanvas( 1243 PassRefPtr<Image> HTMLCanvasElement::GetSourceImageForCanvas(
1240 SourceImageStatus* status, 1244 SourceImageStatus* status,
1241 AccelerationHint hint, 1245 AccelerationHint hint,
1242 SnapshotReason reason, 1246 SnapshotReason reason,
1243 const FloatSize&) const { 1247 const FloatSize&) {
1244 if (!width() || !height()) { 1248 if (!width() || !height()) {
1245 *status = kZeroSizeCanvasSourceImageStatus; 1249 *status = kZeroSizeCanvasSourceImageStatus;
1246 return nullptr; 1250 return nullptr;
1247 } 1251 }
1248 1252
1249 if (!IsPaintable()) { 1253 if (!IsPaintable()) {
1250 *status = kInvalidSourceImageStatus; 1254 *status = kInvalidSourceImageStatus;
1251 return nullptr; 1255 return nullptr;
1252 } 1256 }
1253 1257
(...skipping 15 matching lines...) Expand all
1269 } 1273 }
1270 1274
1271 sk_sp<SkImage> sk_image; 1275 sk_sp<SkImage> sk_image;
1272 // TODO(ccameron): Canvas should produce sRGB images. 1276 // TODO(ccameron): Canvas should produce sRGB images.
1273 // https://crbug.com/672299 1277 // https://crbug.com/672299
1274 if (Is3d()) { 1278 if (Is3d()) {
1275 // Because WebGL sources always require making a copy of the back buffer, we 1279 // Because WebGL sources always require making a copy of the back buffer, we
1276 // use paintRenderingResultsToCanvas instead of getImage in order to keep a 1280 // use paintRenderingResultsToCanvas instead of getImage in order to keep a
1277 // cached copy of the backing in the canvas's ImageBuffer. 1281 // cached copy of the backing in the canvas's ImageBuffer.
1278 RenderingContext()->PaintRenderingResultsToCanvas(kBackBuffer); 1282 RenderingContext()->PaintRenderingResultsToCanvas(kBackBuffer);
1279 if (HasImageBuffer()) { 1283 if (GetImageBuffer()) {
1280 sk_image = Buffer()->NewSkImageSnapshot(hint, reason); 1284 sk_image = GetImageBuffer()->NewSkImageSnapshot(hint, reason);
1281 } else { 1285 } else {
1282 sk_image = CreateTransparentSkImage(Size()); 1286 sk_image = CreateTransparentSkImage(Size());
1283 } 1287 }
1284 } else { 1288 } else {
1285 if (ExpensiveCanvasHeuristicParameters:: 1289 if (ExpensiveCanvasHeuristicParameters::
1286 kDisableAccelerationToAvoidReadbacks && 1290 kDisableAccelerationToAvoidReadbacks &&
1287 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled() && 1291 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled() &&
1288 hint == kPreferNoAcceleration && HasImageBuffer() && 1292 hint == kPreferNoAcceleration && GetImageBuffer() &&
1289 Buffer()->IsAccelerated()) { 1293 GetImageBuffer()->IsAccelerated()) {
1290 Buffer()->DisableAcceleration(); 1294 GetImageBuffer()->DisableAcceleration();
1291 } 1295 }
1292 RefPtr<Image> image = RenderingContext()->GetImage(hint, reason); 1296 RefPtr<Image> image = RenderingContext()->GetImage(hint, reason);
1293 if (image) { 1297 if (image) {
1294 sk_image = image->ImageForCurrentFrame(); 1298 sk_image = image->ImageForCurrentFrame();
1295 } else { 1299 } else {
1296 sk_image = CreateTransparentSkImage(Size()); 1300 sk_image = CreateTransparentSkImage(Size());
1297 } 1301 }
1298 } 1302 }
1299 1303
1300 if (sk_image) { 1304 if (sk_image) {
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1459 // Creates a placeholder layer first before Surface is created. 1463 // Creates a placeholder layer first before Surface is created.
1460 surface_layer_bridge_->CreateSolidColorLayer(); 1464 surface_layer_bridge_->CreateSolidColorLayer();
1461 } 1465 }
1462 } 1466 }
1463 1467
1464 void HTMLCanvasElement::OnWebLayerReplaced() { 1468 void HTMLCanvasElement::OnWebLayerReplaced() {
1465 SetNeedsCompositingUpdate(); 1469 SetNeedsCompositingUpdate();
1466 } 1470 }
1467 1471
1468 } // namespace blink 1472 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLCanvasElement.h ('k') | third_party/WebKit/Source/core/html/HTMLVideoElement.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698