WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-219946-20201217142852.patch (text/plain), 62.47 KB, created by
Kimmo Kinnunen
on 2020-12-17 04:28:54 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Kimmo Kinnunen
Created:
2020-12-17 04:28:54 PST
Size:
62.47 KB
patch
obsolete
>Subversion Revision: 270765 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 8300cb39856524fc01ef87b9d91ad85dcfe7a69e..7b2e3867fb45ee23272da76d2c5fb9a599984ca3 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,186 @@ >+2020-12-17 Kimmo Kinnunen <kkinnunen@apple.com> >+ >+ REGRESSION (r268386): Snapshots of WebGL content in the tab picker don't work (black map on Google Maps) >+ https://bugs.webkit.org/show_bug.cgi?id=219946 >+ <rdar://problem/72013784> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Fix case where WebGL would first be displayed with hardware code path >+ and then displayed with software code path (painting from the paint >+ tree). Former happens when user looks at the page and latter happens >+ when printing or when Safari takes a snapshot. >+ >+ This is not a real regression of r268386. Prior to that, the software >+ display would have used uninitialized IOSurface contents or contents of >+ 1-2 frames prior and would leave the hardware display buffer not >+ updated. >+ >+ CanvasRenderingContext::paintRenderingResultsToCanvas() is used for two >+ purposes: >+ 1) Image extraction uses, such as toData() or >+ constructing an Image out of the contents. >+ 2) Painting the rendering to the document during software display. >+ >+ The 1) case uses always the drawing buffer. >+ >+ The 2) case presents the drawing buffer as the new display buffer if >+ there are changes to the drawing buffer and uses the potentially new >+ display buffer to display. >+ >+ For 2D canvas, these two cases are the same case. For WebGL they are >+ different. >+ >+ The display is destructive for WebGL drawing buffer when >+ preserveDrawingBuffer == false. This means that if hardware display has >+ happened, we must read the display buffer during case 2. This code was >+ missing, so the scenario could not have ever worked. >+ >+ The previous code tried to workaround this by the >+ WebGLGraphicsContextBase to detect what the owner intended with the >+ paintRenderingResultsToCanvas, then skip the potential drawing buffer >+ clear, read the drawing buffer and put that data to the "presentation >+ copy" of the HTMLElement. This is not ok, as the uncleared drawing >+ buffer has non-deterministic contents in case the context has displayed >+ and the client has not drawn new content to the drawing buffer. >+ >+ Fix by removing the "presentation copy" of the HTMLCanvas. The >+ presentation image can always be drawn to the CanvasBase::buffer(): >+ - The current contents of the buffer is the presentation image if the >+ context has not changed since updating the buffer with either drawing >+ buffer or previous display buffer. >+ - If the context has changed, we must present and put the new display >+ buffer to the CanvasBase::buffer() >+ - This is also correct contents for the potential next image extraction >+ uses, up to a point when context changes. >+ - If the context changes before an image extraction use, CanvasBase::buffer() is >+ updated with the normal logic, the same as what happens when CanvasBase::buffer() >+ is updated between two image extraction uses. >+ >+ Prior to this, there was an unneeded and incorrectly implemented >+ GPUCanvasContext::markLayerComposited(). The sequence would be: >+ >+ HTMLCanvasElement::paint(): >+ canvasContext().paintRenderingResultsToCanvas(buffer()); >+ context().drawImageBuffer(buffer()); >+ canvasContext().markLayerComposited(); >+ >+ The markLayerComposited() would incorrectly mark the WebGL context compositing >+ being done, but there was no compositing actually happening. The GPU-side >+ display buffer would be incorrect. Also, there is nothing to be done at >+ this stage, as the compositing of WebGL context itself is already >+ finished at WebGL context paintRenderingResultsToCanvas() return. >+ >+ Instead, add CanvasRenderingContext::prepareForDisplayWithPaint() which signals that next >+ paintRenderingResultsToCanvas() is a display operation. This can be used to to detect the >+ paintRenderingResultsToCanvas() in which we must present the drawing buffer as >+ display buffer. >+ >+ Implement the display buffer read with OpenGL. >+ >+ Refactor the drawing buffer read code to be able to reuse the read code >+ for the display buffer read. The refactored code reduces redundant the >+ allocations of full-screen malloc buffers and ensures allocation results are >+ checked instead of crashing with nullptr derefs when OOM happens. Fixes >+ errors such as rdar://67553531 (CrashTracer: com.apple.WebKit.WebContent at >+ WebCore: WebCore::GraphicsContextGLOpenGL::paintRenderingResultsToCanvas). >+ Removes RGBA->BGRA->RGBA conversions from >+ GraphicsContextGLOpenGL::paintRenderingResultsToImageData(). >+ Removes manual alpha premultiplication and makes CG draw with unpremultiplied >+ alpha. >+ Changes Cairo variant of GraphicsContextGLOpenGL to convert manually RGBA->BGRA >+ instead of (big) OpenGL driver doing it in case of non-NVIDIA platforms. >+ >+ No new tests, the snapshot / sw+hw drawing is not testable at the moment. >+ >+ * Modules/webgpu/GPUCanvasContext.cpp: >+ (WebCore::GPUCanvasContext::configureSwapChain): >+ (WebCore::GPUCanvasContext::prepareForDisplayWithPaint): >+ (WebCore::GPUCanvasContext::paintRenderingResultsToCanvas): >+ * Modules/webgpu/GPUCanvasContext.h: >+ * html/HTMLCanvasElement.cpp: >+ (WebCore::HTMLCanvasElement::paint): >+ * html/HTMLCanvasElement.h: >+ * html/canvas/CanvasRenderingContext.h: >+ (WebCore::CanvasRenderingContext::prepareForDisplayWithPaint): >+ * html/canvas/GPUBasedCanvasRenderingContext.h: >+ * html/canvas/WebGLRenderingContextBase.cpp: >+ (WebCore::WebGLRenderingContextBase::initializeNewContext): >+ (WebCore::WebGLRenderingContextBase::prepareForDisplayWithPaint): >+ (WebCore::WebGLRenderingContextBase::paintRenderingResultsToCanvas): >+ (WebCore::WebGLRenderingContextBase::validateElementArraySize): >+ (WebCore::WebGLRenderingContextBase::validateIndexArrayPrecise): >+ (WebCore::WebGLRenderingContextBase::validateDrawElements): >+ (WebCore::WebGLRenderingContextBase::vertexAttribfvImpl): >+ (WebCore::WebGLRenderingContextBase::initVertexAttrib0): >+ * html/canvas/WebGLRenderingContextBase.h: >+ * platform/graphics/GraphicsContextGL.h: >+ * platform/graphics/RemoteGraphicsContextGLProxyBase.cpp: >+ * platform/graphics/RemoteGraphicsContextGLProxyBase.h: >+ * platform/graphics/angle/GraphicsContextGLANGLE.cpp: >+ (WebCore::GraphicsContextGLOpenGL::readPixelsForPaintResults): >+ (WebCore::GraphicsContextGLOpenGL::readRenderingResults): >+ (WebCore::GraphicsContextGLOpenGL::reshape): >+ (WebCore::GraphicsContextGLOpenGL::getProgramInfoLog): >+ (WebCore::GraphicsContextGLOpenGL::getShaderInfoLog): >+ * platform/graphics/angle/GraphicsContextGLANGLEUtilities.h: >+ (WebCore::ScopedRestoreTextureBinding::ScopedRestoreTextureBinding): >+ (WebCore::ScopedBufferBinding::ScopedBufferBinding): >+ (WebCore::ScopedBufferBinding::~ScopedBufferBinding): >+ (WebCore::ScopedBufferBinding::query): >+ (WebCore::ScopedRestoreReadFramebufferBinding::ScopedRestoreReadFramebufferBinding): >+ (WebCore::ScopedRestoreReadFramebufferBinding::markBindingChanged): >+ (WebCore::ScopedRestoreReadFramebufferBinding::bindFramebuffer): >+ (WebCore::ScopedRestoreReadFramebufferBinding::~ScopedRestoreReadFramebufferBinding): >+ (WebCore::ScopedPixelStorageMode::ScopedPixelStorageMode): >+ (WebCore::ScopedPixelStorageMode::~ScopedPixelStorageMode): >+ (WebCore::ScopedPixelStorageMode::pixelStore): >+ (WebCore::ScopedPixelStorageMode::operator GLint const): >+ (WebCore::ScopedTexture::ScopedTexture): >+ (WebCore::ScopedTexture::~ScopedTexture): >+ (WebCore::ScopedTexture::operator GLuint const): >+ (WebCore::ScopedFramebuffer::ScopedFramebuffer): >+ (WebCore::ScopedFramebuffer::~ScopedFramebuffer): >+ (WebCore::ScopedFramebuffer::operator GLuint const): >+ * platform/graphics/cairo/GraphicsContextGLCairo.cpp: >+ (WebCore::GraphicsContextGLOpenGL::paintToCanvas): >+ * platform/graphics/cg/GraphicsContextGLCG.cpp: >+ (WebCore::releaseImageData): >+ (WebCore::GraphicsContextGLOpenGL::paintToCanvas): >+ * platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.h: >+ * platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm: >+ (WebCore::GraphicsContextGLOpenGL::allowOfflineRenderers const): >+ (WebCore::GraphicsContextGLOpenGL::readCompositedResults): >+ * platform/graphics/cocoa/WebGLLayer.mm: >+ * platform/graphics/opengl/GraphicsContextGLOpenGL.cpp: >+ (WebCore::GraphicsContextGLOpenGL::paintRenderingResultsToCanvas): >+ (WebCore::GraphicsContextGLOpenGL::paintCompositedResultsToCanvas): >+ (WebCore::GraphicsContextGLOpenGL::paintRenderingResultsToImageData): >+ (WebCore::GraphicsContextGLOpenGL::readCompositedResults): >+ * platform/graphics/opengl/GraphicsContextGLOpenGL.h: >+ * platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp: >+ (WebCore::GraphicsContextGLOpenGL::readPixelsForPaintResults): >+ * platform/graphics/opengl/GraphicsContextGLOpenGLCommon.cpp: >+ (WebCore::GraphicsContextGLOpenGL::readRenderingResults): >+ (WebCore::GraphicsContextGLOpenGL::reshape): >+ (WebCore::GraphicsContextGLOpenGL::blendFunc): >+ (WebCore::GraphicsContextGLOpenGL::compileShader): >+ (WebCore::GraphicsContextGLOpenGL::getActiveAttribImpl): >+ (WebCore::GraphicsContextGLOpenGL::getActiveAttrib): >+ (WebCore::GraphicsContextGLOpenGL::getActiveUniformImpl): >+ (WebCore::GraphicsContextGLOpenGL::getActiveUniform): >+ (WebCore::GraphicsContextGLOpenGL::originalSymbolName): >+ (WebCore::GraphicsContextGLOpenGL::mappedSymbolName): >+ (WebCore::GraphicsContextGLOpenGL::deleteVertexArray): >+ (WebCore::GraphicsContextGLOpenGL::isVertexArray): >+ (WebCore::GraphicsContextGLOpenGL::getNonBuiltInActiveSymbolCount): >+ (WebCore::GraphicsContextGLOpenGL::getUnmangledInfoLog): >+ (WebCore::GraphicsContextGLOpenGL::getShaderi): >+ (WebCore::GraphicsContextGLOpenGL::getShaderInfoLog): >+ (WebCore::GraphicsContextGLOpenGL::getShaderSource): >+ * platform/graphics/opengl/GraphicsContextGLOpenGLES.cpp: >+ (WebCore::GraphicsContextGLOpenGL::readPixelsForPaintResults): >+ > 2020-12-14 Lauro Moura <lmoura@igalia.com> > > REGRESSSION(270435) [GStreamer] Many media source tests failing and timing out >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 30328cf6e845f753e642b453b86311817d4c06c9..e0899a92bc20c359ba807b2810b0dd89eb22dc9e 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,20 @@ >+2020-12-17 Kimmo Kinnunen <kkinnunen@apple.com> >+ >+ REGRESSION (r268386): Snapshots of WebGL content in the tab picker don't work (black map on Google Maps) >+ https://bugs.webkit.org/show_bug.cgi?id=219946 >+ <rdar://problem/72013784> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add dummy implementations of GraphicsContextGL::paintCompositedResultsToCanvas. >+ Painting to canvas is not implemented yet for the remote GraphicsContextGL implementation. >+ >+ * GPUProcess/graphics/RemoteGraphicsContextGLCocoa.cpp: >+ (WebKit::RemoteGraphicsContextGLCocoa::displayBuffer const): >+ * WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp: >+ (WebKit::RemoteGraphicsContextGLProxy::paintCompositedResultsToCanvas): >+ * WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.h: >+ > 2020-12-13 Yusuke Suzuki <ysuzuki@apple.com> > > [JSC] Introduce vmEntryCustomAccessor and vmEntryHostFunction for JITCage >diff --git a/Source/WebCore/Modules/webgpu/GPUCanvasContext.cpp b/Source/WebCore/Modules/webgpu/GPUCanvasContext.cpp >index e30350b462a0fed44668bf896029293e1178e887..38b1528ffc3a9525850a94d65ed2794a4d804c35 100644 >--- a/Source/WebCore/Modules/webgpu/GPUCanvasContext.cpp >+++ b/Source/WebCore/Modules/webgpu/GPUCanvasContext.cpp >@@ -90,10 +90,18 @@ void GPUCanvasContext::reshape(int width, int height) > notifyCanvasContentChanged(); > } > >-void GPUCanvasContext::markLayerComposited() >+void GPUCanvasContext::prepareForDisplayWithPaint() > { >- if (m_swapChain && m_swapChain->swapChain()) >+ m_isDisplayingWithPaint = true; >+} >+ >+void GPUCanvasContext::paintRenderingResultsToCanvas() >+{ >+ // FIXME: Unimplemented. >+ if (m_isDisplayingWithPaint && m_swapChain && m_swapChain->swapChain()) { > m_swapChain->swapChain()->present(); >+ m_isDisplayingWithPaint = false; >+ } > } > > } // namespace WebCore >diff --git a/Source/WebCore/Modules/webgpu/GPUCanvasContext.h b/Source/WebCore/Modules/webgpu/GPUCanvasContext.h >index 6df20b4a647f6a1878b38156c2d0710765432a8d..9b0fe7b0d08ce93c7eca8694a00d1632e13d0c98 100644 >--- a/Source/WebCore/Modules/webgpu/GPUCanvasContext.h >+++ b/Source/WebCore/Modules/webgpu/GPUCanvasContext.h >@@ -53,13 +53,15 @@ private: > bool isWebGPU() const final { return true; } > PlatformLayer* platformLayer() const final; > void reshape(int width, int height) final; >- void markLayerComposited() final; >+ void prepareForDisplayWithPaint() final; >+ void paintRenderingResultsToCanvas() final; > > // ActiveDOMObject. > const char* activeDOMObjectName() const final { return "GPUCanvasContext"; } > // FIXME: Stubs. > void stop() final { } > >+ bool m_isDisplayingWithPaint { false }; > RefPtr<WebGPUSwapChain> m_swapChain; > }; > >diff --git a/Source/WebCore/html/HTMLCanvasElement.cpp b/Source/WebCore/html/HTMLCanvasElement.cpp >index 169caa90024d26772305062f598d12ccddbab3ff..54b3401de90f22a89b69627fb401d8555d567e70 100644 >--- a/Source/WebCore/html/HTMLCanvasElement.cpp >+++ b/Source/WebCore/html/HTMLCanvasElement.cpp >@@ -642,20 +642,17 @@ void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r) > > if (m_context) { > shouldPaint = paintsIntoCanvasBuffer() || document().printing() || m_isSnapshotting; >- if (shouldPaint) >+ if (shouldPaint) { >+ m_context->prepareForDisplayWithPaint(); > m_context->paintRenderingResultsToCanvas(); >+ } > } > > if (shouldPaint) { > if (hasCreatedImageBuffer()) { >- if (m_presentedImage) >- context.drawImage(*m_presentedImage, snappedIntRect(r), renderer()->imageOrientation()); >- else if (ImageBuffer* imageBuffer = buffer()) >+ if (ImageBuffer* imageBuffer = buffer()) > context.drawImageBuffer(*imageBuffer, snappedIntRect(r)); > } >- >- if (isGPUBased()) >- downcast<GPUBasedCanvasRenderingContext>(*m_context).markLayerComposited(); > } > } > >@@ -668,19 +665,6 @@ bool HTMLCanvasElement::isGPUBased() const > return m_context && m_context->isGPUBased(); > } > >-void HTMLCanvasElement::makePresentationCopy() >-{ >- if (!m_presentedImage) { >- // The buffer contains the last presented data, so save a copy of it. >- m_presentedImage = buffer()->copyImage(CopyBackingStore, PreserveResolution::Yes); >- } >-} >- >-void HTMLCanvasElement::clearPresentationCopy() >-{ >- m_presentedImage = nullptr; >-} >- > void HTMLCanvasElement::setSurfaceSize(const IntSize& size) > { > CanvasBase::setSize(size); >diff --git a/Source/WebCore/html/HTMLCanvasElement.h b/Source/WebCore/html/HTMLCanvasElement.h >index aeb0189749b58333748404c95bafed04528f9cef..9c9230f5fbb7e6de4b69fd5c86beee4064b442b8 100644 >--- a/Source/WebCore/html/HTMLCanvasElement.h >+++ b/Source/WebCore/html/HTMLCanvasElement.h >@@ -115,8 +115,6 @@ public: > Image* copiedImage() const final; > void clearCopiedImage() const final; > RefPtr<ImageData> getImageData(); >- void makePresentationCopy(); >- void clearPresentationCopy(); > > SecurityOrigin* securityOrigin() const final; > >@@ -199,7 +197,6 @@ private: > > bool m_isSnapshotting { false }; > >- mutable RefPtr<Image> m_presentedImage; > mutable RefPtr<Image> m_copiedImage; // FIXME: This is temporary for platforms that have to copy the image buffer to render (and for CSSCanvasValue). > }; > >@@ -216,4 +213,3 @@ private: > static bool checkTagName(const WebCore::EventTarget& target) { return is<WebCore::Node>(target) && checkTagName(downcast<WebCore::Node>(target)); } > }; > } >- >diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext.h b/Source/WebCore/html/canvas/CanvasRenderingContext.h >index acf83bb72dca701c0fcc6738c1d86ca1178fd494..f38863f78fee3ff89929c74c47ca2e5341990055 100644 >--- a/Source/WebCore/html/canvas/CanvasRenderingContext.h >+++ b/Source/WebCore/html/canvas/CanvasRenderingContext.h >@@ -71,6 +71,9 @@ public: > virtual bool isOffscreen2d() const { return false; } > virtual bool isPaint() const { return false; } > >+ // Called before paintRenderingResultsToCanvas if paintRenderingResultsToCanvas is >+ // used for compositing purposes. >+ virtual void prepareForDisplayWithPaint() { } > virtual void paintRenderingResultsToCanvas() {} > virtual PlatformLayer* platformLayer() const { return 0; } > >diff --git a/Source/WebCore/html/canvas/GPUBasedCanvasRenderingContext.h b/Source/WebCore/html/canvas/GPUBasedCanvasRenderingContext.h >index 47a02eb706ce45d88f19754bb7d8beff9b1f942c..890cd723501e04e28e82f77a0b69dbed59a48595 100644 >--- a/Source/WebCore/html/canvas/GPUBasedCanvasRenderingContext.h >+++ b/Source/WebCore/html/canvas/GPUBasedCanvasRenderingContext.h >@@ -50,8 +50,6 @@ public: > } > > virtual void reshape(int width, int height) = 0; >- virtual void markLayerComposited() = 0; >- > protected: > explicit GPUBasedCanvasRenderingContext(CanvasBase&); > >diff --git a/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp b/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp >index 013b89af4888b87c0f648e52cb561cdb91c54973..30d9e7e91a43c39e812f7bb52b51068bc9367559 100644 >--- a/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp >+++ b/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp >@@ -1199,11 +1199,10 @@ void WebGLRenderingContextBase::restoreStateAfterClear() > m_context->depthMask(m_depthMask); > } > >-void WebGLRenderingContextBase::markLayerComposited() >+ >+void WebGLRenderingContextBase::prepareForDisplayWithPaint() > { >- if (isContextLostOrPending()) >- return; >- m_context->markLayerComposited(); >+ m_isDisplayingWithPaint = true; > } > > void WebGLRenderingContextBase::paintRenderingResultsToCanvas() >@@ -1211,18 +1210,17 @@ void WebGLRenderingContextBase::paintRenderingResultsToCanvas() > if (isContextLostOrPending()) > return; > >- if (auto* canvas = htmlCanvas()) { >- if (canvas->document().printing() || (canvas->isSnapshotting() && canvas->document().page()->isVisible())) >- canvas->clearPresentationCopy(); >- >- // Until the canvas is written to by the application, the clear that >- // happened after it was composited should be ignored by the compositor. >- if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) { >- m_context->paintRenderingResultsToCanvas(canvas->buffer()); >- >- canvas->makePresentationCopy(); >- } else >- canvas->clearPresentationCopy(); >+ if (m_isDisplayingWithPaint) { >+ bool canvasContainsDisplayBuffer = !m_markedCanvasDirty; >+ prepareForDisplay(); >+ m_isDisplayingWithPaint = false; >+ if (!canvasContainsDisplayBuffer) { >+ auto& base = canvasBase(); >+ base.clearCopiedImage(); >+ m_markedCanvasDirty = false; >+ m_context->paintCompositedResultsToCanvas(base.buffer()); >+ } >+ return; > } > > clearIfComposited(ClearCallerOther); >diff --git a/Source/WebCore/html/canvas/WebGLRenderingContextBase.h b/Source/WebCore/html/canvas/WebGLRenderingContextBase.h >index 30a8557d8688e2ea495db716f08be609ec3b4e8a..e8e90cfba16b14dd148c98e069e500ecde2b550f 100644 >--- a/Source/WebCore/html/canvas/WebGLRenderingContextBase.h >+++ b/Source/WebCore/html/canvas/WebGLRenderingContextBase.h >@@ -384,8 +384,8 @@ public: > > void reshape(int width, int height) override; > >- void markLayerComposited() final; >- void paintRenderingResultsToCanvas() override; >+ void prepareForDisplayWithPaint() final; >+ void paintRenderingResultsToCanvas() final; > RefPtr<ImageData> paintRenderingResultsToImageData(); > > void removeSharedObject(WebGLSharedObject&); >@@ -668,6 +668,7 @@ protected: > bool isContextLostOrPending(); > > bool m_compositingResultsNeedUpdating { false }; >+ bool m_isDisplayingWithPaint { false }; > > // Enabled extension objects. > // FIXME: Move some of these to WebGLRenderingContext, the ones not needed for WebGL2 >diff --git a/Source/WebCore/platform/graphics/GraphicsContextGL.h b/Source/WebCore/platform/graphics/GraphicsContextGL.h >index 223a5c9bf1697f25f112dbcc186f819b7ce1de45..aa8ff2368dffd89ceab6a443330db4516a18f9f5 100644 >--- a/Source/WebCore/platform/graphics/GraphicsContextGL.h >+++ b/Source/WebCore/platform/graphics/GraphicsContextGL.h >@@ -1292,7 +1292,7 @@ public: > // the context. > virtual void paintRenderingResultsToCanvas(ImageBuffer*) = 0; > virtual RefPtr<ImageData> paintRenderingResultsToImageData() = 0; >- virtual bool paintCompositedResultsToCanvas(ImageBuffer*) = 0; >+ virtual void paintCompositedResultsToCanvas(ImageBuffer*) = 0; > > // FIXME: this should be removed. The layer should be marked composited by > // preparing for display, so that canvas image buffer and the layer agree >diff --git a/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.cpp b/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.cpp >index 60f7a947efcbb37156c098e0b5ee33c3b62b849b..36faaa7e46622baf3a123fbe95ee94be6409d54c 100644 >--- a/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.cpp >+++ b/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.cpp >@@ -99,11 +99,6 @@ GCGLbitfield RemoteGraphicsContextGLProxyBase::getBuffersToAutoClear() const > return m_buffersToAutoClear; > } > >-bool RemoteGraphicsContextGLProxyBase::paintCompositedResultsToCanvas(ImageBuffer*) >-{ >- return false; >-} >- > void RemoteGraphicsContextGLProxyBase::enablePreserveDrawingBuffer() > { > // Redeclared for export reasons. >diff --git a/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.h b/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.h >index 726aaf6c6a0f62ff282e5b8d202a1294e1de8571..2471d4e25c9aa200ec743b1fe0c6468b0c9a5083 100644 >--- a/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.h >+++ b/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.h >@@ -67,7 +67,6 @@ public: > bool layerComposited() const final; > void setBuffersToAutoClear(GCGLbitfield) final; > GCGLbitfield getBuffersToAutoClear() const final; >- bool paintCompositedResultsToCanvas(ImageBuffer*) final; > void markLayerComposited() final; > void enablePreserveDrawingBuffer() final; > >diff --git a/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp b/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp >index 309a5309b640a3d6a28141ca7b1a75db46e9f951..b5043b74636f7885c5d80c0773555d71200023d5 100644 >--- a/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp >+++ b/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp >@@ -31,6 +31,7 @@ > > #include "ANGLEHeaders.h" > #include "ExtensionsGLANGLE.h" >+#include "GraphicsContextGLANGLEUtilities.h" > #include "ImageBuffer.h" > #include "ImageData.h" > #include "IntRect.h" >@@ -46,9 +47,6 @@ > #include <wtf/text/CString.h> > #include <wtf/text/StringBuilder.h> > >-#if USE(ACCELERATE) >-#include <Accelerate/Accelerate.h> >-#endif > > #if ENABLE(VIDEO) && USE(AVFOUNDATION) > #include "GraphicsContextGLCVANGLE.h" >@@ -64,30 +62,6 @@ static const char* packedDepthStencilExtensionName = "GL_OES_packed_depth_stenci > > namespace { > >-class ScopedResetBufferBinding { >- WTF_MAKE_NONCOPYABLE(ScopedResetBufferBinding); >-public: >- ScopedResetBufferBinding(bool shouldDoWork, GLenum bindingPointQuery, GLenum bindingPoint) >- : m_bindingPointQuery(bindingPointQuery) >- , m_bindingPoint(bindingPoint) >- { >- if (shouldDoWork) >- gl::GetIntegerv(m_bindingPointQuery, &m_bindingValue); >- if (m_bindingValue) >- gl::BindBuffer(m_bindingPoint, 0); >- } >- >- ~ScopedResetBufferBinding() >- { >- if (m_bindingValue) >- gl::BindBuffer(m_bindingPoint, m_bindingValue); >- } >- >-private: >- GLint m_bindingPointQuery { 0 }; >- GLint m_bindingPoint { 0 }; >- GLint m_bindingValue { 0 }; >-}; > > } // namespace anonymous > >@@ -102,36 +76,29 @@ static void wipeAlphaChannelFromPixels(int width, int height, unsigned char* pix > } > #endif > >-void GraphicsContextGLOpenGL::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels) >-{ >- // NVIDIA drivers have a bug where calling readPixels in BGRA can return the wrong values for the alpha channel when the alpha is off for the context. >- gl::ReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); >-#if USE(ACCELERATE) >- vImage_Buffer src; >- src.height = height; >- src.width = width; >- src.rowBytes = width * 4; >- src.data = pixels; >- >- vImage_Buffer dest; >- dest.height = height; >- dest.width = width; >- dest.rowBytes = width * 4; >- dest.data = pixels; >- >- // Swap pixel channels from RGBA to BGRA. >- const uint8_t map[4] = { 2, 1, 0, 3 }; >- vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags); >-#else >- int totalBytes = width * height * 4; >- for (int i = 0; i < totalBytes; i += 4) >- std::swap(pixels[i], pixels[i + 2]); >-#endif >- >+RefPtr<ImageData> GraphicsContextGLOpenGL::readPixelsForPaintResults() >+{ >+ auto imageData = ImageData::create(getInternalFramebufferSize()); >+ if (!imageData) >+ return nullptr; >+ ScopedPixelStorageMode packAlignment(GL_PACK_ALIGNMENT); >+ if (packAlignment > 4) >+ packAlignment.pixelStore(4); >+ ScopedPixelStorageMode packRowLength(GL_PACK_ROW_LENGTH, 0, m_isForWebGL2); >+ ScopedPixelStorageMode packSkipRows(GL_PACK_SKIP_ROWS, 0, m_isForWebGL2); >+ ScopedPixelStorageMode packSkipPixels(GL_PACK_SKIP_PIXELS, 0, m_isForWebGL2); >+ ScopedBufferBinding scopedPixelPackBufferReset(GL_PIXEL_PACK_BUFFER, 0, m_isForWebGL2); >+ >+ gl::ReadnPixelsRobustANGLE(0, 0, imageData->width(), imageData->height(), GL_RGBA, GL_UNSIGNED_BYTE, imageData->data()->byteLength(), nullptr, nullptr, nullptr, imageData->data()->data()); >+ // FIXME: Rendering to GL_RGB textures with a IOSurface bound to the texture image leaves >+ // the alpha in the IOSurface in incorrect state. Also ANGLE gl::ReadPixels will in some >+ // cases expose the non-255 values. >+ // https://bugs.webkit.org/show_bug.cgi?id=215804 > #if PLATFORM(MAC) || PLATFORM(IOS_FAMILY) > if (!contextAttributes().alpha) >- wipeAlphaChannelFromPixels(width, height, pixels); >+ wipeAlphaChannelFromPixels(imageData->width(), imageData->height(), imageData->data()->data()); > #endif >+ return imageData; > } > > void GraphicsContextGLOpenGL::validateAttributes() >@@ -510,64 +477,6 @@ void GraphicsContextGLOpenGL::validateDepthStencil(const char* packedDepthStenci > } > } > >-void GraphicsContextGLOpenGL::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer) >-{ >- Checked<int, RecordOverflow> rowBytes = Checked<int, RecordOverflow>(m_currentWidth) * 4; >- if (rowBytes.hasOverflowed()) >- return; >- >- Checked<int, RecordOverflow> totalBytesChecked = rowBytes * m_currentHeight; >- if (totalBytesChecked.hasOverflowed()) >- return; >- int totalBytes = totalBytesChecked.unsafeGet(); >- >- auto pixels = makeUniqueArray<unsigned char>(totalBytes); >- if (!pixels) >- return; >- >- readRenderingResults(pixels.get(), totalBytes); >- >- if (!contextAttributes().premultipliedAlpha) { >- for (int i = 0; i < totalBytes; i += 4) { >- // Premultiply alpha. >- pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255); >- pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255); >- pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255); >- } >- } >- >- paintToCanvas(pixels.get(), IntSize(m_currentWidth, m_currentHeight), imageBuffer->backendSize(), imageBuffer->context()); >-} >- >-bool GraphicsContextGLOpenGL::paintCompositedResultsToCanvas(ImageBuffer*) >-{ >- // Not needed at the moment, so return that nothing was done. >- return false; >-} >- >-RefPtr<ImageData> GraphicsContextGLOpenGL::paintRenderingResultsToImageData() >-{ >- // Reading premultiplied alpha would involve unpremultiplying, which is >- // lossy. >- if (contextAttributes().premultipliedAlpha) >- return nullptr; >- >- auto imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight)); >- unsigned char* pixels = imageData->data()->data(); >- Checked<int, RecordOverflow> totalBytesChecked = 4 * Checked<int, RecordOverflow>(m_currentWidth) * Checked<int, RecordOverflow>(m_currentHeight); >- if (totalBytesChecked.hasOverflowed()) >- return imageData; >- int totalBytes = totalBytesChecked.unsafeGet(); >- >- readRenderingResults(pixels, totalBytes); >- >- // Convert to RGBA. >- for (int i = 0; i < totalBytes; i += 4) >- std::swap(pixels[i], pixels[i + 2]); >- >- return imageData; >-} >- > void GraphicsContextGLOpenGL::prepareTexture() > { > if (m_layerComposited) >@@ -620,65 +529,15 @@ void GraphicsContextGLOpenGL::prepareTextureImpl() > #endif > } > >-void GraphicsContextGLOpenGL::readRenderingResults(unsigned char *pixels, int pixelsSize) >+RefPtr<ImageData> GraphicsContextGLOpenGL::readRenderingResults() > { >- if (pixelsSize < m_currentWidth * m_currentHeight * 4) >- return; >- >- if (!makeContextCurrent()) >- return; >- >- >- GCGLenum framebufferTarget = m_isForWebGL2 ? GraphicsContextGL::READ_FRAMEBUFFER : GraphicsContextGL::FRAMEBUFFER; >- >- bool mustRestoreFBO = false; >+ ScopedRestoreReadFramebufferBinding fboBinding(m_isForWebGL2, m_state.boundReadFBO); > if (contextAttributes().antialias) { > resolveMultisamplingIfNecessary(); >- gl::BindFramebuffer(framebufferTarget, m_fbo); >- mustRestoreFBO = true; >- } else { >- if (m_state.boundReadFBO != m_fbo) { >- mustRestoreFBO = true; >- gl::BindFramebuffer(framebufferTarget, m_fbo); >- } >+ fboBinding.markBindingChanged(); > } >- >- GLint packAlignment = 4; >- bool mustRestorePackAlignment = false; >- gl::GetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); >- if (packAlignment > 4) { >- gl::PixelStorei(GL_PACK_ALIGNMENT, 4); >- mustRestorePackAlignment = true; >- } >- GLint packRowLength = 0; >- GLint packSkipRows = 0; >- GLint packSkipPixels = 0; >- ScopedResetBufferBinding scopedPixelPackBufferReset(m_isForWebGL2, GL_PIXEL_PACK_BUFFER_BINDING, GL_PIXEL_PACK_BUFFER); >- if (m_isForWebGL2) { >- gl::GetIntegerv(GL_PACK_ROW_LENGTH, &packRowLength); >- if (packRowLength > 0) >- gl::PixelStorei(GL_PACK_ROW_LENGTH, 0); >- gl::GetIntegerv(GL_PACK_SKIP_ROWS, &packSkipRows); >- if (packSkipRows > 0) >- gl::PixelStorei(GL_PACK_SKIP_ROWS, 0); >- gl::GetIntegerv(GL_PACK_SKIP_PIXELS, &packSkipPixels); >- if (packSkipPixels > 0) >- gl::PixelStorei(GL_PACK_SKIP_PIXELS, 0); >- } >- >- readPixelsAndConvertToBGRAIfNecessary(0, 0, m_currentWidth, m_currentHeight, pixels); >- >- if (mustRestorePackAlignment) >- gl::PixelStorei(GL_PACK_ALIGNMENT, packAlignment); >- if (packRowLength > 0) >- gl::PixelStorei(GL_PACK_ROW_LENGTH, packRowLength); >- if (packSkipRows > 0) >- gl::PixelStorei(GL_PACK_SKIP_ROWS, packSkipRows); >- if (packSkipPixels > 0) >- gl::PixelStorei(GL_PACK_SKIP_PIXELS, packSkipPixels); >- >- if (mustRestoreFBO) >- gl::BindFramebuffer(framebufferTarget, m_state.boundReadFBO); >+ fboBinding.bindFramebuffer(m_fbo); >+ return readPixelsForPaintResults(); > } > > void GraphicsContextGLOpenGL::reshape(int width, int height) >@@ -704,7 +563,7 @@ void GraphicsContextGLOpenGL::reshape(int width, int height) > > TemporaryANGLESetting scopedScissor(GL_SCISSOR_TEST, GL_FALSE); > TemporaryANGLESetting scopedDither(GL_DITHER, GL_FALSE); >- ScopedResetBufferBinding scopedPixelUnpackBufferReset(m_isForWebGL2, GL_PIXEL_UNPACK_BUFFER_BINDING, GL_PIXEL_UNPACK_BUFFER); >+ ScopedBufferBinding scopedPixelUnpackBufferReset(GL_PIXEL_UNPACK_BUFFER, 0, m_isForWebGL2); > > bool mustRestoreFBO = reshapeFBOs(IntSize(width, height)); > auto attrs = contextAttributes(); >diff --git a/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLEUtilities.h b/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLEUtilities.h >index 21327ddafc3db5fed2e81326b1fa22c52869f151..4942a955456bf9448401c2e26b57fdb821cd4c51 100644 >--- a/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLEUtilities.h >+++ b/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLEUtilities.h >@@ -36,9 +36,9 @@ namespace WebCore { > class ScopedRestoreTextureBinding { > WTF_MAKE_NONCOPYABLE(ScopedRestoreTextureBinding); > public: >- ScopedRestoreTextureBinding(GCGLenum bindingPointQuery, GCGLenum bindingPoint, bool condition = true) >+ ScopedRestoreTextureBinding(GLenum bindingPointQuery, GLenum bindingPoint, bool condition = true) > { >- ASSERT(bindingPoint != static_cast<GCGLenum>(0u)); >+ ASSERT(bindingPoint != static_cast<GLenum>(0u)); > if (condition) { > m_bindingPoint = bindingPoint; > gl::GetIntegerv(bindingPointQuery, reinterpret_cast<GLint*>(&m_bindingValue)); >@@ -56,6 +56,153 @@ private: > GLuint m_bindingValue { 0u }; > }; > >+ >+class ScopedBufferBinding { >+ WTF_MAKE_NONCOPYABLE(ScopedBufferBinding); >+public: >+ ScopedBufferBinding(GLenum bindingPoint, GLuint bindingValue, bool condition = true) >+ { >+ if (!condition) >+ return; >+ gl::GetIntegerv(query(bindingPoint), reinterpret_cast<GLint*>(&m_bindingValue)); >+ if (bindingValue == m_bindingValue) >+ return; >+ m_bindingPoint = bindingPoint; >+ gl::BindBuffer(m_bindingPoint, bindingValue); >+ } >+ >+ ~ScopedBufferBinding() >+ { >+ if (m_bindingPoint) >+ gl::BindBuffer(m_bindingPoint, m_bindingValue); >+ } >+ >+private: >+ static constexpr GLenum query(GLenum bindingPoint) >+ { >+ if (bindingPoint == GL_PIXEL_PACK_BUFFER) >+ return GL_PIXEL_PACK_BUFFER_BINDING; >+ ASSERT(bindingPoint == GL_PIXEL_UNPACK_BUFFER); >+ return GL_PIXEL_UNPACK_BUFFER_BINDING; >+ } >+ GLint m_bindingPoint { 0 }; >+ GLuint m_bindingValue { 0u }; >+}; >+class ScopedRestoreReadFramebufferBinding { >+ WTF_MAKE_NONCOPYABLE(ScopedRestoreReadFramebufferBinding); >+public: >+ ScopedRestoreReadFramebufferBinding(bool isForWebGL2, GLuint restoreValue) >+ : m_framebufferTarget(isForWebGL2 ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER) >+ , m_bindingValue(restoreValue) >+ { >+ } >+ ScopedRestoreReadFramebufferBinding(bool isForWebGL2, GLuint restoreValue, GLuint value) >+ : m_framebufferTarget(isForWebGL2 ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER) >+ , m_bindingValue(restoreValue) >+ { >+ bindFramebuffer(value); >+ } >+ void markBindingChanged() >+ { >+ m_bindingChanged = true; >+ } >+ void bindFramebuffer(GLuint bindingValue) >+ { >+ if (!m_bindingChanged && m_bindingValue == bindingValue) >+ return; >+ gl::BindFramebuffer(m_framebufferTarget, bindingValue); >+ m_bindingChanged = m_bindingValue != bindingValue; >+ } >+ ~ScopedRestoreReadFramebufferBinding() >+ { >+ if (m_bindingChanged) >+ gl::BindFramebuffer(m_framebufferTarget, m_bindingValue); >+ } >+private: >+ const GLenum m_framebufferTarget; >+ GLuint m_bindingValue { 0u }; >+ bool m_bindingChanged { false }; >+}; >+ >+class ScopedPixelStorageMode { >+ WTF_MAKE_NONCOPYABLE(ScopedPixelStorageMode); >+public: >+ explicit ScopedPixelStorageMode(GLenum name, bool condition = true) >+ : m_name(condition ? name : 0) >+ { >+ if (m_name) >+ gl::GetIntegerv(m_name, &m_originalValue); >+ } >+ ScopedPixelStorageMode(GLenum name, GLint value, bool condition = true) >+ : m_name(condition ? name : 0) >+ { >+ if (m_name) { >+ gl::GetIntegerv(m_name, &m_originalValue); >+ pixelStore(value); >+ } >+ } >+ ~ScopedPixelStorageMode() >+ { >+ if (m_name && m_valueChanged) >+ gl::PixelStorei(m_name, m_originalValue); >+ } >+ void pixelStore(GLint value) >+ { >+ ASSERT(m_name); >+ if (!m_valueChanged && m_originalValue == value) >+ return; >+ gl::PixelStorei(m_name, value); >+ m_valueChanged = m_originalValue != value; >+ } >+ operator GLint() const >+ { >+ ASSERT(m_name && !m_valueChanged); >+ return m_originalValue; >+ } >+private: >+ const GLenum m_name; >+ bool m_valueChanged { false }; >+ GLint m_originalValue { 0 }; >+}; >+ >+class ScopedTexture { >+ WTF_MAKE_NONCOPYABLE(ScopedTexture); >+public: >+ ScopedTexture() >+ { >+ gl::GenTextures(1, &m_object); >+ } >+ ~ScopedTexture() >+ { >+ gl::DeleteTextures(1, &m_object); >+ } >+ operator GLuint() const >+ { >+ return m_object; >+ } >+private: >+ GLuint m_object { 0u }; >+}; >+ >+class ScopedFramebuffer { >+ WTF_MAKE_NONCOPYABLE(ScopedFramebuffer); >+public: >+ ScopedFramebuffer() >+ { >+ gl::GenFramebuffers(1, &m_object); >+ } >+ ~ScopedFramebuffer() >+ { >+ gl::DeleteFramebuffers(1, &m_object); >+ } >+ operator GLuint() const >+ { >+ return m_object; >+ } >+private: >+ GLuint m_object { 0 }; >+}; >+ > } > > #endif >diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextGLCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContextGLCairo.cpp >index 43cdac8b01cda0df062186f15003ea308fa20cd6..56f6b1a701b200c9868d282f07c376da110ce25e 100644 >--- a/Source/WebCore/platform/graphics/cairo/GraphicsContextGLCairo.cpp >+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextGLCairo.cpp >@@ -33,6 +33,7 @@ > #include "CairoUtilities.h" > #include "GraphicsContextGLImageExtractor.h" > #include "Image.h" >+#include "ImageData.h" > #include "ImageSource.h" > #include "PlatformContextCairo.h" > #include "RefPtrCairo.h" >@@ -105,15 +106,30 @@ bool GraphicsContextGLImageExtractor::extractImage(bool premultiplyAlpha, bool i > return true; > } > >-void GraphicsContextGLOpenGL::paintToCanvas(const unsigned char* imagePixels, const IntSize& imageSize, const IntSize& canvasSize, GraphicsContext& context) >+void GraphicsContextGLOpenGL::paintToCanvas(Ref<ImageData>&& imageData, const IntSize& canvasSize, GraphicsContext& context) > { >- if (!imagePixels || imageSize.isEmpty() || canvasSize.isEmpty()) >+ ASSERT(!imageData->size().isEmpty()); >+ if (canvasSize.isEmpty()) > return; > > PlatformContextCairo* platformContext = context.platformContext(); > if (!platformContext) > return; > >+ // Convert RGBA to BGRA. BGRA is CAIRO_FORMAT_ARGB32 on little-endian architectures. >+ size_t totalBytes = imageData->data()->byteLength(); >+ uint8_t* pixels = imageData->data()->data(); >+ for (size_t i = 0; i < totalBytes; i += 4) >+ std::swap(pixels[i], pixels[i + 2]); >+ >+ if (!contextAttributes().premultipliedAlpha) { >+ for (size_t i = 0; i < totalBytes; i += 4) { >+ pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255); >+ pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255); >+ pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255); >+ } >+ } >+ > cairo_t* cr = platformContext->cr(); > platformContext->save(); > >@@ -122,10 +138,10 @@ void GraphicsContextGLOpenGL::paintToCanvas(const unsigned char* imagePixels, co > cairo_paint(cr); > > RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data( >- const_cast<unsigned char*>(imagePixels), CAIRO_FORMAT_ARGB32, imageSize.width(), imageSize.height(), imageSize.width() * 4)); >+ imageData->data()->data(), CAIRO_FORMAT_ARGB32, imageData->width(), imageData->height(), imageData->width() * 4)); > > // OpenGL keeps the pixels stored bottom up, so we need to flip the image here. >- cairo_translate(cr, 0, imageSize.height()); >+ cairo_translate(cr, 0, imageData->height()); > cairo_scale(cr, 1, -1); > > cairo_set_operator(cr, CAIRO_OPERATOR_OVER); >diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextGLCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextGLCG.cpp >index 68d5ac83d912e86efebff4239dfa06466300f1b4..e2e51fd0a060dad21b2d21a5285d40d473bc526a 100644 >--- a/Source/WebCore/platform/graphics/cg/GraphicsContextGLCG.cpp >+++ b/Source/WebCore/platform/graphics/cg/GraphicsContextGLCG.cpp >@@ -505,36 +505,35 @@ bool GraphicsContextGLImageExtractor::extractImage(bool premultiplyAlpha, bool i > return true; > } > >-static void releaseImageData(void*, const void* data, size_t) >+static void releaseImageData(void* imageData, const void*, size_t) > { >- fastFree(const_cast<void*>(data)); >+ reinterpret_cast<ImageData*>(imageData)->deref(); > } > >-void GraphicsContextGLOpenGL::paintToCanvas(const unsigned char* imagePixels, const IntSize& imageSize, const IntSize& canvasSize, GraphicsContext& context) >+void GraphicsContextGLOpenGL::paintToCanvas(Ref<ImageData>&& imageData, const IntSize& canvasSize, GraphicsContext& context) > { >- if (!imagePixels || imageSize.isEmpty() || canvasSize.isEmpty()) >+ ASSERT(!imageData->size().isEmpty()); >+ if (canvasSize.isEmpty()) > return; >+ auto attrs = contextAttributes(); >+ // Input is GL_RGBA == kCGBitmapByteOrder32Big | kCGImageAlpha*Last. >+ // GL_BGRA would be kCGBitmapByteOrder32Little | kCGImageAlpha*First. >+ CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big; >+ if (!attrs.alpha) >+ bitmapInfo |= kCGImageAlphaNoneSkipLast; >+ else if (attrs.premultipliedAlpha) >+ bitmapInfo |= kCGImageAlphaPremultipliedLast; >+ else >+ bitmapInfo |= kCGImageAlphaLast; >+ >+ auto imageSize = imageData->size(); > int rowBytes = imageSize.width() * 4; >- RetainPtr<CGDataProviderRef> dataProvider; >- >- if (context.isAcceleratedContext()) { >- unsigned char* copiedPixels; >- >- if (!tryFastCalloc(imageSize.height(), rowBytes).getValue(copiedPixels)) >- return; >- >- memcpy(copiedPixels, imagePixels, rowBytes * imageSize.height()); >- >- size_t dataSize = rowBytes * imageSize.height(); >- verifyImageBufferIsBigEnough(copiedPixels, dataSize); >- dataProvider = adoptCF(CGDataProviderCreateWithData(0, copiedPixels, dataSize, releaseImageData)); >- } else { > size_t dataSize = rowBytes * imageSize.height(); >+ uint8_t* imagePixels = imageData->data()->data(); > verifyImageBufferIsBigEnough(imagePixels, dataSize); >- dataProvider = adoptCF(CGDataProviderCreateWithData(0, imagePixels, dataSize, 0)); >- } >+ RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateWithData(&imageData.leakRef(), imagePixels, dataSize, releaseImageData)); > >- auto image = NativeImage::create(adoptCF(CGImageCreate(imageSize.width(), imageSize.height(), 8, 32, rowBytes, sRGBColorSpaceRef(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, >+ auto image = NativeImage::create(adoptCF(CGImageCreate(imageSize.width(), imageSize.height(), 8, 32, rowBytes, sRGBColorSpaceRef(), bitmapInfo, > dataProvider.get(), 0, false, kCGRenderingIntentDefault))); > > // CSS styling may cause the canvas's content to be resized on >diff --git a/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.h b/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.h >index d5e4168e31beb8f2bb774cf7de1e95f8d0b99619..4ded8e5f94982671746c9e7f533aac6b18ac6b0a 100644 >--- a/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.h >+++ b/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.h >@@ -63,6 +63,10 @@ public: > // Prepares the target for display with a contents buffer. > virtual void present(Buffer) = 0; > >+ // Returns the most recent presented display buffer. The reference is valid until >+ // next present, recycleBuffer or detachClient call. >+ virtual const Buffer& displayBuffer() const = 0; >+ > // Detaches the client and returns the current contents buffer metadata handle. > // The if multiple buffers have been submitted, recycleBuffer must have been called before calling > // this. >diff --git a/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm b/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm >index 891e9783e25fd4784e36863b3e6e682c295cb424..dbe9c05d328b65c275ec9512046024f3da40c84a 100644 >--- a/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm >+++ b/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm >@@ -730,6 +730,37 @@ void GraphicsContextGLOpenGL::prepareForDisplay() > markLayerComposited(); > } > >+RefPtr<ImageData> GraphicsContextGLOpenGL::readCompositedResults() >+{ >+ auto& displayBuffer = m_swapChain->displayBuffer(); >+ if (!displayBuffer.surface || !displayBuffer.handle) >+ return nullptr; >+ if (displayBuffer.surface->size() != getInternalFramebufferSize()) >+ return nullptr; >+ // Note: We are using GL to read the IOSurface. At the time of writing, there are no convinient >+ // functions to convert the IOSurface pixel data to ImageData. The image data ends up being >+ // drawn to a ImageBuffer, but at the time there's no functions to construct a NativeImage >+ // out of an IOSurface in such a way that drawing the NativeImage would be guaranteed leave >+ // the IOSurface be unrefenced after the draw call finishes. >+ ScopedTexture texture; >+ GCGLenum textureTarget = drawingBufferTextureTarget(); >+ ScopedRestoreTextureBinding restoreBinding(drawingBufferTextureTargetQuery(), textureTarget, textureTarget != TEXTURE_RECTANGLE_ARB); >+ gl::BindTexture(textureTarget, texture); >+ if (!EGL_BindTexImage(m_displayObj, displayBuffer.handle, EGL_BACK_BUFFER)) >+ return nullptr; >+ gl::TexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); >+ ScopedFramebuffer fbo; >+ ScopedRestoreReadFramebufferBinding fboBinding(m_isForWebGL2, m_state.boundReadFBO, fbo); >+ gl::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureTarget, texture, 0); >+ ASSERT(gl::CheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); >+ >+ auto result = readPixelsForPaintResults(); >+ >+ EGLBoolean releaseOk = EGL_ReleaseTexImage(m_displayObj, displayBuffer.handle, EGL_BACK_BUFFER); >+ ASSERT_UNUSED(releaseOk, releaseOk); >+ return result; >+} >+ > } > > #endif // ENABLE(WEBGL) >diff --git a/Source/WebCore/platform/graphics/cocoa/WebGLLayer.mm b/Source/WebCore/platform/graphics/cocoa/WebGLLayer.mm >index 38597e4a8f633a5ee5db74933022dc237fe7e47c..03138ef1430988d715a98b7777d3a5388a3299aa 100644 >--- a/Source/WebCore/platform/graphics/cocoa/WebGLLayer.mm >+++ b/Source/WebCore/platform/graphics/cocoa/WebGLLayer.mm >@@ -39,6 +39,10 @@ public: > explicit WebGLLayerSwapChain(WebGLLayer* layer) : m_layer(layer) { }; > ~WebGLLayerSwapChain() override = default; > void present(Buffer) override; >+ const Buffer& displayBuffer() const override >+ { >+ return m_displayBuffer; >+ } > Buffer recycleBuffer() override > { > if (m_spareBuffer.surface) { >diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp >index 069d286ce4eba4829e0c7383e2f3e8bee72fe292..2feb74c2fad1b2a62ff60c6125d1b8fccf5db56a 100644 >--- a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp >+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp >@@ -31,6 +31,8 @@ > #if ENABLE(WEBGL) > > #include "ExtensionsGL.h" >+#include "ImageBuffer.h" >+#include "ImageData.h" > #include <wtf/UniqueArray.h> > > namespace WebCore { >@@ -194,6 +196,50 @@ void GraphicsContextGLOpenGL::prepareForDisplay() > } > #endif > >+void GraphicsContextGLOpenGL::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer) >+{ >+ if (!makeContextCurrent()) >+ return; >+ if (getInternalFramebufferSize().isEmpty()) >+ return; >+ auto imageData = readRenderingResults(); >+ if (!imageData) >+ return; >+ paintToCanvas(imageData.releaseNonNull(), imageBuffer->backendSize(), imageBuffer->context()); >+} >+ >+void GraphicsContextGLOpenGL::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer) >+{ >+ if (!makeContextCurrent()) >+ return; >+ if (getInternalFramebufferSize().isEmpty()) >+ return; >+ auto imageData = readCompositedResults(); >+ if (!imageData) >+ return; >+ paintToCanvas(imageData.releaseNonNull(), imageBuffer->backendSize(), imageBuffer->context()); >+} >+ >+RefPtr<ImageData> GraphicsContextGLOpenGL::paintRenderingResultsToImageData() >+{ >+ if (!makeContextCurrent()) >+ return nullptr; >+ if (getInternalFramebufferSize().isEmpty()) >+ return nullptr; >+ // Reading premultiplied alpha would involve unpremultiplying, which is >+ // lossy. >+ if (contextAttributes().premultipliedAlpha) >+ return nullptr; >+ return readRenderingResults(); >+} >+ >+#if !PLATFORM(COCOA) >+RefPtr<ImageData> GraphicsContextGLOpenGL::readCompositedResults() >+{ >+ return nullptr; >+} >+#endif >+ > } // namespace WebCore > > #endif // ENABLE(WEBGL) >diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h >index f524de92dcd9a598b0fbef8d33b9c4409b8cd1b0..78096e2eb0876f9527c854790d1afa735120c8a9 100644 >--- a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h >+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h >@@ -428,9 +428,6 @@ public: > void getActiveUniformBlockiv(GCGLuint program, GCGLuint uniformBlockIndex, GCGLenum pname, GCGLSpan<GCGLint> params) final; > > // Helper methods. >- >- void paintToCanvas(const unsigned char* imagePixels, const IntSize& imageSize, const IntSize& canvasSize, GraphicsContext&); >- > void markContextChanged() final; > void markLayerComposited() final; > bool layerComposited() const final; >@@ -450,7 +447,7 @@ public: > > void paintRenderingResultsToCanvas(ImageBuffer*) final; > RefPtr<ImageData> paintRenderingResultsToImageData() final; >- bool paintCompositedResultsToCanvas(ImageBuffer*) final; >+ void paintCompositedResultsToCanvas(ImageBuffer*) final; > > #if USE(OPENGL) && ENABLE(WEBGL2) > void primitiveRestartIndex(GCGLuint); >@@ -530,10 +527,11 @@ private: > // Did the most recent drawing operation leave the GPU in an acceptable state? > void checkGPUStatus(); > >- // Read rendering results into a pixel array with the same format as the >- // backbuffer. >- void readRenderingResults(unsigned char* pixels, int pixelsSize); >- void readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels); >+ >+ RefPtr<ImageData> readRenderingResults(); >+ RefPtr<ImageData> readCompositedResults(); >+ RefPtr<ImageData> readPixelsForPaintResults(); >+ void paintToCanvas(Ref<ImageData>&&, const IntSize& canvasSize, GraphicsContext&); > > bool reshapeFBOs(const IntSize&); > void prepareTextureImpl(); >diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp >index f414f9c9634d61b8d9015d5a6afa527cc342be8f..29df7c9013cb915934abab894fab26c9d7fe770f 100644 >--- a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp >+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp >@@ -30,6 +30,7 @@ > #if ENABLE(WEBGL) && USE(OPENGL) > > #include "ExtensionsGLOpenGL.h" >+#include "ImageData.h" > #include "IntRect.h" > #include "IntSize.h" > #include "Logging.h" >@@ -61,37 +62,26 @@ > namespace WebCore { > > >-void GraphicsContextGLOpenGL::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels) >+RefPtr<ImageData> GraphicsContextGLOpenGL::readPixelsForPaintResults() > { >- auto attrs = contextAttributes(); >+ auto imageData = ImageData::create(getInternalFramebufferSize()); >+ if (!imageData) >+ return nullptr; >+ >+ GLint packAlignment = 4; >+ bool mustRestorePackAlignment = false; >+ ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); >+ if (packAlignment > 4) { >+ ::glPixelStorei(GL_PACK_ALIGNMENT, 4); >+ mustRestorePackAlignment = true; >+ } > >- // NVIDIA drivers have a bug where calling readPixels in BGRA can return the wrong values for the alpha channel when the alpha is off for the context. >- if (!attrs.alpha && getExtensions().isNVIDIA()) { >- ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); >-#if USE(ACCELERATE) >- vImage_Buffer src; >- src.height = height; >- src.width = width; >- src.rowBytes = width * 4; >- src.data = pixels; >- >- vImage_Buffer dest; >- dest.height = height; >- dest.width = width; >- dest.rowBytes = width * 4; >- dest.data = pixels; >- >- // Swap pixel channels from RGBA to BGRA. >- const uint8_t map[4] = { 2, 1, 0, 3 }; >- vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags); >-#else >- int totalBytes = width * height * 4; >- for (int i = 0; i < totalBytes; i += 4) >- std::swap(pixels[i], pixels[i + 2]); >-#endif >- } else >- ::glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels); >+ ::glReadPixels(0, 0, imageData->width(), imageData->height(), GL_RGBA, GL_UNSIGNED_BYTE, imageData->data()->data()); >+ >+ if (mustRestorePackAlignment) >+ ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); > >+ return imageData; > } > > void GraphicsContextGLOpenGL::validateAttributes() >diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLCommon.cpp >index 2de185a668130a362c12767f383f57f1349dd481..fcdb711a6f8cb059e00b74cd0ccb7c9ace90da60 100644 >--- a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLCommon.cpp >+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLCommon.cpp >@@ -137,64 +137,6 @@ void GraphicsContextGLOpenGL::validateDepthStencil(const char* packedDepthStenci > } > } > >-void GraphicsContextGLOpenGL::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer) >-{ >- Checked<int, RecordOverflow> rowBytes = Checked<int, RecordOverflow>(m_currentWidth) * 4; >- if (rowBytes.hasOverflowed()) >- return; >- >- Checked<int, RecordOverflow> totalBytesChecked = rowBytes * m_currentHeight; >- if (totalBytesChecked.hasOverflowed()) >- return; >- int totalBytes = totalBytesChecked.unsafeGet(); >- >- auto pixels = makeUniqueArray<unsigned char>(totalBytes); >- if (!pixels) >- return; >- >- readRenderingResults(pixels.get(), totalBytes); >- >- if (!contextAttributes().premultipliedAlpha) { >- for (int i = 0; i < totalBytes; i += 4) { >- // Premultiply alpha. >- pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255); >- pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255); >- pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255); >- } >- } >- >- paintToCanvas(pixels.get(), IntSize(m_currentWidth, m_currentHeight), imageBuffer->backendSize(), imageBuffer->context()); >-} >- >-bool GraphicsContextGLOpenGL::paintCompositedResultsToCanvas(ImageBuffer*) >-{ >- // Not needed at the moment, so return that nothing was done. >- return false; >-} >- >-RefPtr<ImageData> GraphicsContextGLOpenGL::paintRenderingResultsToImageData() >-{ >- // Reading premultiplied alpha would involve unpremultiplying, which is >- // lossy. >- if (contextAttributes().premultipliedAlpha) >- return nullptr; >- >- auto imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight)); >- unsigned char* pixels = imageData->data()->data(); >- Checked<int, RecordOverflow> totalBytesChecked = 4 * Checked<int, RecordOverflow>(m_currentWidth) * Checked<int, RecordOverflow>(m_currentHeight); >- if (totalBytesChecked.hasOverflowed()) >- return imageData; >- int totalBytes = totalBytesChecked.unsafeGet(); >- >- readRenderingResults(pixels, totalBytes); >- >- // Convert to RGBA. >- for (int i = 0; i < totalBytes; i += 4) >- std::swap(pixels[i], pixels[i + 2]); >- >- return imageData; >-} >- > void GraphicsContextGLOpenGL::prepareTexture() > { > if (m_layerComposited) >@@ -236,15 +178,8 @@ void GraphicsContextGLOpenGL::prepareTexture() > ::glFlush(); > } > >-void GraphicsContextGLOpenGL::readRenderingResults(unsigned char *pixels, int pixelsSize) >+RefPtr<ImageData> GraphicsContextGLOpenGL::readRenderingResults() > { >- if (pixelsSize < m_currentWidth * m_currentHeight * 4) >- return; >- >- if (!makeContextCurrent()) >- return; >- >- > bool mustRestoreFBO = false; > if (contextAttributes().antialias) { > resolveMultisamplingIfNecessary(); >@@ -257,22 +192,10 @@ void GraphicsContextGLOpenGL::readRenderingResults(unsigned char *pixels, int pi > ::glBindFramebufferEXT(GraphicsContextGL::FRAMEBUFFER, m_fbo); > } > } >- >- GLint packAlignment = 4; >- bool mustRestorePackAlignment = false; >- ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); >- if (packAlignment > 4) { >- ::glPixelStorei(GL_PACK_ALIGNMENT, 4); >- mustRestorePackAlignment = true; >- } >- >- readPixelsAndConvertToBGRAIfNecessary(0, 0, m_currentWidth, m_currentHeight, pixels); >- >- if (mustRestorePackAlignment) >- ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); >- >+ auto result = readPixelsForPaintResults(); > if (mustRestoreFBO) > ::glBindFramebufferEXT(GraphicsContextGL::FRAMEBUFFER, m_state.boundDrawFBO); >+ return result; > } > > void GraphicsContextGLOpenGL::reshape(int width, int height) >diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLES.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLES.cpp >index 0d476c229d6f6ee96ccf993d81d5c3dd65215e48..939fb93e1c213449d07e03e5cbe80aa81e18ef64 100644 >--- a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLES.cpp >+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLES.cpp >@@ -64,14 +64,26 @@ void GraphicsContextGLOpenGL::readnPixels(GCGLint x, GCGLint y, GCGLsizei width, > ::glBindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); > } > >-void GraphicsContextGLOpenGL::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels) >+RefPtr<ImageData> GraphicsContextGLOpenGL::readPixelsForPaintResults() > { >- ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); >- int totalBytes = width * height * 4; >- if (isGLES2Compliant()) { >- for (int i = 0; i < totalBytes; i += 4) >- std::swap(pixels[i], pixels[i + 2]); // Convert to BGRA. >+ auto imageData = ImageData::create(getInternalFramebufferSize()); >+ if (!imageData) >+ return nullptr; >+ >+ GLint packAlignment = 4; >+ bool mustRestorePackAlignment = false; >+ ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); >+ if (packAlignment > 4) { >+ ::glPixelStorei(GL_PACK_ALIGNMENT, 4); >+ mustRestorePackAlignment = true; > } >+ >+ ::glReadPixels(0, 0, imageData->width(), imageData->height(), GL_RGBA, GL_UNSIGNED_BYTE, imageData->data()->data()); >+ >+ if (mustRestorePackAlignment) >+ ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); >+ >+ return imageData; > } > > bool GraphicsContextGLOpenGL::reshapeFBOs(const IntSize& size) >diff --git a/Source/WebKit/GPUProcess/graphics/RemoteGraphicsContextGLCocoa.cpp b/Source/WebKit/GPUProcess/graphics/RemoteGraphicsContextGLCocoa.cpp >index e7c40c985cb7d2722869a5dff9691947077af46c..8e2d1fc6518628395e9741c44e7ac851b08ef627 100644 >--- a/Source/WebKit/GPUProcess/graphics/RemoteGraphicsContextGLCocoa.cpp >+++ b/Source/WebKit/GPUProcess/graphics/RemoteGraphicsContextGLCocoa.cpp >@@ -48,6 +48,7 @@ public: > // GraphicsContextGLIOSurfaceSwapChain overrides. > Buffer recycleBuffer() final; > void present(Buffer) final; >+ const Buffer& displayBuffer() const final; > void* detachClient() final; > private: > GraphicsContextGLIOSurfaceSwapChain::Buffer m_displayBuffer; >@@ -76,6 +77,11 @@ void RemoteGraphicsContextGLCocoa::present(Buffer buffer) > m_displayBuffer = WTFMove(buffer); > } > >+const GraphicsContextGLIOSurfaceSwapChain::Buffer& RemoteGraphicsContextGLCocoa::displayBuffer() const >+{ >+ return m_displayBuffer; >+} >+ > void* RemoteGraphicsContextGLCocoa::detachClient() > { > return std::exchange(m_displayBuffer.handle, nullptr); >diff --git a/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp b/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp >index 34a06fb0076acd3fd32b3a4b6b09d68d027bb588..53db6150c1d8ec825e23abef651e5b3b9799245e 100644 >--- a/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp >+++ b/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp >@@ -121,6 +121,11 @@ void RemoteGraphicsContextGLProxy::paintRenderingResultsToCanvas(ImageBuffer*) > notImplemented(); > } > >+void RemoteGraphicsContextGLProxy::paintCompositedResultsToCanvas(ImageBuffer*) >+{ >+ notImplemented(); >+} >+ > RefPtr<ImageData> RemoteGraphicsContextGLProxy::paintRenderingResultsToImageData() > { > notImplemented(); >diff --git a/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.h b/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.h >index d99eda29f6db5e1819713178f2aa531b4f5dd6e0..a1439347d89e0adbf08a42a42591bbb3dbeb21e7 100644 >--- a/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.h >+++ b/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.h >@@ -71,6 +71,7 @@ public: > void simulateContextChanged() final; > void paintRenderingResultsToCanvas(WebCore::ImageBuffer*) final; > RefPtr<WebCore::ImageData> paintRenderingResultsToImageData() final; >+ void paintCompositedResultsToCanvas(WebCore::ImageBuffer*) final; > > // Functions with a generated implementation. This list is used by generate-gpup-webgl script. > void setFailNextGPUStatusCheck() final;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 219946
:
416405
|
416406
|
416408
|
416411
|
416412
|
416413
|
416414
|
416415
| 416416