| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 | 53 |
| 54 namespace { | 54 namespace { |
| 55 enum { | 55 enum { |
| 56 InvalidMailboxIndex = -1, | 56 InvalidMailboxIndex = -1, |
| 57 MaxCanvasAnimationBacklog = 2, // Make sure the the GPU is never more than t
wo animation frames behind. | 57 MaxCanvasAnimationBacklog = 2, // Make sure the the GPU is never more than t
wo animation frames behind. |
| 58 }; | 58 }; |
| 59 } // namespace | 59 } // namespace |
| 60 | 60 |
| 61 namespace blink { | 61 namespace blink { |
| 62 | 62 |
| 63 static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size,
int msaaSampleCount, OpacityMode opacityMode, bool* surfaceIsAccelerated) | 63 static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size,
int msaaSampleCount, OpacityMode opacityMode, sk_sp<SkColorSpace> colorSpace, b
ool* surfaceIsAccelerated) |
| 64 { | 64 { |
| 65 if (gr) | 65 if (gr) |
| 66 gr->resetContext(); | 66 gr->resetContext(); |
| 67 | 67 |
| 68 SkAlphaType alphaType = (Opaque == opacityMode) ? kOpaque_SkAlphaType : kPre
mul_SkAlphaType; | 68 SkAlphaType alphaType = (Opaque == opacityMode) ? kOpaque_SkAlphaType : kPre
mul_SkAlphaType; |
| 69 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), alphaTy
pe); | 69 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), alphaTy
pe, colorSpace); |
| 70 SkSurfaceProps disableLCDProps(0, kUnknown_SkPixelGeometry); | 70 SkSurfaceProps disableLCDProps(0, kUnknown_SkPixelGeometry); |
| 71 sk_sp<SkSurface> surface; | 71 sk_sp<SkSurface> surface; |
| 72 | 72 |
| 73 if (gr) { | 73 if (gr) { |
| 74 *surfaceIsAccelerated = true; | 74 *surfaceIsAccelerated = true; |
| 75 surface = SkSurface::MakeRenderTarget(gr, SkBudgeted::kNo, info, msaaSam
pleCount, Opaque == opacityMode ? 0 : &disableLCDProps); | 75 surface = SkSurface::MakeRenderTarget(gr, SkBudgeted::kNo, info, msaaSam
pleCount, Opaque == opacityMode ? 0 : &disableLCDProps); |
| 76 } | 76 } |
| 77 | 77 |
| 78 if (!surface) { | 78 if (!surface) { |
| 79 *surfaceIsAccelerated = false; | 79 *surfaceIsAccelerated = false; |
| 80 surface = SkSurface::MakeRaster(info, Opaque == opacityMode ? 0 : &disab
leLCDProps); | 80 surface = SkSurface::MakeRaster(info, Opaque == opacityMode ? 0 : &disab
leLCDProps); |
| 81 } | 81 } |
| 82 | 82 |
| 83 if (surface) { | 83 if (surface) { |
| 84 if (opacityMode == Opaque) { | 84 if (opacityMode == Opaque) { |
| 85 surface->getCanvas()->clear(SK_ColorBLACK); | 85 surface->getCanvas()->clear(SK_ColorBLACK); |
| 86 } else { | 86 } else { |
| 87 surface->getCanvas()->clear(SK_ColorTRANSPARENT); | 87 surface->getCanvas()->clear(SK_ColorTRANSPARENT); |
| 88 } | 88 } |
| 89 } | 89 } |
| 90 return fromSkSp(surface); | 90 return fromSkSp(surface); |
| 91 } | 91 } |
| 92 | 92 |
| 93 Canvas2DLayerBridge::Canvas2DLayerBridge(std::unique_ptr<WebGraphicsContext3DPro
vider> contextProvider, const IntSize& size, int msaaSampleCount, OpacityMode op
acityMode, AccelerationMode accelerationMode) | 93 Canvas2DLayerBridge::Canvas2DLayerBridge(std::unique_ptr<WebGraphicsContext3DPro
vider> contextProvider, const IntSize& size, int msaaSampleCount, OpacityMode op
acityMode, AccelerationMode accelerationMode, sk_sp<SkColorSpace> colorSpace) |
| 94 : m_contextProvider(std::move(contextProvider)) | 94 : m_contextProvider(std::move(contextProvider)) |
| 95 , m_logger(wrapUnique(new Logger)) | 95 , m_logger(wrapUnique(new Logger)) |
| 96 , m_weakPtrFactory(this) | 96 , m_weakPtrFactory(this) |
| 97 , m_imageBuffer(0) | 97 , m_imageBuffer(0) |
| 98 , m_msaaSampleCount(msaaSampleCount) | 98 , m_msaaSampleCount(msaaSampleCount) |
| 99 , m_bytesAllocated(0) | 99 , m_bytesAllocated(0) |
| 100 , m_haveRecordedDrawCommands(false) | 100 , m_haveRecordedDrawCommands(false) |
| 101 , m_destructionInProgress(false) | 101 , m_destructionInProgress(false) |
| 102 , m_filterQuality(kLow_SkFilterQuality) | 102 , m_filterQuality(kLow_SkFilterQuality) |
| 103 , m_isHidden(false) | 103 , m_isHidden(false) |
| 104 , m_isDeferralEnabled(true) | 104 , m_isDeferralEnabled(true) |
| 105 , m_isRegisteredTaskObserver(false) | 105 , m_isRegisteredTaskObserver(false) |
| 106 , m_renderingTaskCompletedForCurrentFrame(false) | 106 , m_renderingTaskCompletedForCurrentFrame(false) |
| 107 , m_softwareRenderingWhileHidden(false) | 107 , m_softwareRenderingWhileHidden(false) |
| 108 , m_lastImageId(0) | 108 , m_lastImageId(0) |
| 109 , m_lastFilter(GL_LINEAR) | 109 , m_lastFilter(GL_LINEAR) |
| 110 , m_accelerationMode(accelerationMode) | 110 , m_accelerationMode(accelerationMode) |
| 111 , m_opacityMode(opacityMode) | 111 , m_opacityMode(opacityMode) |
| 112 , m_size(size) | 112 , m_size(size) |
| 113 , m_colorSpace(colorSpace) |
| 113 { | 114 { |
| 114 DCHECK(m_contextProvider); | 115 DCHECK(m_contextProvider); |
| 115 DCHECK(!m_contextProvider->isSoftwareRendering()); | 116 DCHECK(!m_contextProvider->isSoftwareRendering()); |
| 116 // Used by browser tests to detect the use of a Canvas2DLayerBridge. | 117 // Used by browser tests to detect the use of a Canvas2DLayerBridge. |
| 117 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_
SCOPE_GLOBAL); | 118 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_
SCOPE_GLOBAL); |
| 118 startRecording(); | 119 startRecording(); |
| 119 } | 120 } |
| 120 | 121 |
| 121 Canvas2DLayerBridge::~Canvas2DLayerBridge() | 122 Canvas2DLayerBridge::~Canvas2DLayerBridge() |
| 122 { | 123 { |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 return nullptr; // re-creation will happen through restore() | 459 return nullptr; // re-creation will happen through restore() |
| 459 } | 460 } |
| 460 | 461 |
| 461 bool wantAcceleration = shouldAccelerate(hint); | 462 bool wantAcceleration = shouldAccelerate(hint); |
| 462 if (CANVAS2D_BACKGROUND_RENDER_SWITCH_TO_CPU && isHidden() && wantAccelerati
on) { | 463 if (CANVAS2D_BACKGROUND_RENDER_SWITCH_TO_CPU && isHidden() && wantAccelerati
on) { |
| 463 wantAcceleration = false; | 464 wantAcceleration = false; |
| 464 m_softwareRenderingWhileHidden = true; | 465 m_softwareRenderingWhileHidden = true; |
| 465 } | 466 } |
| 466 | 467 |
| 467 bool surfaceIsAccelerated; | 468 bool surfaceIsAccelerated; |
| 468 m_surface = createSkSurface(wantAcceleration ? m_contextProvider->grContext(
) : nullptr, m_size, m_msaaSampleCount, m_opacityMode, &surfaceIsAccelerated); | 469 m_surface = createSkSurface(wantAcceleration ? m_contextProvider->grContext(
) : nullptr, m_size, m_msaaSampleCount, m_opacityMode, m_colorSpace, &surfaceIsA
ccelerated); |
| 469 | 470 |
| 470 if (!m_surface) | 471 if (!m_surface) |
| 471 reportSurfaceCreationFailure(); | 472 reportSurfaceCreationFailure(); |
| 472 | 473 |
| 473 if (m_surface && surfaceIsAccelerated && !m_layer) { | 474 if (m_surface && surfaceIsAccelerated && !m_layer) { |
| 474 m_layer = wrapUnique(Platform::current()->compositorSupport()->createExt
ernalTextureLayer(this)); | 475 m_layer = wrapUnique(Platform::current()->compositorSupport()->createExt
ernalTextureLayer(this)); |
| 475 m_layer->setOpaque(m_opacityMode == Opaque); | 476 m_layer->setOpaque(m_opacityMode == Opaque); |
| 476 m_layer->setBlendBackgroundColor(m_opacityMode != Opaque); | 477 m_layer->setBlendBackgroundColor(m_opacityMode != Opaque); |
| 477 GraphicsLayer::registerContentsLayer(m_layer->layer()); | 478 GraphicsLayer::registerContentsLayer(m_layer->layer()); |
| 478 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality); | 479 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality); |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 | 736 |
| 736 gpu::gles2::GLES2Interface* sharedGL = nullptr; | 737 gpu::gles2::GLES2Interface* sharedGL = nullptr; |
| 737 m_layer->clearTexture(); | 738 m_layer->clearTexture(); |
| 738 m_contextProvider = wrapUnique(Platform::current()->createSharedOffscreenGra
phicsContext3DProvider()); | 739 m_contextProvider = wrapUnique(Platform::current()->createSharedOffscreenGra
phicsContext3DProvider()); |
| 739 if (m_contextProvider) | 740 if (m_contextProvider) |
| 740 sharedGL = m_contextProvider->contextGL(); | 741 sharedGL = m_contextProvider->contextGL(); |
| 741 | 742 |
| 742 if (sharedGL && sharedGL->GetGraphicsResetStatusKHR() == GL_NO_ERROR) { | 743 if (sharedGL && sharedGL->GetGraphicsResetStatusKHR() == GL_NO_ERROR) { |
| 743 GrContext* grCtx = m_contextProvider->grContext(); | 744 GrContext* grCtx = m_contextProvider->grContext(); |
| 744 bool surfaceIsAccelerated; | 745 bool surfaceIsAccelerated; |
| 745 RefPtr<SkSurface> surface(createSkSurface(grCtx, m_size, m_msaaSampleCou
nt, m_opacityMode, &surfaceIsAccelerated)); | 746 RefPtr<SkSurface> surface(createSkSurface(grCtx, m_size, m_msaaSampleCou
nt, m_opacityMode, m_colorSpace, &surfaceIsAccelerated)); |
| 746 | 747 |
| 747 if (!m_surface) | 748 if (!m_surface) |
| 748 reportSurfaceCreationFailure(); | 749 reportSurfaceCreationFailure(); |
| 749 | 750 |
| 750 // Current paradigm does support switching from accelerated to non-accel
erated, which would be tricky | 751 // Current paradigm does support switching from accelerated to non-accel
erated, which would be tricky |
| 751 // due to changes to the layer tree, which can only happen at specific t
imes during the document lifecycle. | 752 // due to changes to the layer tree, which can only happen at specific t
imes during the document lifecycle. |
| 752 // Therefore, we can only accept the restored surface if it is accelerat
ed. | 753 // Therefore, we can only accept the restored surface if it is accelerat
ed. |
| 753 if (surface && surfaceIsAccelerated) { | 754 if (surface && surfaceIsAccelerated) { |
| 754 m_surface = surface.release(); | 755 m_surface = surface.release(); |
| 755 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 | 756 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 |
| 756 } | 757 } |
| 757 } | 758 } |
| 758 if (m_imageBuffer) | 759 if (m_imageBuffer) |
| 759 m_imageBuffer->updateGPUMemoryUsage(); | 760 m_imageBuffer->updateGPUMemoryUsage(); |
| 760 | 761 |
| 761 return m_surface.get(); | 762 return m_surface.get(); |
| 762 } | 763 } |
| 763 | 764 |
| 765 static gfx::ColorSpace SkColorSpaceToColorSpace(const SkColorSpace* skColorSpace
) |
| 766 { |
| 767 // TODO(crbug.com/634102): Eliminate this clumsy conversion by unifying |
| 768 // SkColorSpace and gfx::ColorSpace. |
| 769 if (!skColorSpace) |
| 770 return gfx::ColorSpace(); |
| 771 |
| 772 gfx::ColorSpace::TransferID transferID = gfx::ColorSpace::TransferID::UNSPEC
IFIED; |
| 773 switch (skColorSpace->gammaNamed()) { |
| 774 case SkColorSpace::kSRGB_GammaNamed: |
| 775 transferID = gfx::ColorSpace::TransferID::IEC61966_2_1; |
| 776 break; |
| 777 case SkColorSpace::kLinear_GammaNamed: |
| 778 transferID = gfx::ColorSpace::TransferID::LINEAR; |
| 779 break; |
| 780 default: |
| 781 // TODO(crbug.com/634102): Not all curve type are supported |
| 782 DCHECK(false); |
| 783 } |
| 784 |
| 785 // TODO(crbug.com/634102): No primary conversions are performed. |
| 786 // Rec-709 is assumed. |
| 787 return gfx::ColorSpace(gfx::ColorSpace::PrimaryID::BT709, transferID, gfx::C
olorSpace::MatrixID::RGB, gfx::ColorSpace::RangeID::FULL); |
| 788 } |
| 789 |
| 764 bool Canvas2DLayerBridge::PrepareTextureMailbox( | 790 bool Canvas2DLayerBridge::PrepareTextureMailbox( |
| 765 cc::TextureMailbox* outMailbox, | 791 cc::TextureMailbox* outMailbox, |
| 766 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) | 792 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) |
| 767 { | 793 { |
| 768 if (m_destructionInProgress) { | 794 if (m_destructionInProgress) { |
| 769 // It can be hit in the following sequence. | 795 // It can be hit in the following sequence. |
| 770 // 1. Canvas draws something. | 796 // 1. Canvas draws something. |
| 771 // 2. The compositor begins the frame. | 797 // 2. The compositor begins the frame. |
| 772 // 3. Javascript makes a context be lost. | 798 // 3. Javascript makes a context be lost. |
| 773 // 4. Here. | 799 // 4. Here. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 793 // Early exit if canvas was not drawn to since last prepareMailbox. | 819 // Early exit if canvas was not drawn to since last prepareMailbox. |
| 794 GLenum filter = getGLFilter(); | 820 GLenum filter = getGLFilter(); |
| 795 if (image->uniqueID() == m_lastImageId && filter == m_lastFilter) | 821 if (image->uniqueID() == m_lastImageId && filter == m_lastFilter) |
| 796 return false; | 822 return false; |
| 797 m_lastImageId = image->uniqueID(); | 823 m_lastImageId = image->uniqueID(); |
| 798 m_lastFilter = filter; | 824 m_lastFilter = filter; |
| 799 | 825 |
| 800 if (!prepareMailboxFromImage(image.release(), outMailbox)) | 826 if (!prepareMailboxFromImage(image.release(), outMailbox)) |
| 801 return false; | 827 return false; |
| 802 outMailbox->set_nearest_neighbor(getGLFilter() == GL_NEAREST); | 828 outMailbox->set_nearest_neighbor(getGLFilter() == GL_NEAREST); |
| 829 gfx::ColorSpace colorSpace = SkColorSpaceToColorSpace(m_colorSpace.get()); |
| 830 outMailbox->set_color_space(colorSpace); |
| 803 | 831 |
| 804 auto func = WTF::bind(&Canvas2DLayerBridge::mailboxReleased, | 832 auto func = WTF::bind(&Canvas2DLayerBridge::mailboxReleased, |
| 805 m_weakPtrFactory.createWeakPtr(), | 833 m_weakPtrFactory.createWeakPtr(), |
| 806 outMailbox->mailbox()); | 834 outMailbox->mailbox()); |
| 807 *outReleaseCallback = cc::SingleReleaseCallback::Create( | 835 *outReleaseCallback = cc::SingleReleaseCallback::Create( |
| 808 convertToBaseCallback(std::move(func))); | 836 convertToBaseCallback(std::move(func))); |
| 809 return true; | 837 return true; |
| 810 } | 838 } |
| 811 | 839 |
| 812 void Canvas2DLayerBridge::mailboxReleased(const gpu::Mailbox& mailbox, | 840 void Canvas2DLayerBridge::mailboxReleased(const gpu::Mailbox& mailbox, |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 Canvas2DLayerBridge::MailboxInfo::MailboxInfo() = default; | 1013 Canvas2DLayerBridge::MailboxInfo::MailboxInfo() = default; |
| 986 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) = defaul
t; | 1014 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) = defaul
t; |
| 987 | 1015 |
| 988 void Canvas2DLayerBridge::Logger::reportHibernationEvent(HibernationEvent event) | 1016 void Canvas2DLayerBridge::Logger::reportHibernationEvent(HibernationEvent event) |
| 989 { | 1017 { |
| 990 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, ("Canvas.Hib
ernationEvents", HibernationEventCount)); | 1018 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, ("Canvas.Hib
ernationEvents", HibernationEventCount)); |
| 991 hibernationHistogram.count(event); | 1019 hibernationHistogram.count(event); |
| 992 } | 1020 } |
| 993 | 1021 |
| 994 } // namespace blink | 1022 } // namespace blink |
| OLD | NEW |