Enforce the use of the CPU backend in test mode to ensure that ref-tests
produce consistent results across different computers, as this
consistency cannot be achieved with the GPU backend.
Skia now uses GPU-accelerated painting on Linux if Vulkan is available.
Most of the performance gain is currently negated by reading the GPU
backend back into RAM to pass it to the Browser process. In the future,
this could be improved by sharing GPU-allocated memory across the
Browser and WebContent processes.
GPU painter that uses AccelGfx is slower and way less complete compared
to both default Gfx::Painter and Skia painter. It does not make much
sense to keep it, considering Skia painter already uses Metal backend on
macOS by default and there is an option to enable GPU-accelerated
backend on linux.
If Metal context and IOSurface are available, Skia painter will use
Ganesh GPU backend on macOS, which is noticeably faster than the default
CPU backend.
Painting pipeline:
1. (WebContent) Allocate IOSurface for backing store
2. (WebContent) Allocate MTLTexture that wraps IOSurface
3. (WebContent) Paint into MTLTexture using Skia
4. (Browser) Wrap IOSurface into Gfx::Painter and use
QPainter/CoreGraphics to blit backing store into viewport.
Things we should improve in the future:
1. Upload textures for images in advance instead of doing that before
every repaint.
2. Teach AppKit client to read directly from IOSurface instead of
copying.
This change introduces Skia painter available under a flag. It's not
yet match capabilities of Gfx::Painter and is not ready to replace it.
Motivation:
- The current CPU painter is a performance bottleneck on most websites.
Our own GPU painter implementation is very immature and has received
relatively little attention.
- There is ongoing effort on building painter that supports affine
transforms (AffineCommandExecutorCPU) but it is far from being on par
with the default CPU painter. Skia will allow us to immediately get
full transformation support for all painting commands.
GPU painting:
I experimented with Ganesh GPU-backend, however profiling revealed that
without sharing viewport texture between WebContent and Browser
processes, it won't bring much performance improvement compared to
CPU-backend. Therefore, I decided to keep this PR focused on
implementing most of painting commands and switch to GPU-backend in
future changes.
Text rendring:
Skia painter uses glyph bitmaps produced by LibGfx. Using Skia for text
rendering will require large refactoring of the font rendering
subsystem. Currently, it's impossible to construct SkFont right before
rendering because Gfx::VectorFont can't be serialized back into sequence
of bytes.
There is a problem with ugly include paths like:
`#include <core/SkBitmap.h>`.
I would prefer to have skia prefix in the path. There was an attempt to
fix that but PR was rejected https://github.com/microsoft/vcpkg/pull/32660
Regressions compared to Gfx::Painter:
- DrawText is not implemented
- PaintTextShadow is not implemented
- PaintRadialGradient and PaintLinearGradient do not support "transition
hints" and repeat length
- PaintConicGradient is not implemented
- DrawTriangleWave is not implemented
- DrawLine does not account for line style property
- DrawScaledBitmap and DrawScaledImmutableBitmap do not account for
scaling mode property
Capturing a struct that owns bunch of JS::Handle makes it very hard to
understand what keeps these handles alive in the GC-graph.
Instead let's capture only members of a struct used in the callback.
Changes the signature of queue_global_task() from AK:Function to
JS::HeapFunction to be more clear to the user of the function that this
is what it uses internally.
Fixes bug when "navigate forward" button in UI is disabled after
performing following steps:
1. Load page with an iframe (top step = 0, iframe step = 0)
2. Navigate iframe to different document (top step = 0, iframe step = 1)
3. Navigate back from browser UI (top step = 0, iframe step = 0)
No test because change is only observable from browser UI.
It is going to be used to communicate whether it is possible to navigate
back or forward after session history stored on browser side will no
longer be used to driver navigation.
See spec issue https://github.com/whatwg/html/issues/9869
Previous attempt on fixing reload had to be reverted because it broke
Soundcloud and GitHub, but this change does not seem to introduce new
crashes.
"apply the history step" initiated by reloading or back/forward
navigation might require doing fetching while populating a document,
so it is not possible to restrict spin_until() to process only
NavigationAndTraversal task source.
"apply the history step" initiated by synchronous navigation keeps
processing only NavigationAndTraversal task source because it will
never have to populate a document. Another reason to keep synchronous
navigation blocking other task sources is that we crash if active SHE
changes in the middle of "apply the history step" initiated by sync
navigation. The new test is added to makes sure we don't regress that.
Workaround spec bug by explicitly carrying information whether
navigation is sync (History api, fragment change) or not.
See for more details https://github.com/whatwg/html/issues/10232
These changes do not solve hanging `location.reload()` and
`location.go()` but only align implementation with the latest edits in
the specification.
`WindowProxy-Get-after-detaching-from-browsing-context` test output is
affected because `iframe.remove();` no longer synchronously does
destruction of a document, but queues a task on event loop.
Co-Authored-By: Andrew Kaster <akaster@serenityos.org>
While waiting for a task that populates a session history entry, we
can't limit the processing of the event loop to the
`NavigationAndTraversal` task source. This is because fetching uses the
`Networking` task source, which also needs to be processed.
Since making a fetch request might take some time, we want to process
everything on the event loop while waiting, to avoid blocking user
interactions.
It is still possible to use `spin_processing_tasks_with_source_until()`
on subsequent steps of `apply_the_history_step()`.
Also modifies test that was flaky.
In our implementation of the "apply the history step" algorithm, we
have to spin-wait for the completion of tasks queued on the event loop.
Before this change, we allowed tasks from any source to be executed
while we were waiting. It should not be possible because it allows to
interrupt history step application by anything, including another
history step application.
Fixes https://github.com/SerenityOS/serenity/issues/23598
This URL library ends up being a relatively fundamental base library of
the system, as LibCore depends on LibURL.
This change has two main benefits:
* Moving AK back more towards being an agnostic library that can
be used between the kernel and userspace. URL has never really fit
that description - and is not used in the kernel.
* URL _should_ depend on LibUnicode, as it needs punnycode support.
However, it's not really possible to do this inside of AK as it can't
depend on any external library. This change brings us a little closer
to being able to do that, but unfortunately we aren't there quite
yet, as the code generators depend on LibCore.
When WebDriver asks to destroy a window, we can hit this case with no
active browsing context. This seems odd, but perhaps is a spec issue as
well. Just log to dbgln for now.
The IPC layer between chromes and LibWeb now understands that multiple
top level traversables can live in each WebContent process.
This largely mechanical change adds a billion page_id/page_index
arguments to make sure that pages that end up opening new WebViews
through mechanisms like window.open() still work properly with those
extra windows.