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 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
735 return document().getSecurityOrigin(); | 735 return document().getSecurityOrigin(); |
736 } | 736 } |
737 | 737 |
738 bool HTMLCanvasElement::originClean() const | 738 bool HTMLCanvasElement::originClean() const |
739 { | 739 { |
740 if (document().settings() && document().settings()->disableReadingFromCanvas ()) | 740 if (document().settings() && document().settings()->disableReadingFromCanvas ()) |
741 return false; | 741 return false; |
742 return m_originClean; | 742 return m_originClean; |
743 } | 743 } |
744 | 744 |
745 bool HTMLCanvasElement::shouldAccelerate(const IntSize& size, const WebGraphicsC ontext3DProvider* sharedMainThreadContextProvider) const | 745 bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const |
746 { | 746 { |
747 if (m_context && !m_context->is2d()) | 747 if (m_context && !m_context->is2d()) |
748 return false; | 748 return false; |
749 | 749 |
750 if (RuntimeEnabledFeatures::forceDisplayList2dCanvasEnabled()) | 750 if (RuntimeEnabledFeatures::forceDisplayList2dCanvasEnabled()) |
751 return false; | 751 return false; |
752 | 752 |
753 if (!RuntimeEnabledFeatures::accelerated2dCanvasEnabled()) | 753 if (!RuntimeEnabledFeatures::accelerated2dCanvasEnabled()) |
754 return false; | 754 return false; |
755 | 755 |
(...skipping 22 matching lines...) Expand all Loading... | |
778 // If the GPU resources would be very expensive, prefer a display list. | 778 // If the GPU resources would be very expensive, prefer a display list. |
779 if (canvasPixelCount > ExpensiveCanvasHeuristicParameters::PreferDisplay ListOverGpuSizeThreshold) | 779 if (canvasPixelCount > ExpensiveCanvasHeuristicParameters::PreferDisplay ListOverGpuSizeThreshold) |
780 return false; | 780 return false; |
781 } | 781 } |
782 | 782 |
783 // Do not use acceleration for small canvas. | 783 // Do not use acceleration for small canvas. |
784 Settings* settings = document().settings(); | 784 Settings* settings = document().settings(); |
785 if (!settings || canvasPixelCount < settings->minimumAccelerated2dCanvasSize ()) | 785 if (!settings || canvasPixelCount < settings->minimumAccelerated2dCanvasSize ()) |
786 return false; | 786 return false; |
787 | 787 |
788 if (sharedMainThreadContextProvider->isSoftwareRendering()) | |
789 return false; | |
790 | |
791 // When GPU allocated memory runs low (due to having created too many | 788 // When GPU allocated memory runs low (due to having created too many |
792 // accelerated canvases), the compositor starves and browser becomes laggy. | 789 // accelerated canvases), the compositor starves and browser becomes laggy. |
793 // Thus, we should stop allocating more GPU memory to new canvases created | 790 // Thus, we should stop allocating more GPU memory to new canvases created |
794 // when the current memory usage exceeds the threshold. | 791 // when the current memory usage exceeds the threshold. |
795 if (ImageBuffer::getGlobalGPUMemoryUsage() >= MaxGlobalGPUMemoryUsage) | 792 if (ImageBuffer::getGlobalGPUMemoryUsage() >= MaxGlobalGPUMemoryUsage) |
796 return false; | 793 return false; |
797 | 794 |
798 // Allocating too many GPU resources can makes us run into the driver's | 795 // Allocating too many GPU resources can makes us run into the driver's |
799 // resource limits. So we need to keep the number of texture resources | 796 // resource limits. So we need to keep the number of texture resources |
800 // under tight control | 797 // under tight control |
(...skipping 17 matching lines...) Expand all Loading... | |
818 { | 815 { |
819 if (RuntimeEnabledFeatures::forceDisplayList2dCanvasEnabled()) | 816 if (RuntimeEnabledFeatures::forceDisplayList2dCanvasEnabled()) |
820 return true; | 817 return true; |
821 | 818 |
822 if (!RuntimeEnabledFeatures::displayList2dCanvasEnabled()) | 819 if (!RuntimeEnabledFeatures::displayList2dCanvasEnabled()) |
823 return false; | 820 return false; |
824 | 821 |
825 return true; | 822 return true; |
826 } | 823 } |
827 | 824 |
828 std::unique_ptr<ImageBufferSurface> HTMLCanvasElement::createImageBufferSurface( const IntSize& deviceSize, int* msaaSampleCount, sk_sp<SkColorSpace> colorSpace) | 825 std::unique_ptr<ImageBufferSurface> HTMLCanvasElement::createAcceleratedImageBuf ferSurface(const IntSize& deviceSize, OpacityMode opacityMode, sk_sp<SkColorSpac e> colorSpace, int* msaaSampleCount) |
829 { | 826 { |
830 OpacityMode opacityMode = !m_context || m_context->creationAttributes().alph a() ? NonOpaque : Opaque; | |
831 | |
832 *msaaSampleCount = 0; | |
833 if (is3D()) { | 827 if (is3D()) { |
834 // If 3d, but the use of the canvas will be for non-accelerated content | 828 // If 3d, but the use of the canvas will be for non-accelerated content |
835 // then make a non-accelerated ImageBuffer. This means copying the inter nal | 829 // then make a non-accelerated ImageBuffer. This means copying the inter nal |
836 // Image will require a pixel readback, but that is unavoidable in this case. | 830 // Image will require a pixel readback, but that is unavoidable in this case. |
837 return wrapUnique(new AcceleratedImageBufferSurface(deviceSize, opacityM ode, colorSpace)); | 831 return wrapUnique(new AcceleratedImageBufferSurface(deviceSize, opacityM ode, colorSpace)); |
838 } | 832 } |
839 | 833 |
840 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider = wrapUnique(P latform::current()->createSharedOffscreenGraphicsContext3DProvider()); | 834 if (!shouldAccelerate(deviceSize)) |
835 return nullptr; | |
836 | |
837 if (document().settings()) | |
838 *msaaSampleCount = document().settings()->accelerated2dCanvasMSAASampleC ount(); | |
839 | |
840 // Avoid creating |contextProvider| until we're sure we want to try use it, | |
841 // since it costs us GPU memory. | |
842 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider(Platform::curr ent()->createSharedOffscreenGraphicsContext3DProvider()); | |
841 if (!contextProvider) { | 843 if (!contextProvider) { |
842 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Accelerated2DCanva sGPUContextLost); | 844 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Accelerated2DCanva sGPUContextLost); |
843 } else if (shouldAccelerate(deviceSize, contextProvider.get())) { | 845 return nullptr; |
844 if (document().settings()) | |
845 *msaaSampleCount = document().settings()->accelerated2dCanvasMSAASam pleCount(); | |
846 std::unique_ptr<ImageBufferSurface> surface = wrapUnique(new Canvas2DIma geBufferSurface(std::move(contextProvider), deviceSize, *msaaSampleCount, opacit yMode, Canvas2DLayerBridge::EnableAcceleration, colorSpace)); | |
847 if (surface->isValid()) { | |
848 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated 2DCanvasImageBufferCreated); | |
849 return surface; | |
850 } | |
851 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCa nvasImageBufferCreationFailed); | |
852 } | 846 } |
853 | 847 |
854 std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory> surfaceFactory = wrapUnique(new UnacceleratedSurfaceFactory()); | 848 if (contextProvider->isSoftwareRendering()) |
Justin Novosad
2016/08/26 14:11:12
In a follow-up CL It would be nice to be able to m
| |
849 return nullptr; // Don't use accelerated canvas with swiftshader. | |
855 | 850 |
851 std::unique_ptr<ImageBufferSurface> surface = wrapUnique(new Canvas2DImageBu fferSurface(std::move(contextProvider), deviceSize, *msaaSampleCount, opacityMod e, Canvas2DLayerBridge::EnableAcceleration, std::move(colorSpace))); | |
852 if (surface->isValid()) { | |
853 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCa nvasImageBufferCreated); | |
854 return surface; | |
855 } | |
856 | |
857 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCanvas ImageBufferCreationFailed); | |
858 return nullptr; | |
859 } | |
860 | |
861 std::unique_ptr<ImageBufferSurface> HTMLCanvasElement::createSoftwareImageBuffer Surface(const IntSize& deviceSize, OpacityMode opacityMode, sk_sp<SkColorSpace> colorSpace) | |
862 { | |
856 if (shouldUseDisplayList(deviceSize)) { | 863 if (shouldUseDisplayList(deviceSize)) { |
857 std::unique_ptr<ImageBufferSurface> surface = wrapUnique(new RecordingIm ageBufferSurface(deviceSize, std::move(surfaceFactory), opacityMode, colorSpace) ); | 864 auto surface = wrapUnique(new RecordingImageBufferSurface(deviceSize, wr apUnique(new UnacceleratedSurfaceFactory), opacityMode, colorSpace)); |
858 if (surface->isValid()) { | 865 if (surface->isValid()) { |
859 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::DisplayList2DC anvasImageBufferCreated); | 866 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::DisplayList2DC anvasImageBufferCreated); |
860 return surface; | 867 return std::move(surface); |
861 } | 868 } |
862 surfaceFactory = wrapUnique(new UnacceleratedSurfaceFactory()); // recre ate because previous one was released | 869 // We fallback to a non-display-list surface without recording a metric here. |
863 } | 870 } |
864 auto surface = surfaceFactory->createSurface(deviceSize, opacityMode, colorS pace); | 871 |
865 if (!surface->isValid()) { | 872 auto surfaceFactory = wrapUnique(new UnacceleratedSurfaceFactory()); |
866 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCan vasImageBufferCreationFailed); | 873 auto surface = surfaceFactory->createSurface(deviceSize, opacityMode, std::m ove(colorSpace)); |
867 } else { | 874 if (surface->isValid()) { |
868 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCan vasImageBufferCreated); | 875 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCan vasImageBufferCreated); |
876 return surface; | |
869 } | 877 } |
870 return surface; | 878 |
879 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCanvasI mageBufferCreationFailed); | |
880 return nullptr; | |
871 } | 881 } |
872 | 882 |
873 void HTMLCanvasElement::createImageBuffer() | 883 void HTMLCanvasElement::createImageBuffer() |
874 { | 884 { |
875 createImageBufferInternal(nullptr); | 885 createImageBufferInternal(nullptr); |
876 if (m_didFailToCreateImageBuffer && m_context->is2d() && !size().isEmpty()) | 886 if (m_didFailToCreateImageBuffer && m_context->is2d() && !size().isEmpty()) |
877 m_context->loseContext(CanvasRenderingContext::SyntheticLostContext); | 887 m_context->loseContext(CanvasRenderingContext::SyntheticLostContext); |
878 } | 888 } |
879 | 889 |
880 void HTMLCanvasElement::createImageBufferInternal(std::unique_ptr<ImageBufferSur face> externalSurface) | 890 void HTMLCanvasElement::createImageBufferInternal(std::unique_ptr<ImageBufferSur face> externalSurface) |
881 { | 891 { |
882 DCHECK(!m_imageBuffer); | 892 DCHECK(!m_imageBuffer); |
883 | 893 |
884 m_didFailToCreateImageBuffer = true; | 894 m_didFailToCreateImageBuffer = true; |
885 m_imageBufferIsClear = true; | 895 m_imageBufferIsClear = true; |
886 | 896 |
887 if (!ImageBuffer::canCreateImageBuffer(size())) | 897 if (!ImageBuffer::canCreateImageBuffer(size())) |
888 return; | 898 return; |
889 | 899 |
900 OpacityMode opacityMode = !m_context || m_context->creationAttributes().alph a() ? NonOpaque : Opaque; | |
890 int msaaSampleCount = 0; | 901 int msaaSampleCount = 0; |
891 std::unique_ptr<ImageBufferSurface> surface; | 902 std::unique_ptr<ImageBufferSurface> surface = std::move(externalSurface); |
892 if (externalSurface) { | 903 if (!surface) |
893 surface = std::move(externalSurface); | 904 surface = createAcceleratedImageBufferSurface(size(), opacityMode, m_con text->skColorSpace(), &msaaSampleCount); |
894 } else { | 905 if (!surface) |
895 surface = createImageBufferSurface(size(), &msaaSampleCount, m_context-> skColorSpace()); | 906 surface = createSoftwareImageBufferSurface(size(), opacityMode, m_contex t->skColorSpace()); |
896 } | 907 if (!surface) |
908 return; | |
909 DCHECK(surface->isValid()); | |
897 m_imageBuffer = ImageBuffer::create(std::move(surface)); | 910 m_imageBuffer = ImageBuffer::create(std::move(surface)); |
898 if (!m_imageBuffer) | 911 DCHECK(m_imageBuffer); |
899 return; | |
900 m_imageBuffer->setClient(this); | 912 m_imageBuffer->setClient(this); |
901 | 913 |
902 m_didFailToCreateImageBuffer = false; | 914 m_didFailToCreateImageBuffer = false; |
903 | 915 |
904 updateExternallyAllocatedMemory(); | 916 updateExternallyAllocatedMemory(); |
905 | 917 |
906 if (is3D()) { | 918 if (is3D()) { |
907 // Early out for WebGL canvases | 919 // Early out for WebGL canvases |
908 return; | 920 return; |
909 } | 921 } |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1233 | 1245 |
1234 bool HTMLCanvasElement::createSurfaceLayer() | 1246 bool HTMLCanvasElement::createSurfaceLayer() |
1235 { | 1247 { |
1236 DCHECK(!m_surfaceLayerBridge); | 1248 DCHECK(!m_surfaceLayerBridge); |
1237 std::unique_ptr<CanvasSurfaceLayerBridgeClient> bridgeClient = wrapUnique(ne w CanvasSurfaceLayerBridgeClientImpl()); | 1249 std::unique_ptr<CanvasSurfaceLayerBridgeClient> bridgeClient = wrapUnique(ne w CanvasSurfaceLayerBridgeClientImpl()); |
1238 m_surfaceLayerBridge = wrapUnique(new CanvasSurfaceLayerBridge(std::move(bri dgeClient))); | 1250 m_surfaceLayerBridge = wrapUnique(new CanvasSurfaceLayerBridge(std::move(bri dgeClient))); |
1239 return m_surfaceLayerBridge->createSurfaceLayer(this->width(), this->height( )); | 1251 return m_surfaceLayerBridge->createSurfaceLayer(this->width(), this->height( )); |
1240 } | 1252 } |
1241 | 1253 |
1242 } // namespace blink | 1254 } // namespace blink |
OLD | NEW |