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

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

Issue 758493004: canvas: make a temporary buffer when a context doesn't exist. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: buffer() creates noContextImageBuffer when no context Created 6 years 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 75
76 //In Skia, we will also limit width/height to 32767. 76 //In Skia, we will also limit width/height to 32767.
77 const int MaxSkiaDim = 32767; // Maximum width/height in CSS pixels. 77 const int MaxSkiaDim = 32767; // Maximum width/height in CSS pixels.
78 78
79 bool canCreateImageBuffer(const IntSize& deviceSize) 79 bool canCreateImageBuffer(const IntSize& deviceSize)
80 { 80 {
81 if (deviceSize.width() * deviceSize.height() > MaxCanvasArea) 81 if (deviceSize.width() * deviceSize.height() > MaxCanvasArea)
82 return false; 82 return false;
83 if (deviceSize.width() > MaxSkiaDim || deviceSize.height() > MaxSkiaDim) 83 if (deviceSize.width() > MaxSkiaDim || deviceSize.height() > MaxSkiaDim)
84 return false; 84 return false;
85 if (!deviceSize.width() || !deviceSize.height()) 85 if (deviceSize.isEmpty())
86 return false; 86 return false;
87 return true; 87 return true;
88 } 88 }
89 89
90 } // namespace 90 } // namespace
91 91
92 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CanvasObserver); 92 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CanvasObserver);
93 93
94 inline HTMLCanvasElement::HTMLCanvasElement(Document& document) 94 inline HTMLCanvasElement::HTMLCanvasElement(Document& document)
95 : HTMLElement(canvasTag, document) 95 : HTMLElement(canvasTag, document)
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 return lowercaseMimeType; 403 return lowercaseMimeType;
404 } 404 }
405 405
406 const AtomicString HTMLCanvasElement::imageSourceURL() const 406 const AtomicString HTMLCanvasElement::imageSourceURL() const
407 { 407 {
408 return AtomicString(toDataURLInternal("image/png", 0, FrontBuffer)); 408 return AtomicString(toDataURLInternal("image/png", 0, FrontBuffer));
409 } 409 }
410 410
411 String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double * quality, SourceDrawingBuffer sourceBuffer) const 411 String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double * quality, SourceDrawingBuffer sourceBuffer) const
412 { 412 {
413 if (m_size.isEmpty() || !canCreateImageBuffer(size())) 413 if (!buffer())
414 return String("data:,"); 414 return String("data:,");
415 415
416 String encodingMimeType = toEncodingMimeType(mimeType); 416 String encodingMimeType = toEncodingMimeType(mimeType);
417 if (!m_context) { 417 if (m_context && m_context->is3d()) {
418 RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(m_size);
419 return ImageEncoder::toDataURL(ImageEncoder::RawImageBytes(imageData->si ze(), imageData->data()->data()), encodingMimeType, quality);
420 }
421
422 if (m_context->is3d()) {
423 // Get non-premultiplied data because of inaccurate premultiplied alpha conversion of buffer()->toDataURL(). 418 // Get non-premultiplied data because of inaccurate premultiplied alpha conversion of buffer()->toDataURL().
424 RefPtrWillBeRawPtr<ImageData> imageData = 419 RefPtrWillBeRawPtr<ImageData> imageData =
425 toWebGLRenderingContext(m_context.get())->paintRenderingResultsToIma geData(sourceBuffer); 420 toWebGLRenderingContext(m_context.get())->paintRenderingResultsToIma geData(sourceBuffer);
426 if (imageData) 421 if (imageData)
427 return ImageEncoder::toDataURL(ImageEncoder::RawImageBytes(imageData ->size(), imageData->data()->data()), encodingMimeType, quality); 422 return ImageEncoder::toDataURL(ImageEncoder::RawImageBytes(imageData ->size(), imageData->data()->data()), encodingMimeType, quality);
428 m_context->paintRenderingResultsToCanvas(sourceBuffer); 423 m_context->paintRenderingResultsToCanvas(sourceBuffer);
429 } 424 }
430 425
431 return buffer()->toDataURL(encodingMimeType, quality); 426 return buffer()->toDataURL(encodingMimeType, quality);
432 } 427 }
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 if (surface->isValid()) 542 if (surface->isValid())
548 return surface.release(); 543 return surface.release();
549 surfaceFactory = createSurfaceFactory(deviceSize, msaaSampleCount); // r ecreate because old previous one was released 544 surfaceFactory = createSurfaceFactory(deviceSize, msaaSampleCount); // r ecreate because old previous one was released
550 } 545 }
551 546
552 return surfaceFactory->createSurface(deviceSize, opacityMode); 547 return surfaceFactory->createSurface(deviceSize, opacityMode);
553 } 548 }
554 549
555 void HTMLCanvasElement::createImageBuffer() 550 void HTMLCanvasElement::createImageBuffer()
556 { 551 {
552 ASSERT(m_context);
557 createImageBufferInternal(); 553 createImageBufferInternal();
558 if (m_didFailToCreateImageBuffer && m_context && m_context->is2d()) 554 if (m_didFailToCreateImageBuffer && m_context->is2d())
559 toCanvasRenderingContext2D(m_context.get())->loseContext(); 555 toCanvasRenderingContext2D(m_context.get())->loseContext();
560 } 556 }
561 557
562 void HTMLCanvasElement::createImageBufferInternal() 558 void HTMLCanvasElement::createImageBufferInternal()
563 { 559 {
564 ASSERT(!m_imageBuffer); 560 ASSERT(!m_imageBuffer);
565 ASSERT(!m_contextStateSaver); 561 ASSERT(!m_contextStateSaver);
566 562
567 m_didFailToCreateImageBuffer = true; 563 m_didFailToCreateImageBuffer = true;
568 m_imageBufferIsClear = true; 564 m_imageBufferIsClear = true;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 if (checkedExternallyAllocatedMemory.safeGet(externallyAllocatedMemory) == C heckedState::DidOverflow) 640 if (checkedExternallyAllocatedMemory.safeGet(externallyAllocatedMemory) == C heckedState::DidOverflow)
645 externallyAllocatedMemory = std::numeric_limits<intptr_t>::max(); 641 externallyAllocatedMemory = std::numeric_limits<intptr_t>::max();
646 642
647 // Subtracting two intptr_t that are known to be positive will never underfl ow. 643 // Subtracting two intptr_t that are known to be positive will never underfl ow.
648 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyA llocatedMemory - m_externallyAllocatedMemory); 644 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyA llocatedMemory - m_externallyAllocatedMemory);
649 m_externallyAllocatedMemory = externallyAllocatedMemory; 645 m_externallyAllocatedMemory = externallyAllocatedMemory;
650 } 646 }
651 647
652 GraphicsContext* HTMLCanvasElement::drawingContext() const 648 GraphicsContext* HTMLCanvasElement::drawingContext() const
653 { 649 {
654 return buffer() ? m_imageBuffer->context() : 0; 650 return buffer() && m_imageBuffer ? m_imageBuffer->context() : 0;
655 } 651 }
656 652
657 GraphicsContext* HTMLCanvasElement::existingDrawingContext() const 653 GraphicsContext* HTMLCanvasElement::existingDrawingContext() const
658 { 654 {
659 if (!hasImageBuffer()) 655 if (!hasImageBuffer())
660 return nullptr; 656 return nullptr;
661 657
662 return drawingContext(); 658 return drawingContext();
663 } 659 }
664 660
665 ImageBuffer* HTMLCanvasElement::buffer() const 661 ImageBuffer* HTMLCanvasElement::buffer() const
666 { 662 {
663 if (!m_context) {
664 if (!canCreateImageBuffer(size()))
665 return nullptr;
666 m_noContextImageBuffer = ImageBuffer::create(size(), NonOpaque);
Justin Novosad 2014/11/27 18:58:35 Please explain how this code helps. It seems waste
Justin Novosad 2014/11/27 19:04:29 Ironically, the title of this change is "Don't mak
dshwang 2014/11/27 19:34:28 That's good question. Two reason: 1. this method r
Justin Novosad 2014/11/27 20:18:15 That is a problem. We cannot guarantee that this m
dshwang 2014/11/27 20:42:17 That's true, but in that sense, most of layout tes
dshwang 2014/11/28 07:49:44 Let me explain more in the case of context.drawIma
667 return m_noContextImageBuffer.get();
668 }
669 if (m_noContextImageBuffer) {
670 m_noContextImageBuffer.clear();
671 const_cast<HTMLCanvasElement*>(this)->clearCopiedImage();
672 }
667 if (!hasImageBuffer() && !m_didFailToCreateImageBuffer) 673 if (!hasImageBuffer() && !m_didFailToCreateImageBuffer)
668 const_cast<HTMLCanvasElement*>(this)->createImageBuffer(); 674 const_cast<HTMLCanvasElement*>(this)->createImageBuffer();
669 return m_imageBuffer.get(); 675 return m_imageBuffer.get();
670 } 676 }
671 677
672 void HTMLCanvasElement::ensureUnacceleratedImageBuffer() 678 void HTMLCanvasElement::ensureUnacceleratedImageBuffer()
673 { 679 {
680 ASSERT(m_context);
674 if ((hasImageBuffer() && !m_imageBuffer->isAccelerated()) || m_didFailToCrea teImageBuffer) 681 if ((hasImageBuffer() && !m_imageBuffer->isAccelerated()) || m_didFailToCrea teImageBuffer)
675 return; 682 return;
676 discardImageBuffer(); 683 discardImageBuffer();
677 OpacityMode opacityMode = !m_context || m_context->hasAlpha() ? NonOpaque : Opaque; 684 OpacityMode opacityMode = m_context->hasAlpha() ? NonOpaque : Opaque;
678 m_imageBuffer = ImageBuffer::create(size(), opacityMode); 685 m_imageBuffer = ImageBuffer::create(size(), opacityMode);
679 m_didFailToCreateImageBuffer = !m_imageBuffer; 686 m_didFailToCreateImageBuffer = !m_imageBuffer;
680 } 687 }
681 688
682 Image* HTMLCanvasElement::copiedImage(SourceDrawingBuffer sourceBuffer) const 689 Image* HTMLCanvasElement::copiedImage(SourceDrawingBuffer sourceBuffer) const
683 { 690 {
684 if (!m_copiedImage && buffer()) { 691 if (!m_copiedImage && buffer()) {
Justin Novosad 2014/11/27 18:58:35 Not new in this patch, but there is something wron
dshwang 2014/11/27 19:34:28 Good point. I'll fix it in the separate CL. Thank
685 if (m_context && m_context->is3d()) 692 if (m_context && m_context->is3d())
686 m_context->paintRenderingResultsToCanvas(sourceBuffer); 693 m_context->paintRenderingResultsToCanvas(sourceBuffer);
687 m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled); 694 m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled);
688 updateExternallyAllocatedMemory(); 695 updateExternallyAllocatedMemory();
689 } 696 }
690 return m_copiedImage.get(); 697 return m_copiedImage.get();
691 } 698 }
692 699
693 void HTMLCanvasElement::discardImageBuffer() 700 void HTMLCanvasElement::discardImageBuffer()
694 { 701 {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 if (!buffer()) { 754 if (!buffer()) {
748 *status = InvalidSourceImageStatus; 755 *status = InvalidSourceImageStatus;
749 return nullptr; 756 return nullptr;
750 } 757 }
751 758
752 if (m_context && m_context->is3d()) { 759 if (m_context && m_context->is3d()) {
753 m_context->paintRenderingResultsToCanvas(BackBuffer); 760 m_context->paintRenderingResultsToCanvas(BackBuffer);
754 *status = ExternalSourceImageStatus; 761 *status = ExternalSourceImageStatus;
755 762
756 // can't create SkImage from WebGLImageBufferSurface (contains only SkBi tmap) 763 // can't create SkImage from WebGLImageBufferSurface (contains only SkBi tmap)
757 return m_imageBuffer->copyImage(DontCopyBackingStore, Unscaled); 764 return buffer()->copyImage(DontCopyBackingStore, Unscaled);
Justin Novosad 2014/11/27 18:58:35 I think this CL is a good opportunity to fix somet
dshwang 2014/11/27 19:34:28 That's good idea, but many const methods call buff
Justin Novosad 2014/11/27 20:18:15 Acknowledged.
758 } 765 }
759 766
760 RefPtr<SkImage> image = m_imageBuffer->newImageSnapshot(); 767 RefPtr<SkImage> image = buffer()->newImageSnapshot();
761 if (image) { 768 if (image) {
762 *status = NormalSourceImageStatus; 769 *status = NormalSourceImageStatus;
763 770
764 return StaticBitmapImage::create(image.release()); 771 return StaticBitmapImage::create(image.release());
765 } 772 }
766 773
767 774
768 *status = InvalidSourceImageStatus; 775 *status = InvalidSourceImageStatus;
769 776
770 return nullptr; 777 return nullptr;
771 } 778 }
772 779
773 bool HTMLCanvasElement::wouldTaintOrigin(SecurityOrigin*) const 780 bool HTMLCanvasElement::wouldTaintOrigin(SecurityOrigin*) const
774 { 781 {
775 return !originClean(); 782 return !originClean();
776 } 783 }
777 784
778 FloatSize HTMLCanvasElement::sourceSize() const 785 FloatSize HTMLCanvasElement::sourceSize() const
779 { 786 {
780 return FloatSize(width(), height()); 787 return FloatSize(width(), height());
781 } 788 }
782 789
783 } 790 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698