Previously, bitmap-backed images were stored as raster SkImages and
re-uploaded to the GPU every frame. This caused significant overhead
in createProxyFromBitmap, uploadToTexture, and memmove.
Now, ensure_sk_image() converts raster SkImages to GPU textures using
SkImages::TextureFromImage() on first use. The texture is cached and
reused for subsequent frames.
- Mipmaps disabled (kNo) to reduce upload time and memory
- Budgeted (kYes) to let Skia manage GPU memory and evict under pressure
- Falls back to raster rendering if no GPU context available
Previously, SkTextBlob was built on every paint in
DisplayListPlayerSkia::draw_glyph_run(), which meant:
- Repeated work when the same display list is painted multiple times
- Glyph arrays were allocated and populated on each paint
Now the blob is built once during display list recording and cached in
GlyphRun.
Previously, both mask and clip-path were rendered to separate mutable
Gfx::Bitmap objects which forced CPU rasterization. They were then
combined using a CPU pixel-by-pixel operation before being returned
as an ImmutableBitmap.
Instead of including mask in the final bitmap as already rasterized
images, we now use display lists which opens opportunity to utilize
GPU if available.
Bitmap::apply_mask() and ApplyMaskBitmap display list command are no
longer used and have been removed.
This saves us from having our own color conversion code, which was
taking up a fair amount of time in VideoDataProvider. With this change,
we should be able to play high resolution videos without interruptions
on machines where the CPU can keep up with decoding.
In order to make this change, ImmutableBitmap is now able to be
constructed with YUV data instead of an RBG bitmap. It holds onto a
YUVData instance that stores the buffers of image data, since Skia
itself doesn't take ownership of them.
In order to support greater than 8 bits of color depth, we normalize
the 10- or 12-bit color values into a 16-bit range.
A malicious IPC peer could claim an enormous color space size, causing
OOM when we try to allocate a buffer. Add a 1 MiB limit since color
space profiles shouldn't be anywhere near that large.
Also validate that SkColorSpace::Deserialize() actually succeeded
before using the result.
The total_buffer_size calculation could theoretically overflow if we
tried to encode a sequence of bitmaps with combined size > SIZE_MAX.
Use Checked<size_t> and VERIFY to catch this (unlikely) encoding bug.
When rendering text, if none of the fonts in the cascade list contain a
glyph for a given code point, we now query Skia's font manager to find
a system font that can render it.
ENABLE_WINDOWS_CI and the *_CI presets were initially added back when
the AK library and all the AK Test* executables were the only targets
that supported building and running in CI. Since then, almost all the
targets in the codebase are built on Windows besides the following:
- LibLine
- test-262-runner
Since these targets above are not required to actually run or test the
browser on Windows in its current experimental state, fully disabling
them should be fine for now.
ENABLE_WINDOWS_CI was also used to exclude test-web from ctest. This
can be fully disabled on Windows for now until proper runtime support
is added.
The remaining locations were all using ENABLE_WINDOWS_CI as a proxy for
ENABLE_ADDRESS_SANITIZER, so we can just be explicit instead.
The new presets map much more directly to the unix Release, Debug, and
Sanitizer presets which should make setting up ladybird on Windows less
confusing.
We also make the new Windows_Experimental_Release preset the default in
ladybird.py to match Unix.
Add ElementResizeAction to Page (maybe there's a better place). It's
just a mousemove delegate that updates styles on the target element.
Add ChromeMetrics for zoom-invariant chrome like scrollbar thumb
thickness, resize gripper size, paddings, etc. It's not user-stylable
but separates basic concerns in a way that a visually gifted
designer unlike myself can adjust to taste.
These values are pre-divided by zoom factor so that PaintableBox can
continue using device_pixels_per_css_pixel calls as normal.
The adjusted metrics are computed on demand from Page multiple times
per paint cycle, which is not ideal but avoids lifetime management and
atomics. Maybe someone with more surety about the painting flow control
can improve this, but it won't be a huge win. If profiling shows
this slowing paints, then Ladybird is in good shape.
Update PaintableBox to draw the resize gripper and deconflict
the scrollbars. Set apropriate cursors for scrollbars and gripper in
mousemove. We override EventHandler's cursor handling because nothing
should ever come between a man and his resize gripper.
Chrome metrics use the CSSPixels class. This is good because it's
broadly compatible but bad because they're actually different units
when zoom is not 1.0. If that's a problem, we could make a new type
or just use double.
For ASCII text, we know the script is Latin and direction is LTR.
Set these properties directly instead of calling
hb_buffer_guess_segment_properties(), which scans the text buffer
to detect script and direction.
For non-ASCII text, use the text_type parameter to set direction
when known (Ltr/Rtl), reducing guesswork to just script detection.
Skia deprecated some non-span versions of their API, but they provided
SK_SUPPORT_UNSPANNED_APIS to expose the legacy versions.
SkFontMgr_New_FontConfig now requires a font scanner to be passed in.
There were a few screenshot tests that visibily looked the same but skia
must've changed some rendering infrastructure as the PNGs were not
matching anymore so I rebaselined those and adjusted the fuzzy matching
config to allow them to pass on both macOS and Linux.
The empty-radial-gradient-crash Ref test started to fail as we were
setting the horizontal scale factor to inf in when the height = 0. It
looks like something changed to make doing that not valid anymore.
The overlay port is removed as the issues, mainly skcms symbol import
and export were resolved upstream in skia and utilized in the new port
version.
Skia deprecated some non-span versions of their API, but they provided
SK_SUPPORT_UNSPANNED_APIS to expose the legacy versions.
SkFontMgr_New_FontConfig now requires a font scanner to be passed in.
There were a few screenshot tests that visibily looked the same but skia
must've changed some rendering infrastructure as the PNGs were not
matching anymore so I rebaselined those and adjusted the fuzzy matching
config to allow them to pass on both macOS and Linux.
The empty-radial-gradient-crash Ref test started to fail as we were
setting the horizontal scale factor to inf in when the height = 0. It
looks like something changed to make doing that not valid anymore.
The overlay port is removed as the issues, mainly skcms symbol import
and export were resolved upstream in skia and utilized in the new port
version.
The recent commits 28ba610f32 and
70c4ed261f adjusted some include
directives to avoid excessive recompilation when changing some header
files. This has broken compilation with clang-cl on Windows without
getting noticed before the PRs were merged.
The verified pixel output in this test just reflects currently observed
behavior, I have not verified that all cases output the correct data wrt
what the spec expects.
This makes it so that we can visit satellite and hybrid view on
maps.apple.com. Previously this would crash from a bounds check due to
us asking Skia to write 32bpp RGBx8888 data into a buffer sized for
24bpp RGB888.
This is not technically necessary, presumably the bitmap type does not
offer any guarantees about what values are stored in the alpha component
for non-alpha pixel formats.
But the previous behavior meant that `set_pixel()` would produce
different values in the alpha component depending on whether the bitmap
format was RGBx or BGRx (i.e. `color.alpha()` vs. 0x00), which can be a
bit confusing.
This factors the conversion logic to be independent from WebGL code,
allowing us to write unit tests for it that can run in CI (since WebGL
can't run in CI).
The `Bitmap` type was referring to to its internal pixel format by a
name that represents the order of the color components as they are layed
out in memory. Contrary, the `Color` type was using a naming that where
the name represents the order of the components from most to least
significant byte when viewed as a unsigned 32bit integer. This is
confusing as you have to keep remembering which mental model to use
depending on which code you work with.
To unify the two, the naming of RGBA-like colors in the `Color` type has
been adjusted to match the one from the Bitmap type. This seems to be
generally in line with how web APIs think about these types:
* `ImageData.pixelFormat` can be `rgba-8unorm` backed by a
`Uint8ClamedArray`, but there is no pixel format backed by a 32bit
unsigned type.
* WebGL can use format `RGBA` with type `UNSIGNED_BYTE`, but there is no
such format with type `UNSIGNED_INT`.
Additionally, it appears that other browsers and browser-adjacent
libraries also think similarly about these types:
* Firefox:
https://github.com/mozilla-firefox/firefox/blob/main/gfx/2d/Types.h
* WebKit:
https://github.com/WebKit/WebKit/blob/main/Source/WebCore/platform/graphics/PixelFormat.h
* Skia:
https://chromium.googlesource.com/skia/+/refs/heads/main/include/core/SkColorType.h
This has the not so nice side effect that APIs that interact with these
types through 32bit unsigned integers now have the component order
inverted due to little-endian byte order. E.g. specifying a color as hex
constant needs to be done as `0xAABBGGRR` if it is to be treated as
RGBA8888.
We could alleviate this by providing endian-independent APIs to callers.
But I suspect long-term we might want to think differently about bitmap
data anyway, e.g. to better support HDR in the future. However, such
changes would be more involved than just unifying the naming as done
here. So I considered that out of scope for now.
From what I can tell BMP files with an alpha channel always store
unpremultiplied alpha. So let's load them as such to avoid rendering
artifacts from using the wrong alpha type.
We don't discern between opaque and non-opaque alpha types in LibGfx,
which at some point we might need to do. But for now, assume all opaque
Skia surfaces have premultiplied alpha.
Fixes#6892.
Previously when launching a UI process and/or a WebContent process on
Windows, the following message would be output to the console:
Fontconfig error: Cannot load default config file: No such file: (null)
Apparently on Windows, you have to provide a font .conf file to
fontconfig explicitly. Since we are not doing that, the default fonts
that are backed off to are not ideal.
Similar to how we aren't using fontconfig on Android, Windows also has
native font infrastructure in terms of both a collection of System
installed fonts as well as skia support for font managers that use
native Windows APIs. With that, we can remove the usage of fontconfig
entirely and improve the fonts used on websites like ladybird.org or
google.com.
This changes Gfx::ScalingMode to reflect the three modes of scaling we
support using Skia, which makes it a bit easier to reason about the mode
to select. New is ::BilinearMipmap, which uses linear interpolation
between mipmap levels to produce higher quality downscaled images.
The cubic resampling options Mitchell and its sibling CatmullRom both
produced weird artifacts or resulted in a worse quality than
BilinearMipmap when downscaling. We might not have been using these
correctly, but the new ::BilinearMipmap method seems to mirror what
Chrome uses for downscaled images.
This fixes an issue where having an emoji font first in the font-family
cascade list would cause us to get the space width from the emoji font
as well.
We now look at adjacent text chunks when deciding which font to use for
space widths, instead of just blindly obeying the font-family value.