- Revision
- 279741
- Author
- mmaxfi...@apple.com
- Date
- 2021-07-08 12:11:05 -0700 (Thu, 08 Jul 2021)
Log Message
Source/WebCore:
[GPU Process] Draw PDFs using an intermediate ImageBuffer when using the GPU process
https://bugs.webkit.org/show_bug.cgi?id=227550
Reviewed by Tim Horton.
When drawing PDFs, we usually already have a cached ImageBuffer of the contents of the PDF.
However, in the situation where we don't have this cached ImageBuffer, we can't just draw
the PDF into the platformContext when we're using the GPU Process. So, instead, we need to
draw the PDF into an intermediate ImageBuffer and then send that to the GPU Process.
When we have a fully functional custom CGContext, we can use that to send all the PDF drawing
commands to the GPU Process, and this patch should then be reverted.
Test: fast/images/pdf-in-canvas.html
* platform/graphics/cg/PDFDocumentImage.cpp:
(WebCore::PDFDocumentImage::draw):
* platform/mac/LocalCurrentGraphicsContextMac.mm:
(WebCore::LocalCurrentGraphicsContext::LocalCurrentGraphicsContext):
LayoutTests:
[GPU Process] Temporarily disable drawing large PDFs in display list drawing
https://bugs.webkit.org/show_bug.cgi?id=227550
Reviewed by Tim Horton.
* fast/images/pdf-in-canvas-expected.html: Added.
* fast/images/pdf-in-canvas.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (279740 => 279741)
--- trunk/LayoutTests/ChangeLog 2021-07-08 18:54:16 UTC (rev 279740)
+++ trunk/LayoutTests/ChangeLog 2021-07-08 19:11:05 UTC (rev 279741)
@@ -1,3 +1,13 @@
+2021-07-08 Myles C. Maxfield <mmaxfi...@apple.com>
+
+ [GPU Process] Temporarily disable drawing large PDFs in display list drawing
+ https://bugs.webkit.org/show_bug.cgi?id=227550
+
+ Reviewed by Tim Horton.
+
+ * fast/images/pdf-in-canvas-expected.html: Added.
+ * fast/images/pdf-in-canvas.html: Added.
+
2021-07-08 Ayumi Kojima <ayumi_koj...@apple.com>
[Mac wk2 Debug] fast/canvas/canvas-composite-image.html is a flaky crash.
Added: trunk/LayoutTests/fast/images/pdf-in-canvas-expected.html (0 => 279741)
--- trunk/LayoutTests/fast/images/pdf-in-canvas-expected.html (rev 0)
+++ trunk/LayoutTests/fast/images/pdf-in-canvas-expected.html 2021-07-08 19:11:05 UTC (rev 279741)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<p>This test passes if you see a green box below (possibly with a green border).</p>
+<div style="position: relative;">
+ <div style="position: absolute; left: 0px; top: 0px; width: 100px; height: 100px; background: #008E00;"></div>
+ <div style="position: absolute; left: -3px; top: -3px; width: 6px; height: 106px; background: green;"></div>
+ <div style="position: absolute; left: 97px; top: -3px; width: 6px; height: 106px; background: green;"></div>
+ <div style="position: absolute; left: -3px; top: -3px; width: 106px; height: 6px; background: green;"></div>
+ <div style="position: absolute; left: -3px; top: 97px; width: 106px; height: 6px; background: green;"></div
+</div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/images/pdf-in-canvas.html (0 => 279741)
--- trunk/LayoutTests/fast/images/pdf-in-canvas.html (rev 0)
+++ trunk/LayoutTests/fast/images/pdf-in-canvas.html 2021-07-08 19:11:05 UTC (rev 279741)
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<p>This test passes if you see a green box below (possibly with a green border).</p>
+<img id="image">
+<div style="position: relative;">
+ <canvas id="canvas" width="100" height="100"></canvas>
+ <div style="position: absolute; left: -3px; top: -3px; width: 6px; height: 106px; background: green;"></div>
+ <div style="position: absolute; left: 97px; top: -3px; width: 6px; height: 106px; background: green;"></div>
+ <div style="position: absolute; left: -3px; top: -3px; width: 106px; height: 6px; background: green;"></div>
+ <div style="position: absolute; left: -3px; top: 97px; width: 106px; height: 6px; background: green;"></div
+</div>
+<script>
+if (window.testRunner) {
+ testRunner.waitUntilDone();
+}
+// Emulate a big PDF on iOS (which has the PDFImageCachingPolicy set to BelowMemoryLimit).
+if (window.internals)
+ internals.settings.setPDFImageCachingPolicy("Disabled");
+let canvas = document.getElementById("canvas");
+let context = canvas.getContext("2d");
+let image = document.getElementById("image");
+image.addEventListener("load", function() {
+ var state = 0;
+ function tick() {
+ context.drawImage(image, 0, 0, 100, 100);
+ if (state < 10) {
+ context.fillRect(0, 0, 100, 100);
+ ++state;
+ requestAnimationFrame(tick);
+ } else {
+ image.style.display = "none";
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }
+ }
+ requestAnimationFrame(tick);
+});
+image.src = ""
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (279740 => 279741)
--- trunk/Source/WebCore/ChangeLog 2021-07-08 18:54:16 UTC (rev 279740)
+++ trunk/Source/WebCore/ChangeLog 2021-07-08 19:11:05 UTC (rev 279741)
@@ -1,3 +1,25 @@
+2021-07-08 Myles C. Maxfield <mmaxfi...@apple.com>
+
+ [GPU Process] Draw PDFs using an intermediate ImageBuffer when using the GPU process
+ https://bugs.webkit.org/show_bug.cgi?id=227550
+
+ Reviewed by Tim Horton.
+
+ When drawing PDFs, we usually already have a cached ImageBuffer of the contents of the PDF.
+ However, in the situation where we don't have this cached ImageBuffer, we can't just draw
+ the PDF into the platformContext when we're using the GPU Process. So, instead, we need to
+ draw the PDF into an intermediate ImageBuffer and then send that to the GPU Process.
+
+ When we have a fully functional custom CGContext, we can use that to send all the PDF drawing
+ commands to the GPU Process, and this patch should then be reverted.
+
+ Test: fast/images/pdf-in-canvas.html
+
+ * platform/graphics/cg/PDFDocumentImage.cpp:
+ (WebCore::PDFDocumentImage::draw):
+ * platform/mac/LocalCurrentGraphicsContextMac.mm:
+ (WebCore::LocalCurrentGraphicsContext::LocalCurrentGraphicsContext):
+
2021-07-08 Yusuke Suzuki <ysuz...@apple.com>
Use JSC::Yarr::flagsString to get string representation of RegExp flags
Modified: trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp (279740 => 279741)
--- trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp 2021-07-08 18:54:16 UTC (rev 279740)
+++ trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp 2021-07-08 19:11:05 UTC (rev 279741)
@@ -161,6 +161,9 @@
context.translate(dstRect.location() - srcRect.location());
context.scale(FloatSize(hScale, -vScale));
context.translate(0, -srcRect.height());
+
+ // FIXME https://bugs.webkit.org/show_bug.cgi?id=227808: Surely there needs to be a clip operation here,
+ // if the srcRect is smaller than the whole PDF.
}
// To avoid the jetsam on iOS, we are going to limit the size of all the PDF cachedImages to be 64MB.
@@ -246,6 +249,8 @@
// We need to transform the coordinate system such that top-left of m_cachedImageRect will be mapped to the
// top-left of dstRect. Although only m_cachedImageRect.size() of the image copied, the sizes of srcRect
// and dstRect should be passed to this function because they are used to calculate the image scaling.
+ // FIXME https://bugs.webkit.org/show_bug.cgi?id=227809: Passing in m_cachedImageRect.location() for the
+ // source rect position doesn't seem correct here.
transformContextForPainting(bufferContext, dstRect, FloatRect(m_cachedImageRect.location(), srcRect.size()));
drawPDFPage(bufferContext);
@@ -275,10 +280,25 @@
// of the source PDF was copied to 'm_cachedImageBuffer', the sizes of the source
// and the destination rectangles will be equal and no scaling will be needed here.
context.drawImageBuffer(*m_cachedImageBuffer, m_cachedImageRect);
- }
- else {
+ } else if (context.hasPlatformContext()) {
transformContextForPainting(context, dstRect, srcRect);
drawPDFPage(context);
+ } else {
+ // We can't draw the PDF directly because we have no platform context (probably because we're doing display list drawing).
+ // We also need to be careful about not getting terminated due to memory pressure.
+ //
+ // (scalar * width) * (scalar * height) = max number of pixels
+ // Solve for scalar...
+ // scalar = sqrt(max number of pixels / (width * height))
+ auto scalar = std::min(1.f, std::sqrt(static_cast<float>(s_maxCachedImageArea) / (dstRect.width() * dstRect.height())));
+ FloatRect localDestinationRect(FloatPoint(), dstRect.size() * scalar);
+ if (auto imageBuffer = ImageBuffer::createCompatibleBuffer(localDestinationRect.size(), context)) {
+ auto& bufferContext = imageBuffer->context();
+ transformContextForPainting(bufferContext, localDestinationRect, srcRect);
+ drawPDFPage(bufferContext);
+ context.drawImageBuffer(*imageBuffer, dstRect);
+ } else
+ return ImageDrawResult::DidNothing;
}
}
Modified: trunk/Source/WebCore/platform/mac/LocalCurrentGraphicsContextMac.mm (279740 => 279741)
--- trunk/Source/WebCore/platform/mac/LocalCurrentGraphicsContextMac.mm 2021-07-08 18:54:16 UTC (rev 279740)
+++ trunk/Source/WebCore/platform/mac/LocalCurrentGraphicsContextMac.mm 2021-07-08 19:11:05 UTC (rev 279741)
@@ -32,7 +32,8 @@
m_savedGraphicsContext.save();
if (!m_savedGraphicsContext.hasPlatformContext()) {
- WTFLogAlways("LocalCurrentGraphicsContext is not setting the global context because the provided GraphicsContext does not have a platform context (likely display list recording)");
+ WTFLogAlways("LocalCurrentGraphicsContext is setting the global context to nil because the provided GraphicsContext does not have a platform context (likely display list recording)");
+ [NSGraphicsContext setCurrentContext:nil];
return;
}