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

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

Issue 2493673002: Synchronize OffscreenCanvas content with the placeholder canvas (Closed)
Patch Set: build fix Created 4 years, 1 month 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 14 matching lines...) Expand all
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28 #include "core/html/HTMLCanvasElement.h" 28 #include "core/html/HTMLCanvasElement.h"
29 29
30 #include "bindings/core/v8/ExceptionMessages.h" 30 #include "bindings/core/v8/ExceptionMessages.h"
31 #include "bindings/core/v8/ExceptionState.h" 31 #include "bindings/core/v8/ExceptionState.h"
32 #include "bindings/core/v8/ScriptController.h" 32 #include "bindings/core/v8/ScriptController.h"
33 #include "core/HTMLNames.h" 33 #include "core/HTMLNames.h"
34 #include "core/InputTypeNames.h" 34 #include "core/InputTypeNames.h"
35 #include "core/dom/DOMNodeIds.h"
xidachen 2016/11/11 16:54:00 Do we need to include this header here?
Justin Novosad 2016/11/11 22:09:00 Done.
35 #include "core/dom/Document.h" 36 #include "core/dom/Document.h"
36 #include "core/dom/Element.h" 37 #include "core/dom/Element.h"
37 #include "core/dom/ElementTraversal.h" 38 #include "core/dom/ElementTraversal.h"
38 #include "core/dom/ExceptionCode.h" 39 #include "core/dom/ExceptionCode.h"
39 #include "core/dom/TaskRunnerHelper.h" 40 #include "core/dom/TaskRunnerHelper.h"
40 #include "core/fileapi/File.h" 41 #include "core/fileapi/File.h"
41 #include "core/frame/ImageBitmap.h" 42 #include "core/frame/ImageBitmap.h"
42 #include "core/frame/LocalFrame.h" 43 #include "core/frame/LocalFrame.h"
43 #include "core/frame/Settings.h" 44 #include "core/frame/Settings.h"
44 #include "core/frame/UseCounter.h" 45 #include "core/frame/UseCounter.h"
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 } 139 }
139 140
140 DEFINE_NODE_FACTORY(HTMLCanvasElement) 141 DEFINE_NODE_FACTORY(HTMLCanvasElement)
141 142
142 HTMLCanvasElement::~HTMLCanvasElement() { 143 HTMLCanvasElement::~HTMLCanvasElement() {
143 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( 144 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
144 -m_externallyAllocatedMemory); 145 -m_externallyAllocatedMemory);
145 } 146 }
146 147
147 void HTMLCanvasElement::dispose() { 148 void HTMLCanvasElement::dispose() {
149 releasePlaceholderFrame();
150
148 if (m_context) { 151 if (m_context) {
149 m_context->detachCanvas(); 152 m_context->detachCanvas();
150 m_context = nullptr; 153 m_context = nullptr;
151 } 154 }
152 m_imageBuffer = nullptr; 155 m_imageBuffer = nullptr;
153 } 156 }
154 157
155 void HTMLCanvasElement::parseAttribute(const QualifiedName& name, 158 void HTMLCanvasElement::parseAttribute(const QualifiedName& name,
156 const AtomicString& oldValue, 159 const AtomicString& oldValue,
157 const AtomicString& value) { 160 const AtomicString& value) {
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 if (layoutBox() && layoutBox()->hasAcceleratedCompositing()) 466 if (layoutBox() && layoutBox()->hasAcceleratedCompositing())
464 layoutBox()->contentChanged(CanvasChanged); 467 layoutBox()->contentChanged(CanvasChanged);
465 } 468 }
466 if (hadImageBuffer) 469 if (hadImageBuffer)
467 layoutObject->setShouldDoFullPaintInvalidation(); 470 layoutObject->setShouldDoFullPaintInvalidation();
468 } 471 }
469 } 472 }
470 } 473 }
471 474
472 bool HTMLCanvasElement::paintsIntoCanvasBuffer() const { 475 bool HTMLCanvasElement::paintsIntoCanvasBuffer() const {
476 if (placeholderFrame())
477 return false;
473 DCHECK(m_context); 478 DCHECK(m_context);
474
475 if (!m_context->isAccelerated()) 479 if (!m_context->isAccelerated())
476 return true; 480 return true;
477 if (layoutBox() && layoutBox()->hasAcceleratedCompositing()) 481 if (layoutBox() && layoutBox()->hasAcceleratedCompositing())
478 return false; 482 return false;
479 483
480 return true; 484 return true;
481 } 485 }
482 486
483 void HTMLCanvasElement::notifyListenersCanvasChanged() { 487 void HTMLCanvasElement::notifyListenersCanvasChanged() {
484 if (m_listeners.size() == 0) 488 if (m_listeners.size() == 0)
(...skipping 23 matching lines...) Expand all
508 if (listener->needsNewFrame()) { 512 if (listener->needsNewFrame()) {
509 listener->sendNewFrame(image); 513 listener->sendNewFrame(image);
510 } 514 }
511 } 515 }
512 } 516 }
513 } 517 }
514 518
515 void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r) { 519 void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r) {
516 // FIXME: crbug.com/438240; there is a bug with the new CSS blending and 520 // FIXME: crbug.com/438240; there is a bug with the new CSS blending and
517 // compositing feature. 521 // compositing feature.
518 if (!m_context) 522 if (!m_context && !placeholderFrame())
519 return; 523 return;
520 524
521 const ComputedStyle* style = ensureComputedStyle(); 525 const ComputedStyle* style = ensureComputedStyle();
522 SkFilterQuality filterQuality = 526 SkFilterQuality filterQuality =
523 (style && style->imageRendering() == ImageRenderingPixelated) 527 (style && style->imageRendering() == ImageRenderingPixelated)
524 ? kNone_SkFilterQuality 528 ? kNone_SkFilterQuality
525 : kLow_SkFilterQuality; 529 : kLow_SkFilterQuality;
526 530
527 if (is3D()) { 531 if (is3D()) {
528 m_context->setFilterQuality(filterQuality); 532 m_context->setFilterQuality(filterQuality);
529 } else if (hasImageBuffer()) { 533 } else if (hasImageBuffer()) {
530 m_imageBuffer->setFilterQuality(filterQuality); 534 m_imageBuffer->setFilterQuality(filterQuality);
531 } 535 }
532 536
533 if (hasImageBuffer() && !m_imageBufferIsClear) 537 if (hasImageBuffer() && !m_imageBufferIsClear)
534 PaintTiming::from(document()).markFirstContentfulPaint(); 538 PaintTiming::from(document()).markFirstContentfulPaint();
535 539
536 if (!paintsIntoCanvasBuffer() && !document().printing()) 540 if (!paintsIntoCanvasBuffer() && !document().printing())
537 return; 541 return;
538 542
543 if (placeholderFrame()) {
544 DCHECK(document().printing());
545 context.drawImage(placeholderFrame().get(), pixelSnappedIntRect(r));
546 return;
547 }
548
539 // TODO(junov): Paint is currently only implemented by ImageBitmap contexts. 549 // TODO(junov): Paint is currently only implemented by ImageBitmap contexts.
540 // We could improve the abstraction by making all context types paint 550 // We could improve the abstraction by making all context types paint
541 // themselves (implement paint()). 551 // themselves (implement paint()).
542 if (m_context->paint(context, pixelSnappedIntRect(r))) 552 if (m_context->paint(context, pixelSnappedIntRect(r)))
543 return; 553 return;
544 554
545 m_context->paintRenderingResultsToCanvas(FrontBuffer); 555 m_context->paintRenderingResultsToCanvas(FrontBuffer);
546 if (hasImageBuffer()) { 556 if (hasImageBuffer()) {
547 if (!context.contextDisabled()) { 557 if (!context.contextDisabled()) {
548 SkBlendMode compositeOperator = 558 SkBlendMode compositeOperator =
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); 622 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType);
613 snapshot->readPixels(imageInfo, imageData->data()->data(), 623 snapshot->readPixels(imageInfo, imageData->data()->data(),
614 imageInfo.minRowBytes(), 0, 0); 624 imageInfo.minRowBytes(), 0, 0);
615 } 625 }
616 } 626 }
617 return imageData; 627 return imageData;
618 } 628 }
619 629
620 imageData = ImageData::create(m_size); 630 imageData = ImageData::create(m_size);
621 631
622 if (!m_context || !imageData) 632 if ((!m_context || !imageData) && !placeholderFrame())
623 return imageData; 633 return imageData;
624 634
625 DCHECK(m_context->is2d()); 635 DCHECK((m_context && m_context->is2d()) || placeholderFrame());
636 sk_sp<SkImage> snapshot;
626 if (hasImageBuffer()) { 637 if (hasImageBuffer()) {
627 sk_sp<SkImage> snapshot = 638 snapshot = buffer()->newSkImageSnapshot(PreferNoAcceleration, reason);
628 buffer()->newSkImageSnapshot(PreferNoAcceleration, reason); 639 } else if (placeholderFrame()) {
629 if (snapshot) { 640 snapshot = placeholderFrame()->imageForCurrentFrame();
630 SkImageInfo imageInfo = SkImageInfo::Make( 641 }
631 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); 642
632 snapshot->readPixels(imageInfo, imageData->data()->data(), 643 if (snapshot) {
633 imageInfo.minRowBytes(), 0, 0); 644 SkImageInfo imageInfo = SkImageInfo::Make(
634 } 645 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType);
646 snapshot->readPixels(imageInfo, imageData->data()->data(),
647 imageInfo.minRowBytes(), 0, 0);
635 } 648 }
636 649
637 return imageData; 650 return imageData;
638 } 651 }
639 652
640 String HTMLCanvasElement::toDataURLInternal( 653 String HTMLCanvasElement::toDataURLInternal(
641 const String& mimeType, 654 const String& mimeType,
642 const double& quality, 655 const double& quality,
643 SourceDrawingBuffer sourceBuffer) const { 656 SourceDrawingBuffer sourceBuffer) const {
644 if (!isPaintable()) 657 if (!isPaintable())
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 if (!imageData) // allocation failure 689 if (!imageData) // allocation failure
677 return String("data:,"); 690 return String("data:,");
678 691
679 return ImageDataBuffer(imageData->size(), imageData->data()->data()) 692 return ImageDataBuffer(imageData->size(), imageData->data()->data())
680 .toDataURL(encodingMimeType, quality); 693 .toDataURL(encodingMimeType, quality);
681 } 694 }
682 695
683 String HTMLCanvasElement::toDataURL(const String& mimeType, 696 String HTMLCanvasElement::toDataURL(const String& mimeType,
684 const ScriptValue& qualityArgument, 697 const ScriptValue& qualityArgument,
685 ExceptionState& exceptionState) const { 698 ExceptionState& exceptionState) const {
686 if (surfaceLayerBridge()) {
687 exceptionState.throwDOMException(InvalidStateError,
688 "canvas.toDataURL is not allowed for a "
689 "canvas that has transferred its control "
690 "to offscreen.");
691 return String();
692 }
693 if (!originClean()) { 699 if (!originClean()) {
694 exceptionState.throwSecurityError("Tainted canvases may not be exported."); 700 exceptionState.throwSecurityError("Tainted canvases may not be exported.");
695 return String(); 701 return String();
696 } 702 }
697 703
698 double quality = UndefinedQualityValue; 704 double quality = UndefinedQualityValue;
699 if (!qualityArgument.isEmpty()) { 705 if (!qualityArgument.isEmpty()) {
700 v8::Local<v8::Value> v8Value = qualityArgument.v8Value(); 706 v8::Local<v8::Value> v8Value = qualityArgument.v8Value();
701 if (v8Value->IsNumber()) { 707 if (v8Value->IsNumber()) {
702 quality = v8Value.As<v8::Number>()->Value(); 708 quality = v8Value.As<v8::Number>()->Value();
703 } 709 }
704 } 710 }
705 return toDataURLInternal(mimeType, quality, BackBuffer); 711 return toDataURLInternal(mimeType, quality, BackBuffer);
706 } 712 }
707 713
708 void HTMLCanvasElement::toBlob(BlobCallback* callback, 714 void HTMLCanvasElement::toBlob(BlobCallback* callback,
709 const String& mimeType, 715 const String& mimeType,
710 const ScriptValue& qualityArgument, 716 const ScriptValue& qualityArgument,
711 ExceptionState& exceptionState) { 717 ExceptionState& exceptionState) {
712 if (surfaceLayerBridge()) {
713 exceptionState.throwDOMException(InvalidStateError,
714 "canvas.toBlob is not allowed for a "
715 "canvas that has transferred its control "
716 "to offscreen.");
717 return;
718 }
719
720 if (!originClean()) { 718 if (!originClean()) {
721 exceptionState.throwSecurityError("Tainted canvases may not be exported."); 719 exceptionState.throwSecurityError("Tainted canvases may not be exported.");
722 return; 720 return;
723 } 721 }
724 722
725 if (!isPaintable()) { 723 if (!isPaintable()) {
726 // If the canvas element's bitmap has no pixels 724 // If the canvas element's bitmap has no pixels
727 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, &document()) 725 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, &document())
728 ->postTask(BLINK_FROM_HERE, 726 ->postTask(BLINK_FROM_HERE,
729 WTF::bind(&BlobCallback::handleEvent, 727 WTF::bind(&BlobCallback::handleEvent,
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
1193 if (!width() || !height()) { 1191 if (!width() || !height()) {
1194 *status = ZeroSizeCanvasSourceImageStatus; 1192 *status = ZeroSizeCanvasSourceImageStatus;
1195 return nullptr; 1193 return nullptr;
1196 } 1194 }
1197 1195
1198 if (!isPaintable()) { 1196 if (!isPaintable()) {
1199 *status = InvalidSourceImageStatus; 1197 *status = InvalidSourceImageStatus;
1200 return nullptr; 1198 return nullptr;
1201 } 1199 }
1202 1200
1201 if (placeholderFrame()) {
1202 *status = NormalSourceImageStatus;
1203 return placeholderFrame();
1204 }
1205
1203 if (!m_context) { 1206 if (!m_context) {
1204 *status = NormalSourceImageStatus; 1207 *status = NormalSourceImageStatus;
1205 return createTransparentImage(size()); 1208 return createTransparentImage(size());
1206 } 1209 }
1207 1210
1208 sk_sp<SkImage> skImage; 1211 sk_sp<SkImage> skImage;
1209 if (m_context->is3d()) { 1212 if (m_context->is3d()) {
1210 // Because WebGL sources always require making a copy of the back buffer, we 1213 // Because WebGL sources always require making a copy of the back buffer, we
1211 // use paintRenderingResultsToCanvas instead of getImage in order to keep a 1214 // use paintRenderingResultsToCanvas instead of getImage in order to keep a
1212 // cached copy of the backing in the canvas's ImageBuffer. 1215 // cached copy of the backing in the canvas's ImageBuffer.
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1357 mojom::blink::OffscreenCanvasSurfacePtr service; 1360 mojom::blink::OffscreenCanvasSurfacePtr service;
1358 Platform::current()->interfaceProvider()->getInterface( 1361 Platform::current()->interfaceProvider()->getInterface(
1359 mojo::GetProxy(&service)); 1362 mojo::GetProxy(&service));
1360 m_surfaceLayerBridge = 1363 m_surfaceLayerBridge =
1361 wrapUnique(new CanvasSurfaceLayerBridge(std::move(service))); 1364 wrapUnique(new CanvasSurfaceLayerBridge(std::move(service)));
1362 return m_surfaceLayerBridge->createSurfaceLayer(this->width(), 1365 return m_surfaceLayerBridge->createSurfaceLayer(this->width(),
1363 this->height()); 1366 this->height());
1364 } 1367 }
1365 1368
1366 } // namespace blink 1369 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698