Skip to content

Commit

Permalink
OffscreenCanvas.transferToImageBuffer() does not clear WebGL drawing …
Browse files Browse the repository at this point in the history
…buffer correctly

https://bugs.webkit.org/show_bug.cgi?id=272960
rdar://126738038

Reviewed by Matt Woodrow.

OffscreenCanvas.transferToImageBuffer() should cause compositing steps
similar to the case of preserveDrawingBuffer=false drawing buffer is
displayed:
 - color buffer, depth, stencil is cleared

Previous clear implementation would use WebGL context state, which
would not necceassarily clear the correct framebuffer in a correct
way.

* Source/WebCore/html/OffscreenCanvas.cpp:
(WebCore::OffscreenCanvas::transferToImageBitmap):
* Source/WebCore/html/canvas/WebGLDefaultFramebuffer.cpp:
(WebCore::WebGLDefaultFramebuffer::markAllBuffersDirty):
* Source/WebCore/html/canvas/WebGLDefaultFramebuffer.h:
* Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::WebGLRenderingContextBase::markBuffersDirtyForTransfer):
* Source/WebCore/html/canvas/WebGLRenderingContextBase.h:

Canonical link: https://commits.webkit.org/279434@main
  • Loading branch information
kkinnunen-apple committed May 29, 2024
1 parent 14d2ee9 commit c3988b9
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 16 deletions.
1 change: 0 additions & 1 deletion LayoutTests/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -1333,7 +1333,6 @@ http/tests/websocket/tests/hybi/imported/blink/permessage-deflate-split-frames.h
http/tests/websocket/tests/hybi/imported/blink/permessage-deflate-unsolicited-negotiation-response.html [ Skip ]
http/tests/websocket/tests/hybi/imported/blink/permessage-deflate-window-bits.html [ Skip ]

http/wpt/offscreen-canvas/transferToImageBitmap-webgl.html [ ImageOnlyFailure Failure ]
imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html [ Failure Pass ]
imported/w3c/web-platform-tests/html/canvas/offscreen/the-offscreen-canvas/size.large.html [ Skip ]

Expand Down
16 changes: 4 additions & 12 deletions Source/WebCore/html/OffscreenCanvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,19 +356,11 @@ ExceptionOr<RefPtr<ImageBitmap>> OffscreenCanvas::transferToImageBitmap()
auto buffer = allocateImageBuffer();
if (!buffer)
return { RefPtr<ImageBitmap> { nullptr } };

if (webGLContext->compositingResultsNeedUpdating())
webGLContext->prepareForDisplay();
RefPtr gc3d = webGLContext->graphicsContextGL();
gc3d->drawSurfaceBufferToImageBuffer(GraphicsContextGL::SurfaceBuffer::DrawingBuffer, *buffer);

// FIXME: The transfer algorithm requires that the canvas effectively
// creates a new backing store. Since we're not doing that yet, we
// need to erase what's there.

GCGLfloat clearColor[4] { };
gc3d->getFloatv(GraphicsContextGL::COLOR_CLEAR_VALUE, clearColor);
gc3d->clearColor(0, 0, 0, 0);
gc3d->clear(GraphicsContextGL::COLOR_BUFFER_BIT | GraphicsContextGL::DEPTH_BUFFER_BIT | GraphicsContextGL::STENCIL_BUFFER_BIT);
gc3d->clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
gc3d->drawSurfaceBufferToImageBuffer(GraphicsContextGL::SurfaceBuffer::DisplayBuffer, *buffer);
webGLContext->markDrawingBuffersDirtyAfterTransfer();
return { ImageBitmap::create(buffer.releaseNonNull(), originClean()) };
}
#endif
Expand Down
9 changes: 9 additions & 0 deletions Source/WebCore/html/canvas/WebGLDefaultFramebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ void WebGLDefaultFramebuffer::markAllUnpreservedBuffersDirty()
m_dirtyBuffers = m_unpreservedBuffers;
}

void WebGLDefaultFramebuffer::markAllBuffersDirty()
{
m_dirtyBuffers |= GraphicsContextGL::COLOR_BUFFER_BIT;
if (m_hasStencil)
m_dirtyBuffers |= GraphicsContextGL::STENCIL_BUFFER_BIT;
if (m_hasDepth)
m_dirtyBuffers |= GraphicsContextGL::DEPTH_BUFFER_BIT;
}

}

#endif
1 change: 1 addition & 0 deletions Source/WebCore/html/canvas/WebGLDefaultFramebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class WebGLDefaultFramebuffer {
GCGLbitfield dirtyBuffers() const { return m_dirtyBuffers; }
void markBuffersClear(GCGLbitfield clearBuffers);
void markAllUnpreservedBuffersDirty();
void markAllBuffersDirty();

private:
WebGLDefaultFramebuffer(WebGLRenderingContextBase&);
Expand Down
9 changes: 9 additions & 0 deletions Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,14 @@ RefPtr<VideoFrame> WebGLRenderingContextBase::surfaceBufferToVideoFrame(SurfaceB
}
#endif

void WebGLRenderingContextBase::markDrawingBuffersDirtyAfterTransfer()
{
// Any draw or read sees cleared drawing buffer.
m_defaultFramebuffer->markAllBuffersDirty();
// Next transfer uses the cleared drawing buffer.
m_compositingResultsNeedUpdating = true;
}

WebGLTexture::TextureExtensionFlag WebGLRenderingContextBase::textureExtensionFlags() const
{
return static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureExtensionFloatLinearEnabled : 0) | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureExtensionHalfFloatLinearEnabled : 0));
Expand Down Expand Up @@ -5682,6 +5690,7 @@ void WebGLRenderingContextBase::prepareForDisplay()
return;
ASSERT(m_compositingResultsNeedUpdating);

clearIfComposited(CallerTypeOther);
m_context->prepareForDisplay();
m_defaultFramebuffer->markAllUnpreservedBuffersDirty();

Expand Down
7 changes: 4 additions & 3 deletions Source/WebCore/html/canvas/WebGLRenderingContextBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ class WebGLRenderingContextBase : public GraphicsContextGL::Client, public GPUBa
#if ENABLE(MEDIA_STREAM) || ENABLE(WEB_CODECS)
RefPtr<VideoFrame> surfaceBufferToVideoFrame(SurfaceBuffer);
#endif
void markDrawingBuffersDirtyAfterTransfer();

void removeSharedObject(WebGLObject&);
void removeContextObject(WebGLObject&);
Expand Down Expand Up @@ -486,6 +487,9 @@ class WebGLRenderingContextBase : public GraphicsContextGL::Client, public GPUBa
const PixelStoreParameters& unpackPixelStoreParameters() const { return m_unpackParameters; };

WeakPtr<WebGLRenderingContextBase> createRefForContextObject();

bool compositingResultsNeedUpdating() const final { return m_compositingResultsNeedUpdating; }
void prepareForDisplay() final;
protected:
WebGLRenderingContextBase(CanvasBase&, WebGLContextAttributes&&);

Expand Down Expand Up @@ -590,10 +594,7 @@ class WebGLRenderingContextBase : public GraphicsContextGL::Client, public GPUBa
void loseExtensions(LostContextMode);

virtual void uncacheDeletedBuffer(const AbstractLocker&, WebGLBuffer*);

bool compositingResultsNeedUpdating() const final { return m_compositingResultsNeedUpdating; }
bool needsPreparationForDisplay() const final { return true; }
void prepareForDisplay() final;
void updateActiveOrdinal();

struct ContextLostState {
Expand Down

0 comments on commit c3988b9

Please sign in to comment.