Modified: trunk/Source/WebCore/ChangeLog (280962 => 280963)
--- trunk/Source/WebCore/ChangeLog 2021-08-12 13:01:27 UTC (rev 280962)
+++ trunk/Source/WebCore/ChangeLog 2021-08-12 13:35:06 UTC (rev 280963)
@@ -1,3 +1,28 @@
+2021-08-12 Kimmo Kinnunen <[email protected]>
+
+ webgl/1.0.x/conformance/textures/misc/texture-corner-case-videos.html fails on Cocoa
+ https://bugs.webkit.org/show_bug.cgi?id=228821
+ <rdar://problem/81562236>
+
+ Reviewed by Kenneth Russell.
+
+ When uploading the WebGL texture content from videos, use the video
+ visible data size instead of video element size. The video data can
+ be scaled with its filters, but we should upload only the original
+ pixels.
+
+ The GPU codepath already did this, but CPU codepath did not.
+ This change fixes the CPU codepath.
+
+ Fixes webgl/1.0.x/conformance/textures/misc/texture-corner-case-videos.html
+ webgl/2.0.y/conformance/textures/misc/texture-corner-case-videos.html
+
+ * html/canvas/WebGLRenderingContextBase.cpp:
+ (WebCore::WebGLRenderingContextBase::texImageSourceHelper):
+ (WebCore::WebGLRenderingContextBase::videoFrameToImage):
+ (WebCore::WebGLRenderingContextBase::LRUImageBufferCache::imageBuffer):
+ * html/canvas/WebGLRenderingContextBase.h:
+
2021-08-12 Youenn Fablet <[email protected]>
Implement SFrameTransform error handling
Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (280962 => 280963)
--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp 2021-08-12 13:01:27 UTC (rev 280962)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp 2021-08-12 13:35:06 UTC (rev 280963)
@@ -4934,7 +4934,7 @@
}
// Fallback pure SW path.
- RefPtr<Image> image = videoFrameToImage(video.get(), DontCopyBackingStore);
+ RefPtr<Image> image = videoFrameToImage(video.get(), DontCopyBackingStore, functionName);
if (!image)
return { };
texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, zoffset, format, type, image.get(), GraphicsContextGL::DOMSource::Video, m_unpackFlipY, m_unpackPremultiplyAlpha, false, inputSourceImageRect, depth, unpackImageHeight);
@@ -5768,18 +5768,44 @@
#if ENABLE(VIDEO)
-RefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy)
+RefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy, const char* functionName)
{
- IntSize size(video->videoWidth(), video->videoHeight());
- ImageBuffer* buf = m_generatedImageCache.imageBuffer(size);
- if (!buf) {
- synthesizeGLError(GraphicsContextGL::OUT_OF_MEMORY, "texImage2D", "out of memory");
+#if USE(AVFOUNDATION)
+ auto nativeImage = video->nativeImageForCurrentTime();
+ // Currently we might be missing an image due to MSE not being able to provide the first requested frame.
+ // https://bugs.webkit.org/show_bug.cgi?id=228997
+ if (!nativeImage)
return nullptr;
+ IntSize imageSize = nativeImage->size();
+ if (imageSize.isEmpty()) {
+ synthesizeGLError(GraphicsContextGL::INVALID_VALUE, functionName, "video visible size is empty");
+ return nullptr;
}
- FloatRect destRect(0, 0, size.width(), size.height());
- // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
- video->paintCurrentFrameInContext(buf->context(), destRect);
- return buf->copyImage(backingStoreCopy);
+ FloatRect imageRect { { }, imageSize };
+ ImageBuffer* imageBuffer = m_generatedImageCache.imageBuffer(imageSize, CompositeOperator::Copy);
+ if (!imageBuffer) {
+ synthesizeGLError(GraphicsContextGL::OUT_OF_MEMORY, functionName, "out of memory");
+ return nullptr;
+ }
+ imageBuffer->context().drawNativeImage(*nativeImage, imageRect.size(), imageRect, imageRect, CompositeOperator::Copy);
+#else
+ // This is a legacy code path that produces incompatible texture size when the
+ // video visible size is different to the natural size. This should be removed
+ // once all platforms implement nativeImageForCurrentTime().
+ IntSize videoSize { static_cast<int>(video->videoWidth()), static_cast<int>(video->videoHeight()) };
+ ImageBuffer* imageBuffer = m_generatedImageCache.imageBuffer(videoSize);
+ if (!imageBuffer) {
+ synthesizeGLError(GraphicsContextGL::OUT_OF_MEMORY, functionName, "out of memory");
+ return nullptr;
+ }
+ video->paintCurrentFrameInContext(imageBuffer->context(), { { }, videoSize });
+#endif
+ RefPtr<Image> image = imageBuffer->copyImage(backingStoreCopy);
+ if (!image) {
+ synthesizeGLError(GraphicsContextGL::OUT_OF_MEMORY, functionName, "out of memory");
+ return nullptr;
+ }
+ return image;
}
#endif
@@ -7621,7 +7647,7 @@
{
}
-ImageBuffer* WebGLRenderingContextBase::LRUImageBufferCache::imageBuffer(const IntSize& size)
+ImageBuffer* WebGLRenderingContextBase::LRUImageBufferCache::imageBuffer(const IntSize& size, CompositeOperator fillOperator)
{
size_t i;
for (i = 0; i < m_buffers.size(); ++i) {
@@ -7631,7 +7657,8 @@
if (buf->logicalSize() != size)
continue;
bubbleToFront(i);
- buf->context().clearRect(FloatRect({ }, FloatSize(size)));
+ if (fillOperator != CompositeOperator::Copy && fillOperator != CompositeOperator::Clear)
+ buf->context().clearRect({ { }, size });
return buf;
}
Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h (280962 => 280963)
--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h 2021-08-12 13:01:27 UTC (rev 280962)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h 2021-08-12 13:35:06 UTC (rev 280963)
@@ -524,7 +524,7 @@
RefPtr<Image> drawImageIntoBuffer(Image&, int width, int height, int deviceScaleFactor, const char* functionName);
#if ENABLE(VIDEO)
- RefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy);
+ RefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy, const char* functionName);
#endif
WebGLTexture::TextureExtensionFlag textureExtensionFlags() const;
@@ -614,8 +614,9 @@
class LRUImageBufferCache {
public:
LRUImageBufferCache(int capacity);
- // The pointer returned is owned by the image buffer map.
- ImageBuffer* imageBuffer(const IntSize& size);
+ // Returns pointer to a cleared image buffer that is owned by the cache. The pointer is valid until next call.
+ // Using fillOperator == CompositeOperator::Copy can be used to omit the clear of the buffer.
+ ImageBuffer* imageBuffer(const IntSize&, CompositeOperator fillOperator = CompositeOperator::SourceOver);
private:
void bubbleToFront(size_t idx);
Vector<RefPtr<ImageBuffer>> m_buffers;