mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-24 18:32:28 -05:00
LibAccelGfx+LibWeb: Move glyph atlas into a singleton class
This is going to allow us reuse glyph texture across painters and page repaints.
This commit is contained in:
parent
4b23046a22
commit
28723d8be1
6 changed files with 157 additions and 105 deletions
|
@ -3,6 +3,7 @@ include(accelerated_graphics)
|
||||||
if (HAS_ACCELERATED_GRAPHICS)
|
if (HAS_ACCELERATED_GRAPHICS)
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
GL.cpp
|
GL.cpp
|
||||||
|
GlyphAtlas.cpp
|
||||||
Context.cpp
|
Context.cpp
|
||||||
Painter.cpp
|
Painter.cpp
|
||||||
Program.cpp
|
Program.cpp
|
||||||
|
|
81
Userland/Libraries/LibAccelGfx/GlyphAtlas.cpp
Normal file
81
Userland/Libraries/LibAccelGfx/GlyphAtlas.cpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AK/QuickSort.h>
|
||||||
|
#include <LibAccelGfx/GlyphAtlas.h>
|
||||||
|
#include <LibGfx/Painter.h>
|
||||||
|
|
||||||
|
namespace AccelGfx {
|
||||||
|
|
||||||
|
GlyphAtlas& GlyphAtlas::the()
|
||||||
|
{
|
||||||
|
static OwnPtr<GlyphAtlas> s_the;
|
||||||
|
if (!s_the)
|
||||||
|
s_the = make<GlyphAtlas>();
|
||||||
|
return *s_the;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlyphAtlas::update(HashMap<Gfx::Font const*, HashTable<u32>> const& unique_glyphs)
|
||||||
|
{
|
||||||
|
HashMap<GlyphsTextureKey, NonnullRefPtr<Gfx::Bitmap>> glyph_bitmaps;
|
||||||
|
for (auto const& [font, code_points] : unique_glyphs) {
|
||||||
|
for (auto const& code_point : code_points) {
|
||||||
|
auto glyph = font->glyph(code_point);
|
||||||
|
if (glyph.bitmap()) {
|
||||||
|
auto atlas_key = GlyphsTextureKey { font, code_point };
|
||||||
|
glyph_bitmaps.set(atlas_key, *glyph.bitmap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glyph_bitmaps.is_empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vector<GlyphsTextureKey> glyphs_sorted_by_height;
|
||||||
|
glyphs_sorted_by_height.ensure_capacity(glyph_bitmaps.size());
|
||||||
|
for (auto const& [atlas_key, bitmap] : glyph_bitmaps) {
|
||||||
|
glyphs_sorted_by_height.append(atlas_key);
|
||||||
|
}
|
||||||
|
quick_sort(glyphs_sorted_by_height, [&](auto const& a, auto const& b) {
|
||||||
|
auto const& bitmap_a = *glyph_bitmaps.get(a);
|
||||||
|
auto const& bitmap_b = *glyph_bitmaps.get(b);
|
||||||
|
return bitmap_a->height() > bitmap_b->height();
|
||||||
|
});
|
||||||
|
|
||||||
|
int current_x = 0;
|
||||||
|
int current_y = 0;
|
||||||
|
int row_height = 0;
|
||||||
|
int const texture_width = 512;
|
||||||
|
int const padding = 1;
|
||||||
|
for (auto const& glyphs_texture_key : glyphs_sorted_by_height) {
|
||||||
|
auto const& bitmap = *glyph_bitmaps.get(glyphs_texture_key);
|
||||||
|
if (current_x + bitmap->width() > texture_width) {
|
||||||
|
current_x = 0;
|
||||||
|
current_y += row_height + padding;
|
||||||
|
row_height = 0;
|
||||||
|
}
|
||||||
|
m_glyphs_texture_map.set(glyphs_texture_key, { current_x, current_y, bitmap->width(), bitmap->height() });
|
||||||
|
current_x += bitmap->width() + padding;
|
||||||
|
row_height = max(row_height, bitmap->height());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto glyphs_texture_bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { texture_width, current_y + row_height }));
|
||||||
|
auto glyphs_texture_painter = Gfx::Painter(*glyphs_texture_bitmap);
|
||||||
|
for (auto const& [glyphs_texture_key, glyph_bitmap] : glyph_bitmaps) {
|
||||||
|
auto rect = m_glyphs_texture_map.get(glyphs_texture_key).value();
|
||||||
|
glyphs_texture_painter.blit({ rect.x(), rect.y() }, glyph_bitmap, glyph_bitmap->rect());
|
||||||
|
}
|
||||||
|
|
||||||
|
GL::upload_texture_data(m_texture, *glyphs_texture_bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<Gfx::IntRect> GlyphAtlas::get_glyph_rect(Gfx::Font const* font, u32 code_point) const
|
||||||
|
{
|
||||||
|
auto atlas_key = GlyphsTextureKey { font, code_point };
|
||||||
|
return m_glyphs_texture_map.get(atlas_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
64
Userland/Libraries/LibAccelGfx/GlyphAtlas.h
Normal file
64
Userland/Libraries/LibAccelGfx/GlyphAtlas.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/HashMap.h>
|
||||||
|
#include <AK/Noncopyable.h>
|
||||||
|
#include <LibAccelGfx/GL.h>
|
||||||
|
#include <LibGfx/Font/Font.h>
|
||||||
|
|
||||||
|
namespace AccelGfx {
|
||||||
|
|
||||||
|
class GlyphAtlas {
|
||||||
|
AK_MAKE_NONCOPYABLE(GlyphAtlas);
|
||||||
|
|
||||||
|
public:
|
||||||
|
GlyphAtlas()
|
||||||
|
: m_texture(GL::create_texture())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~GlyphAtlas()
|
||||||
|
{
|
||||||
|
GL::delete_texture(m_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GlyphAtlas& the();
|
||||||
|
|
||||||
|
struct GlyphsTextureKey {
|
||||||
|
Gfx::Font const* font;
|
||||||
|
u32 code_point;
|
||||||
|
|
||||||
|
bool operator==(GlyphsTextureKey const& other) const
|
||||||
|
{
|
||||||
|
return font == other.font && code_point == other.code_point;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void update(HashMap<Gfx::Font const*, HashTable<u32>> const& unique_glyphs);
|
||||||
|
Optional<Gfx::IntRect> get_glyph_rect(Gfx::Font const*, u32 code_point) const;
|
||||||
|
|
||||||
|
GL::Texture const& texture() const { return m_texture; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
GL::Texture m_texture;
|
||||||
|
HashMap<GlyphsTextureKey, Gfx::IntRect> m_glyphs_texture_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace AK {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Traits<AccelGfx::GlyphAtlas::GlyphsTextureKey> : public DefaultTraits<AccelGfx::GlyphAtlas::GlyphsTextureKey> {
|
||||||
|
static unsigned hash(AccelGfx::GlyphAtlas::GlyphsTextureKey const& key)
|
||||||
|
{
|
||||||
|
return pair_int_hash(ptr_hash(key.font), key.code_point);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -5,10 +5,8 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/QuickSort.h>
|
|
||||||
#include <LibAccelGfx/GL.h>
|
#include <LibAccelGfx/GL.h>
|
||||||
#include <LibAccelGfx/Painter.h>
|
#include <LibAccelGfx/Painter.h>
|
||||||
#include <LibGfx/Color.h>
|
|
||||||
#include <LibGfx/ImmutableBitmap.h>
|
#include <LibGfx/ImmutableBitmap.h>
|
||||||
#include <LibGfx/Painter.h>
|
#include <LibGfx/Painter.h>
|
||||||
|
|
||||||
|
@ -145,23 +143,12 @@ OwnPtr<Painter> Painter::create()
|
||||||
return make<Painter>(context);
|
return make<Painter>(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
OwnPtr<Painter> Painter::create_with_glyphs_texture_from_painter(Painter const& painter)
|
|
||||||
{
|
|
||||||
auto& context = Context::the();
|
|
||||||
auto glyphs_texture_painter = make<Painter>(context);
|
|
||||||
glyphs_texture_painter->m_glyphs_texture = painter.m_glyphs_texture;
|
|
||||||
glyphs_texture_painter->m_glyphs_texture_size = painter.m_glyphs_texture_size;
|
|
||||||
glyphs_texture_painter->m_glyphs_texture_map = painter.m_glyphs_texture_map;
|
|
||||||
return glyphs_texture_painter;
|
|
||||||
}
|
|
||||||
|
|
||||||
Painter::Painter(Context& context)
|
Painter::Painter(Context& context)
|
||||||
: m_context(context)
|
: m_context(context)
|
||||||
, m_rectangle_program(Program::create(Program::Name::RectangleProgram, vertex_shader_source, solid_color_fragment_shader_source))
|
, m_rectangle_program(Program::create(Program::Name::RectangleProgram, vertex_shader_source, solid_color_fragment_shader_source))
|
||||||
, m_rounded_rectangle_program(Program::create(Program::Name::RoundedRectangleProgram, vertex_shader_source, rect_with_rounded_corners_fragment_shader_source))
|
, m_rounded_rectangle_program(Program::create(Program::Name::RoundedRectangleProgram, vertex_shader_source, rect_with_rounded_corners_fragment_shader_source))
|
||||||
, m_blit_program(Program::create(Program::Name::BlitProgram, blit_vertex_shader_source, blit_fragment_shader_source))
|
, m_blit_program(Program::create(Program::Name::BlitProgram, blit_vertex_shader_source, blit_fragment_shader_source))
|
||||||
, m_linear_gradient_program(Program::create(Program::Name::LinearGradientProgram, linear_gradient_vertex_shader_source, linear_gradient_fragment_shader_source))
|
, m_linear_gradient_program(Program::create(Program::Name::LinearGradientProgram, linear_gradient_vertex_shader_source, linear_gradient_fragment_shader_source))
|
||||||
, m_glyphs_texture(GL::create_texture())
|
|
||||||
{
|
{
|
||||||
m_state_stack.empend(State());
|
m_state_stack.empend(State());
|
||||||
}
|
}
|
||||||
|
@ -365,62 +352,6 @@ void Painter::draw_scaled_bitmap(Gfx::FloatRect const& dst_rect, Gfx::Bitmap con
|
||||||
GL::delete_texture(texture);
|
GL::delete_texture(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Painter::prepare_glyph_texture(HashMap<Gfx::Font const*, HashTable<u32>> const& unique_glyphs)
|
|
||||||
{
|
|
||||||
HashMap<GlyphsTextureKey, NonnullRefPtr<Gfx::Bitmap>> glyph_bitmaps;
|
|
||||||
for (auto const& [font, code_points] : unique_glyphs) {
|
|
||||||
for (auto const& code_point : code_points) {
|
|
||||||
auto glyph = font->glyph(code_point);
|
|
||||||
if (glyph.bitmap()) {
|
|
||||||
auto atlas_key = GlyphsTextureKey { font, code_point };
|
|
||||||
glyph_bitmaps.set(atlas_key, *glyph.bitmap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glyph_bitmaps.is_empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Vector<GlyphsTextureKey> glyphs_sorted_by_height;
|
|
||||||
glyphs_sorted_by_height.ensure_capacity(glyph_bitmaps.size());
|
|
||||||
for (auto const& [atlas_key, bitmap] : glyph_bitmaps) {
|
|
||||||
glyphs_sorted_by_height.append(atlas_key);
|
|
||||||
}
|
|
||||||
quick_sort(glyphs_sorted_by_height, [&](auto const& a, auto const& b) {
|
|
||||||
auto const& bitmap_a = *glyph_bitmaps.get(a);
|
|
||||||
auto const& bitmap_b = *glyph_bitmaps.get(b);
|
|
||||||
return bitmap_a->height() > bitmap_b->height();
|
|
||||||
});
|
|
||||||
|
|
||||||
int current_x = 0;
|
|
||||||
int current_y = 0;
|
|
||||||
int row_height = 0;
|
|
||||||
int texture_width = 512;
|
|
||||||
int padding = 1;
|
|
||||||
for (auto const& glyphs_texture_key : glyphs_sorted_by_height) {
|
|
||||||
auto const& bitmap = *glyph_bitmaps.get(glyphs_texture_key);
|
|
||||||
if (current_x + bitmap->width() > texture_width) {
|
|
||||||
current_x = 0;
|
|
||||||
current_y += row_height + padding;
|
|
||||||
row_height = 0;
|
|
||||||
}
|
|
||||||
m_glyphs_texture_map.set(glyphs_texture_key, { current_x, current_y, bitmap->width(), bitmap->height() });
|
|
||||||
current_x += bitmap->width() + padding;
|
|
||||||
row_height = max(row_height, bitmap->height());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto glyphs_texture_bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { texture_width, current_y + row_height }));
|
|
||||||
auto glyphs_texure_painter = Gfx::Painter(*glyphs_texture_bitmap);
|
|
||||||
for (auto const& [glyphs_texture_key, glyph_bitmap] : glyph_bitmaps) {
|
|
||||||
auto rect = m_glyphs_texture_map.get(glyphs_texture_key).value();
|
|
||||||
glyphs_texure_painter.blit({ rect.x(), rect.y() }, glyph_bitmap, glyph_bitmap->rect());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_glyphs_texture_size = glyphs_texture_bitmap->size();
|
|
||||||
|
|
||||||
GL::upload_texture_data(m_glyphs_texture, *glyphs_texture_bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Painter::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color)
|
void Painter::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color)
|
||||||
{
|
{
|
||||||
bind_target_canvas();
|
bind_target_canvas();
|
||||||
|
@ -428,20 +359,22 @@ void Painter::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Col
|
||||||
Vector<GLfloat> vertices;
|
Vector<GLfloat> vertices;
|
||||||
vertices.ensure_capacity(glyph_run.size() * 24);
|
vertices.ensure_capacity(glyph_run.size() * 24);
|
||||||
|
|
||||||
for (auto& glyph_or_emoji : glyph_run) {
|
auto const& glyph_atlas = GlyphAtlas::the();
|
||||||
|
|
||||||
|
for (auto const& glyph_or_emoji : glyph_run) {
|
||||||
if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
|
if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
|
||||||
auto& glyph = glyph_or_emoji.get<Gfx::DrawGlyph>();
|
auto const& glyph = glyph_or_emoji.get<Gfx::DrawGlyph>();
|
||||||
|
|
||||||
auto const* font = glyph.font;
|
auto const* font = glyph.font;
|
||||||
auto code_point = glyph.code_point;
|
auto code_point = glyph.code_point;
|
||||||
auto point = glyph.position;
|
auto point = glyph.position;
|
||||||
|
|
||||||
auto maybe_texture_rect = m_glyphs_texture_map.get(GlyphsTextureKey { font, code_point });
|
auto maybe_texture_rect = glyph_atlas.get_glyph_rect(font, code_point);
|
||||||
if (!maybe_texture_rect.has_value()) {
|
if (!maybe_texture_rect.has_value()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto texture_rect = to_texture_space(maybe_texture_rect.value().to_type<float>(), m_glyphs_texture_size);
|
auto texture_rect = to_texture_space(maybe_texture_rect.value().to_type<float>(), *glyph_atlas.texture().size);
|
||||||
|
|
||||||
auto glyph_position = point + Gfx::FloatPoint(font->glyph_left_bearing(code_point), 0);
|
auto glyph_position = point + Gfx::FloatPoint(font->glyph_left_bearing(code_point), 0);
|
||||||
auto glyph_size = maybe_texture_rect->size().to_type<float>();
|
auto glyph_size = maybe_texture_rect->size().to_type<float>();
|
||||||
|
@ -497,7 +430,7 @@ void Painter::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Col
|
||||||
|
|
||||||
m_blit_program.use();
|
m_blit_program.use();
|
||||||
|
|
||||||
GL::bind_texture(m_glyphs_texture);
|
GL::bind_texture(glyph_atlas.texture());
|
||||||
GL::set_texture_scale_mode(GL::ScalingMode::Nearest);
|
GL::set_texture_scale_mode(GL::ScalingMode::Nearest);
|
||||||
|
|
||||||
auto position_attribute = m_blit_program.get_attribute_location("aVertexPosition");
|
auto position_attribute = m_blit_program.get_attribute_location("aVertexPosition");
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <LibAccelGfx/Context.h>
|
#include <LibAccelGfx/Context.h>
|
||||||
#include <LibAccelGfx/Forward.h>
|
#include <LibAccelGfx/Forward.h>
|
||||||
#include <LibAccelGfx/GL.h>
|
#include <LibAccelGfx/GL.h>
|
||||||
|
#include <LibAccelGfx/GlyphAtlas.h>
|
||||||
#include <LibAccelGfx/Program.h>
|
#include <LibAccelGfx/Program.h>
|
||||||
#include <LibGfx/AffineTransform.h>
|
#include <LibGfx/AffineTransform.h>
|
||||||
#include <LibGfx/Font/Font.h>
|
#include <LibGfx/Font/Font.h>
|
||||||
|
@ -29,7 +30,6 @@ class Painter {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static OwnPtr<Painter> create();
|
static OwnPtr<Painter> create();
|
||||||
static OwnPtr<Painter> create_with_glyphs_texture_from_painter(Painter const& painter);
|
|
||||||
|
|
||||||
Painter(Context&);
|
Painter(Context&);
|
||||||
~Painter();
|
~Painter();
|
||||||
|
@ -60,18 +60,6 @@ public:
|
||||||
void draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::IntRect const& src_rect, ScalingMode = ScalingMode::NearestNeighbor);
|
void draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::IntRect const& src_rect, ScalingMode = ScalingMode::NearestNeighbor);
|
||||||
void draw_scaled_immutable_bitmap(Gfx::FloatRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::FloatRect const& src_rect, ScalingMode = ScalingMode::NearestNeighbor);
|
void draw_scaled_immutable_bitmap(Gfx::FloatRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::FloatRect const& src_rect, ScalingMode = ScalingMode::NearestNeighbor);
|
||||||
|
|
||||||
void prepare_glyph_texture(HashMap<Gfx::Font const*, HashTable<u32>> const& unique_glyphs);
|
|
||||||
|
|
||||||
struct GlyphsTextureKey {
|
|
||||||
Gfx::Font const* font;
|
|
||||||
u32 code_point;
|
|
||||||
|
|
||||||
bool operator==(GlyphsTextureKey const& other) const
|
|
||||||
{
|
|
||||||
return font == other.font && code_point == other.code_point;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color);
|
void draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color);
|
||||||
|
|
||||||
void set_clip_rect(Gfx::IntRect);
|
void set_clip_rect(Gfx::IntRect);
|
||||||
|
@ -118,22 +106,6 @@ private:
|
||||||
Program m_rounded_rectangle_program;
|
Program m_rounded_rectangle_program;
|
||||||
Program m_blit_program;
|
Program m_blit_program;
|
||||||
Program m_linear_gradient_program;
|
Program m_linear_gradient_program;
|
||||||
|
|
||||||
HashMap<GlyphsTextureKey, Gfx::IntRect> m_glyphs_texture_map;
|
|
||||||
Gfx::IntSize m_glyphs_texture_size;
|
|
||||||
GL::Texture m_glyphs_texture;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace AK {
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Traits<AccelGfx::Painter::GlyphsTextureKey> : public DefaultTraits<AccelGfx::Painter::GlyphsTextureKey> {
|
|
||||||
static unsigned hash(AccelGfx::Painter::GlyphsTextureKey const& key)
|
|
||||||
{
|
|
||||||
return pair_int_hash(ptr_hash(key.font), key.code_point);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibAccelGfx/GlyphAtlas.h>
|
||||||
#include <LibWeb/Painting/PaintingCommandExecutorGPU.h>
|
#include <LibWeb/Painting/PaintingCommandExecutorGPU.h>
|
||||||
|
|
||||||
namespace Web::Painting {
|
namespace Web::Painting {
|
||||||
|
@ -92,7 +93,7 @@ CommandResult PaintingCommandExecutorGPU::set_font(Gfx::Font const&)
|
||||||
CommandResult PaintingCommandExecutorGPU::push_stacking_context(float opacity, bool, Gfx::IntRect const& source_paintable_rect, Gfx::IntPoint post_transform_translation, CSS::ImageRendering, StackingContextTransform, Optional<StackingContextMask>)
|
CommandResult PaintingCommandExecutorGPU::push_stacking_context(float opacity, bool, Gfx::IntRect const& source_paintable_rect, Gfx::IntPoint post_transform_translation, CSS::ImageRendering, StackingContextTransform, Optional<StackingContextMask>)
|
||||||
{
|
{
|
||||||
if (opacity < 1) {
|
if (opacity < 1) {
|
||||||
auto painter = AccelGfx::Painter::create_with_glyphs_texture_from_painter(this->painter());
|
auto painter = AccelGfx::Painter::create();
|
||||||
auto canvas = AccelGfx::Canvas::create(source_paintable_rect.size());
|
auto canvas = AccelGfx::Canvas::create(source_paintable_rect.size());
|
||||||
painter->set_target_canvas(canvas);
|
painter->set_target_canvas(canvas);
|
||||||
painter->translate(-source_paintable_rect.location().to_type<float>());
|
painter->translate(-source_paintable_rect.location().to_type<float>());
|
||||||
|
@ -313,7 +314,7 @@ bool PaintingCommandExecutorGPU::would_be_fully_clipped_by_painter(Gfx::IntRect)
|
||||||
|
|
||||||
void PaintingCommandExecutorGPU::prepare_glyph_texture(HashMap<Gfx::Font const*, HashTable<u32>> const& unique_glyphs)
|
void PaintingCommandExecutorGPU::prepare_glyph_texture(HashMap<Gfx::Font const*, HashTable<u32>> const& unique_glyphs)
|
||||||
{
|
{
|
||||||
painter().prepare_glyph_texture(unique_glyphs);
|
AccelGfx::GlyphAtlas::the().update(unique_glyphs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintingCommandExecutorGPU::update_immutable_bitmap_texture_cache(HashMap<u32, Gfx::ImmutableBitmap const*>& immutable_bitmaps)
|
void PaintingCommandExecutorGPU::update_immutable_bitmap_texture_cache(HashMap<u32, Gfx::ImmutableBitmap const*>& immutable_bitmaps)
|
||||||
|
|
Loading…
Add table
Reference in a new issue