In the upcoming changes, the AccelGfx context will be used for WebGL, so
we can no longer assume that the WebContent process has a single global
context.
It is implemented in the way identical to how it works in CPU painter:
1. SampleUnderCorners command saves pixels within corners into a
texture.
2. BlitCornerClipping command uses the texture prepared earlier to
restore pixels within corners.
Let's not assume there is one global OpenGL context because it might
change once we will start creating >1 page inside single WebContent
process or contexts for WebGL.
This change ensures that the GPU painting executor follows the pattern
of the CPU executor, where the state is stored for each stacking
context, but a painter is created only for those with opacity.
Fixes crashing on apple.com because now save() and restore() are called
on correct painters.
Before this change, every repaint required a glyph atlas update, which
took 10-20% of the total painting time according to my testing on
different websites. This change improves that significantly by skipping
atlas updated when all glyphs are already present in the texture.
This change introduces a texture cache for immutable bitmaps in the
GPU painter. The cache is persisted across page repaints, so now, on
page scroll repaint, in many cases, we won't need to upload any new
textures. Also, if the same image is painted more than once on a page,
its texture will only be uploaded once.
Generally, the GPU painter works much faster with this change on all
pages that have images.
For each stacking context with an opacity less than 1, we create a
separate framebuffer. We then blit the texture attached to this
framebuffer with the specified opacity.
To avoid the performance overhead of reading pixels from the texture
into Gfx::Bitmap, a new method that allows for direct blitting from
the texture is introduced, named blit_scaled_texture().
Linear gradient painting is implemented in the following way:
1. The rectangle is divided into segments where each segment represents
a simple linear gradient between an adjacent pair of stops.
2. Each quad is filled separately using a fragment shader that
interpolates between two colors.
For now `angle` and `repeat_length` parameters are ignored.
With these changes it is now possible to create OpenGL context on macOS
and run GPU-painter. For now only QT client has a CLI param that turns
it on though.
Framebuffer object is allocated using OpenGL's API and is not platform
specific which means it could be used on both macOS and Linux unlike
EGL specific PBuffer.
Before, we were using a feature of OpenGL that allows specifying a
pointer to allocated vertex data without creating VBO and VAO, but as
I found out, it does not work on macOS.
This change introduces GL.h with error check wrappers for all the
OpenGL functions we used so far.
For now, the error check is simply:
`VERIFY(glGetError() == GL_NO_ERROR);`
but that is better than continuing execution after encounting an error.
Text painting operates in two steps:
1. Preparation of a texture that contains all the glyphs required for
text painting, along with metadata that describes the locations of
those glyphs within texture beforehand.
2. Blitting glyphs from the prepared texture onto corresponding glyph
quads.
Users of LibAccelGfx will need to call `prepare_glyphs_texture()`,
passing a set of all unique (font, code_paint) pairs, before painting
any text.
In the upcoming changes, Painter will be used to store the state of
OpenGL context. For example, if Painter is aware of the shader that
have already been loaded, it will be possible to reuse them across
repaints. Also, it would be possible to manage state of loaded textures
and add/remove them depending on which ones are present in the next
sequence of painting commands.
This change introduces a new 2D graphics library that uses OpenGL to
perform painting operations. For now, it has extremely limited
functionality and supports only rectangle painting, but we have to
start somewhere.
Since this library is intended to be used by LibWeb, where the
WebContent process does not have an associated window, painting occurs
in an offscreen buffer created using EGL.
For now it is only possible to compile this library on linux.
Offscreen context creation on SerenityOS and MacOS will have to be
implemented separately in the future.
Co-Authored-By: Andreas Kling <awesomekling@gmail.com>