Chromium Code Reviews| 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 |