9 Commits ec590ef3e6 ... 12a2aebeb6

Tác giả SHA1 Thông báo Ngày
  Aliaksandr Kalenik 12a2aebeb6 LibWeb: Move painting surface allocation into rendering thread 1 tuần trước cách đây
  Andreas Kling 3169747989 LibJS: Emit PutById instead of PutByValue when key is string literal 1 tuần trước cách đây
  Andreas Kling 4426c50a18 LibJS: Emit GetById instead of GetByValue when key is string literal 1 tuần trước cách đây
  Andreas Kling 976ccb9224 LibJS: Add fast path for Int32 values in ToBoolean 1 tuần trước cách đây
  Andreas Kling 8de03e8cfd LibJS: Add fast paths in ToNumeric for booleans, null and undefined 1 tuần trước cách đây
  Andrew Kaster 3fcef0c519 Revert "CI: Temporarily install CMake 3.x" 1 tuần trước cách đây
  Andrew Kaster 20352cc05b Meta: Update vcpkg to latest main revision 1 tuần trước cách đây
  Andrew Kaster 91c1aed57f Revert "Meta: Add workaround for CMake 4.0 policy minimum changes" 1 tuần trước cách đây
  Andreas Kling cba80580e2 Revert "LibJS: Avoid calling generic Instruction::length() during dispatch" 1 tuần trước cách đây

+ 1 - 29
.github/actions/setup/action.yml

@@ -31,7 +31,7 @@ runs:
         sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
 
         sudo apt-get update -y
-        sudo apt-get install -y autoconf autoconf-archive automake build-essential ccache clang-19 clang++-19 curl fonts-liberation2 \
+        sudo apt-get install -y autoconf autoconf-archive automake build-essential ccache clang-19 clang++-19 cmake curl fonts-liberation2 \
             gcc-13 g++-13 libegl1-mesa-dev libgl1-mesa-dev libpulse-dev libssl-dev \
             libstdc++-13-dev lld-19 nasm ninja-build qt6-base-dev qt6-tools-dev-tools tar unzip zip
 
@@ -61,34 +61,6 @@ runs:
         brew update
         brew install autoconf autoconf-archive automake bash ccache coreutils llvm@19 nasm ninja qt unzip wabt
 
-    # FIXME: GitHub Actions now bundles CMake 4.0, which breaks many vcpkg dependencies. See:
-    #        https://github.com/microsoft/vcpkg/issues/44726
-    - name: 'Install CMake 3.x'
-      shell: bash
-      run: |
-        set -e
-
-        if ${{ inputs.os == 'Linux' }} ; then
-          cmake_os="linux"
-          cmake_bin="bin"
-
-          if ${{ inputs.arch == 'x86_64' }} ; then
-            cmake_arch="x86_64"
-          elif ${{ inputs.arch == 'arm64' }} ; then
-            cmake_arch="aarch64"
-          fi
-        elif ${{ inputs.os == 'macOS' || inputs.os == 'Android' }} ; then
-          cmake_os="macos"
-          cmake_arch="universal"
-          cmake_bin="CMake.app/Contents/bin"
-        fi
-
-        wget https://github.com/Kitware/CMake/releases/download/v3.31.6/cmake-3.31.6-${cmake_os}-${cmake_arch}.tar.gz
-        tar -xzf ./cmake-3.31.6-${cmake_os}-${cmake_arch}.tar.gz
-        rm ./cmake-3.31.6-${cmake_os}-${cmake_arch}.tar.gz
-
-        echo "${{ github.workspace }}/cmake-3.31.6-${cmake_os}-${cmake_arch}/${cmake_bin}" >> $GITHUB_PATH
-
     - name: 'Set required environment variables'
       if: ${{ inputs.os == 'Linux' && inputs.arch == 'arm64' }}
       uses: actions/github-script@v7

+ 2 - 2
Libraries/LibGfx/SkiaBackendContext.h

@@ -6,8 +6,8 @@
 
 #pragma once
 
+#include <AK/AtomicRefCounted.h>
 #include <AK/Noncopyable.h>
-#include <AK/RefCounted.h>
 #include <LibThreading/Mutex.h>
 
 #ifdef USE_VULKAN
@@ -25,7 +25,7 @@ namespace Gfx {
 
 class MetalContext;
 
-class SkiaBackendContext : public RefCounted<SkiaBackendContext> {
+class SkiaBackendContext : public AtomicRefCounted<SkiaBackendContext> {
     AK_MAKE_NONCOPYABLE(SkiaBackendContext);
     AK_MAKE_NONMOVABLE(SkiaBackendContext);
 

+ 7 - 7
Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -625,9 +625,9 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> AssignmentExpression::g
 
                     if (expression.is_computed()) {
                         if (!lhs_is_super_expression)
-                            generator.emit<Bytecode::Op::PutByValue>(*base, *computed_property, rval, Bytecode::Op::PropertyKind::KeyValue, move(base_identifier));
+                            generator.emit_put_by_value(*base, *computed_property, rval, Bytecode::Op::PropertyKind::KeyValue, move(base_identifier));
                         else
-                            generator.emit<Bytecode::Op::PutByValueWithThis>(*base, *computed_property, *this_value, rval);
+                            generator.emit_put_by_value_with_this(*base, *computed_property, *this_value, rval, Op::PropertyKind::KeyValue);
                     } else if (expression.property().is_identifier()) {
                         auto identifier_table_ref = generator.intern_identifier(as<Identifier>(expression.property()).string());
                         if (!lhs_is_super_expression)
@@ -1180,7 +1180,7 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> ObjectExpression::gener
             auto property_name = TRY(property->key().generate_bytecode(generator)).value();
             auto value = TRY(property->value().generate_bytecode(generator)).value();
 
-            generator.emit<Bytecode::Op::PutByValue>(object, property_name, value, property_kind);
+            generator.emit_put_by_value(object, property_name, value, property_kind, {});
         }
     }
 
@@ -1349,7 +1349,7 @@ static Bytecode::CodeGenerationErrorOr<void> generate_object_binding_pattern_byt
                 excluded_property_names.append(excluded_name);
             }
 
-            generator.emit<Bytecode::Op::GetByValue>(value, object, property_name);
+            generator.emit_get_by_value(value, object, property_name);
         }
 
         if (initializer) {
@@ -1683,7 +1683,7 @@ static Bytecode::CodeGenerationErrorOr<BaseAndValue> get_base_and_value_from_mem
         if (computed_property.has_value()) {
             // 5. Let propertyKey be ? ToPropertyKey(propertyNameValue).
             // FIXME: This does ToPropertyKey out of order, which is observable by Symbol.toPrimitive!
-            generator.emit<Bytecode::Op::GetByValueWithThis>(value, super_base, *computed_property, this_value);
+            generator.emit_get_by_value_with_this(value, super_base, *computed_property, this_value);
         } else {
             // 3. Let propertyKey be StringValue of IdentifierName.
             auto identifier_table_ref = generator.intern_identifier(as<Identifier>(member_expression.property()).string());
@@ -1697,7 +1697,7 @@ static Bytecode::CodeGenerationErrorOr<BaseAndValue> get_base_and_value_from_mem
     auto value = generator.allocate_register();
     if (member_expression.is_computed()) {
         auto property = TRY(member_expression.property().generate_bytecode(generator)).value();
-        generator.emit<Bytecode::Op::GetByValue>(value, base, property);
+        generator.emit_get_by_value(value, base, property);
     } else if (is<PrivateIdentifier>(member_expression.property())) {
         generator.emit<Bytecode::Op::GetPrivateById>(
             value,
@@ -3482,7 +3482,7 @@ static Bytecode::CodeGenerationErrorOr<void> generate_optional_chain(Bytecode::G
             [&](OptionalChain::ComputedReference const& ref) -> Bytecode::CodeGenerationErrorOr<void> {
                 generator.emit_mov(current_base, current_value);
                 auto property = TRY(ref.expression->generate_bytecode(generator)).value();
-                generator.emit<Bytecode::Op::GetByValue>(current_value, current_value, property);
+                generator.emit_get_by_value(current_value, current_value, property);
                 return {};
             },
             [&](OptionalChain::MemberReference const& ref) -> Bytecode::CodeGenerationErrorOr<void> {

+ 54 - 6
Libraries/LibJS/Bytecode/Generator.cpp

@@ -687,7 +687,7 @@ CodeGenerationErrorOr<Generator::ReferenceOperands> Generator::emit_load_from_re
         if (super_reference.referenced_name.has_value()) {
             // 5. Let propertyKey be ? ToPropertyKey(propertyNameValue).
             // FIXME: This does ToPropertyKey out of order, which is observable by Symbol.toPrimitive!
-            emit<Bytecode::Op::GetByValueWithThis>(dst, *super_reference.base, *super_reference.referenced_name, *super_reference.this_value);
+            emit_get_by_value_with_this(dst, *super_reference.base, *super_reference.referenced_name, *super_reference.this_value);
         } else {
             // 3. Let propertyKey be StringValue of IdentifierName.
             auto identifier_table_ref = intern_identifier(as<Identifier>(expression.property()).string());
@@ -706,7 +706,7 @@ CodeGenerationErrorOr<Generator::ReferenceOperands> Generator::emit_load_from_re
         auto saved_property = allocate_register();
         emit<Bytecode::Op::Mov>(saved_property, property);
         auto dst = preferred_dst.has_value() ? preferred_dst.value() : allocate_register();
-        emit<Bytecode::Op::GetByValue>(dst, base, property, move(base_identifier));
+        emit_get_by_value(dst, base, property, move(base_identifier));
         return ReferenceOperands {
             .base = base,
             .referenced_name = saved_property,
@@ -760,7 +760,7 @@ CodeGenerationErrorOr<void> Generator::emit_store_to_reference(JS::ASTNode const
             if (super_reference.referenced_name.has_value()) {
                 // 5. Let propertyKey be ? ToPropertyKey(propertyNameValue).
                 // FIXME: This does ToPropertyKey out of order, which is observable by Symbol.toPrimitive!
-                emit<Bytecode::Op::PutByValueWithThis>(*super_reference.base, *super_reference.referenced_name, *super_reference.this_value, value);
+                emit_put_by_value_with_this(*super_reference.base, *super_reference.referenced_name, *super_reference.this_value, value, Op::PropertyKind::KeyValue);
             } else {
                 // 3. Let propertyKey be StringValue of IdentifierName.
                 auto identifier_table_ref = intern_identifier(as<Identifier>(expression.property()).string());
@@ -771,7 +771,7 @@ CodeGenerationErrorOr<void> Generator::emit_store_to_reference(JS::ASTNode const
 
             if (expression.is_computed()) {
                 auto property = TRY(expression.property().generate_bytecode(*this)).value();
-                emit<Bytecode::Op::PutByValue>(object, property, value);
+                emit_put_by_value(object, property, value, Op::PropertyKind::KeyValue, {});
             } else if (expression.property().is_identifier()) {
                 auto identifier_table_ref = intern_identifier(as<Identifier>(expression.property()).string());
                 emit<Bytecode::Op::PutById>(object, identifier_table_ref, value, Bytecode::Op::PropertyKind::KeyValue, next_property_lookup_cache());
@@ -809,9 +809,9 @@ CodeGenerationErrorOr<void> Generator::emit_store_to_reference(ReferenceOperands
         return {};
     }
     if (reference.base == reference.this_value)
-        emit<Bytecode::Op::PutByValue>(*reference.base, *reference.referenced_name, value);
+        emit_put_by_value(*reference.base, *reference.referenced_name, value, Op::PropertyKind::KeyValue, {});
     else
-        emit<Bytecode::Op::PutByValueWithThis>(*reference.base, *reference.referenced_name, *reference.this_value, value);
+        emit_put_by_value_with_this(*reference.base, *reference.referenced_name, *reference.this_value, value, Op::PropertyKind::KeyValue);
     return {};
 }
 
@@ -1122,6 +1122,54 @@ void Generator::emit_get_by_id_with_this(ScopedOperand dst, ScopedOperand base,
     emit<Op::GetByIdWithThis>(dst, base, id, this_value, m_next_property_lookup_cache++);
 }
 
+void Generator::emit_get_by_value(ScopedOperand dst, ScopedOperand base, ScopedOperand property, Optional<IdentifierTableIndex> base_identifier)
+{
+    if (property.operand().is_constant() && get_constant(property).is_string()) {
+        auto property_key = MUST(get_constant(property).to_property_key(vm()));
+        if (property_key.is_string()) {
+            emit_get_by_id(dst, base, intern_identifier(property_key.as_string()), base_identifier);
+            return;
+        }
+    }
+    emit<Op::GetByValue>(dst, base, property, base_identifier);
+}
+
+void Generator::emit_get_by_value_with_this(ScopedOperand dst, ScopedOperand base, ScopedOperand property, ScopedOperand this_value)
+{
+    if (property.operand().is_constant() && get_constant(property).is_string()) {
+        auto property_key = MUST(get_constant(property).to_property_key(vm()));
+        if (property_key.is_string()) {
+            emit_get_by_id_with_this(dst, base, intern_identifier(property_key.as_string()), this_value);
+            return;
+        }
+    }
+    emit<Op::GetByValueWithThis>(dst, base, property, this_value);
+}
+
+void Generator::emit_put_by_value(ScopedOperand base, ScopedOperand property, ScopedOperand src, Bytecode::Op::PropertyKind kind, Optional<IdentifierTableIndex> base_identifier)
+{
+    if (property.operand().is_constant() && get_constant(property).is_string()) {
+        auto property_key = MUST(get_constant(property).to_property_key(vm()));
+        if (property_key.is_string()) {
+            emit<Op::PutById>(base, intern_identifier(property_key.as_string()), src, kind, m_next_property_lookup_cache++, base_identifier);
+            return;
+        }
+    }
+    emit<Op::PutByValue>(base, property, src, kind, base_identifier);
+}
+
+void Generator::emit_put_by_value_with_this(ScopedOperand base, ScopedOperand property, ScopedOperand this_value, ScopedOperand src, Bytecode::Op::PropertyKind kind)
+{
+    if (property.operand().is_constant() && get_constant(property).is_string()) {
+        auto property_key = MUST(get_constant(property).to_property_key(vm()));
+        if (property_key.is_string()) {
+            emit<Op::PutByIdWithThis>(base, this_value, intern_identifier(property_key.as_string()), src, kind, m_next_property_lookup_cache++);
+            return;
+        }
+    }
+    emit<Bytecode::Op::PutByValueWithThis>(base, property, this_value, src, kind);
+}
+
 void Generator::emit_iterator_value(ScopedOperand dst, ScopedOperand result)
 {
     emit_get_by_id(dst, result, intern_identifier("value"_fly_string));

+ 6 - 0
Libraries/LibJS/Bytecode/Generator.h

@@ -324,6 +324,12 @@ public:
 
     void emit_get_by_id_with_this(ScopedOperand dst, ScopedOperand base, IdentifierTableIndex, ScopedOperand this_value);
 
+    void emit_get_by_value(ScopedOperand dst, ScopedOperand base, ScopedOperand property, Optional<IdentifierTableIndex> base_identifier = {});
+    void emit_get_by_value_with_this(ScopedOperand dst, ScopedOperand base, ScopedOperand property, ScopedOperand this_value);
+
+    void emit_put_by_value(ScopedOperand base, ScopedOperand property, ScopedOperand src, Bytecode::Op::PropertyKind, Optional<IdentifierTableIndex> base_identifier);
+    void emit_put_by_value_with_this(ScopedOperand base, ScopedOperand property, ScopedOperand this_value, ScopedOperand src, Bytecode::Op::PropertyKind);
+
     void emit_iterator_value(ScopedOperand dst, ScopedOperand result);
     void emit_iterator_complete(ScopedOperand dst, ScopedOperand result);
 

+ 1 - 1
Libraries/LibJS/Bytecode/Interpreter.cpp

@@ -386,7 +386,7 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
 #define DISPATCH_NEXT(name)                                                                         \
     do {                                                                                            \
         if constexpr (Op::name::IsVariableLength)                                                   \
-            program_counter += static_cast<Op::name const&>(instruction).length();                  \
+            program_counter += instruction.length();                                                \
         else                                                                                        \
             program_counter += sizeof(Op::name);                                                    \
         auto& next_instruction = *reinterpret_cast<Instruction const*>(&bytecode[program_counter]); \

+ 0 - 8
Libraries/LibJS/Bytecode/Op.h

@@ -313,7 +313,6 @@ public:
     {
         return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Operand) * m_excluded_names_count);
     }
-    size_t length() const { return length_impl(); }
 
     Operand dst() const { return m_dst; }
     Operand from_object() const { return m_from_object; }
@@ -363,7 +362,6 @@ public:
     {
         return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Operand) * m_element_count);
     }
-    size_t length() const { return length_impl(); }
 
     size_t element_count() const { return m_element_count; }
 
@@ -390,7 +388,6 @@ public:
     {
         return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Value) * m_element_count);
     }
-    size_t length() const { return length_impl(); }
 
     void execute_impl(Bytecode::Interpreter&) const;
     ByteString to_byte_string_impl(Bytecode::Executable const&) const;
@@ -1819,7 +1816,6 @@ public:
     {
         return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Operand) * m_argument_count);
     }
-    size_t length() const { return length_impl(); }
 
     Operand dst() const { return m_dst; }
     Operand callee() const { return m_callee; }
@@ -1869,7 +1865,6 @@ public:
     {
         return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Operand) * m_argument_count);
     }
-    size_t length() const { return length_impl(); }
 
     Operand dst() const { return m_dst; }
     Operand callee() const { return m_callee; }
@@ -1921,7 +1916,6 @@ public:
     {
         return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Operand) * m_argument_count);
     }
-    size_t length() const { return length_impl(); }
 
     Operand dst() const { return m_dst; }
     Operand callee() const { return m_callee; }
@@ -1970,7 +1964,6 @@ public:
     {
         return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Operand) * m_argument_count);
     }
-    size_t length() const { return length_impl(); }
 
     Operand dst() const { return m_dst; }
     Operand callee() const { return m_callee; }
@@ -2088,7 +2081,6 @@ public:
     {
         return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Optional<Operand>) * m_element_keys_count);
     }
-    size_t length() const { return length_impl(); }
 
     ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
     ByteString to_byte_string_impl(Bytecode::Executable const&) const;

+ 11 - 0
Libraries/LibJS/Runtime/Value.cpp

@@ -602,6 +602,17 @@ ThrowCompletionOr<GC::Ref<Object>> Value::to_object(VM& vm) const
 // 7.1.3 ToNumeric ( value ), https://tc39.es/ecma262/#sec-tonumeric
 FLATTEN ThrowCompletionOr<Value> Value::to_numeric_slow_case(VM& vm) const
 {
+    // OPTIMIZATION: Fast paths for some trivial common cases.
+    if (is_boolean()) {
+        return Value(as_bool() ? 1 : 0);
+    }
+    if (is_null()) {
+        return Value(0);
+    }
+    if (is_undefined()) {
+        return js_nan();
+    }
+
     // 1. Let primValue be ? ToPrimitive(value, number).
     auto primitive_value = TRY(to_primitive(vm, Value::PreferredType::Number));
 

+ 3 - 0
Libraries/LibJS/Runtime/ValueInlines.h

@@ -17,6 +17,9 @@ inline bool Value::to_boolean() const
     if (is_boolean())
         return as_bool();
 
+    if (is_int32())
+        return as_i32() != 0;
+
     return to_boolean_slow_case();
 }
 

+ 49 - 4
Libraries/LibWeb/HTML/RenderingThread.cpp

@@ -6,6 +6,8 @@
 
 #include <LibCore/EventLoop.h>
 #include <LibWeb/HTML/RenderingThread.h>
+#include <LibWeb/HTML/TraversableNavigable.h>
+#include <LibWeb/Painting/BackingStore.h>
 
 namespace Web::HTML {
 
@@ -21,8 +23,9 @@ RenderingThread::~RenderingThread()
     (void)m_thread->join();
 }
 
-void RenderingThread::start()
+void RenderingThread::start(DisplayListPlayerType display_list_player_type)
 {
+    m_display_list_player_type = display_list_player_type;
     VERIFY(m_skia_player);
     m_thread = Threading::Thread::construct([this] {
         rendering_thread_loop();
@@ -36,6 +39,10 @@ void RenderingThread::rendering_thread_loop()
     while (true) {
         auto task = [this]() -> Optional<Task> {
             Threading::MutexLocker const locker { m_rendering_task_mutex };
+            if (m_needs_to_clear_bitmap_to_surface_cache) {
+                m_bitmap_to_surface.clear();
+                m_needs_to_clear_bitmap_to_surface_cache = false;
+            }
             while (m_rendering_tasks.is_empty() && !m_exit) {
                 m_rendering_task_ready_wake_condition.wait();
             }
@@ -49,18 +56,56 @@ void RenderingThread::rendering_thread_loop()
             break;
         }
 
-        m_skia_player->execute(*task->display_list, task->painting_surface);
+        auto painting_surface = painting_surface_for_backing_store(task->backing_store);
+        m_skia_player->execute(*task->display_list, painting_surface);
         m_main_thread_event_loop.deferred_invoke([callback = move(task->callback)] {
             callback();
         });
     }
 }
 
-void RenderingThread::enqueue_rendering_task(NonnullRefPtr<Painting::DisplayList> display_list, NonnullRefPtr<Gfx::PaintingSurface> painting_surface, Function<void()>&& callback)
+void RenderingThread::enqueue_rendering_task(NonnullRefPtr<Painting::DisplayList> display_list, NonnullRefPtr<Painting::BackingStore> backing_store, Function<void()>&& callback)
 {
     Threading::MutexLocker const locker { m_rendering_task_mutex };
-    m_rendering_tasks.enqueue(Task { move(display_list), move(painting_surface), move(callback) });
+    m_rendering_tasks.enqueue(Task { move(display_list), move(backing_store), move(callback) });
     m_rendering_task_ready_wake_condition.signal();
 }
 
+NonnullRefPtr<Gfx::PaintingSurface> RenderingThread::painting_surface_for_backing_store(Painting::BackingStore& backing_store)
+{
+    auto& bitmap = backing_store.bitmap();
+    auto cached_surface = m_bitmap_to_surface.find(&bitmap);
+    if (cached_surface != m_bitmap_to_surface.end())
+        return cached_surface->value;
+
+    RefPtr<Gfx::PaintingSurface> new_surface;
+    if (m_display_list_player_type == DisplayListPlayerType::SkiaGPUIfAvailable && m_skia_backend_context) {
+#ifdef USE_VULKAN
+        // Vulkan: Try to create an accelerated surface.
+        new_surface = Gfx::PaintingSurface::create_with_size(m_skia_backend_context, backing_store.size(), Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied);
+        new_surface->on_flush = [backing_store = static_cast<NonnullRefPtr<Painting::BackingStore>>(backing_store)](auto& surface) { surface.read_into_bitmap(backing_store->bitmap()); };
+#endif
+#ifdef AK_OS_MACOS
+        // macOS: Wrap an IOSurface if available.
+        if (is<Painting::IOSurfaceBackingStore>(backing_store)) {
+            auto& iosurface_backing_store = static_cast<Painting::IOSurfaceBackingStore&>(backing_store);
+            new_surface = Gfx::PaintingSurface::wrap_iosurface(iosurface_backing_store.iosurface_handle(), *m_skia_backend_context);
+        }
+#endif
+    }
+
+    // CPU and fallback: wrap the backing store bitmap directly.
+    if (!new_surface)
+        new_surface = Gfx::PaintingSurface::wrap_bitmap(bitmap);
+
+    m_bitmap_to_surface.set(&bitmap, *new_surface);
+    return *new_surface;
+}
+
+void RenderingThread::clear_bitmap_to_surface_cache()
+{
+    Threading::MutexLocker const locker { m_rendering_task_mutex };
+    m_needs_to_clear_bitmap_to_surface_cache = true;
+}
+
 }

+ 13 - 3
Libraries/LibWeb/HTML/RenderingThread.h

@@ -11,6 +11,8 @@
 #include <LibThreading/ConditionVariable.h>
 #include <LibThreading/Mutex.h>
 #include <LibThreading/Thread.h>
+#include <LibWeb/Forward.h>
+#include <LibWeb/Page/Page.h>
 #include <LibWeb/Painting/DisplayListPlayerSkia.h>
 
 namespace Web::HTML {
@@ -23,23 +25,28 @@ public:
     RenderingThread();
     ~RenderingThread();
 
-    void start();
+    void start(DisplayListPlayerType);
     void set_skia_player(OwnPtr<Painting::DisplayListPlayerSkia>&& player) { m_skia_player = move(player); }
-    void enqueue_rendering_task(NonnullRefPtr<Painting::DisplayList>, NonnullRefPtr<Gfx::PaintingSurface>, Function<void()>&& callback);
+    void set_skia_backend_context(RefPtr<Gfx::SkiaBackendContext> context) { m_skia_backend_context = move(context); }
+    void enqueue_rendering_task(NonnullRefPtr<Painting::DisplayList>, NonnullRefPtr<Painting::BackingStore>, Function<void()>&& callback);
+    void clear_bitmap_to_surface_cache();
 
 private:
     void rendering_thread_loop();
+    NonnullRefPtr<Gfx::PaintingSurface> painting_surface_for_backing_store(Painting::BackingStore& backing_store);
 
     Core::EventLoop& m_main_thread_event_loop;
+    DisplayListPlayerType m_display_list_player_type;
 
     OwnPtr<Painting::DisplayListPlayerSkia> m_skia_player;
+    RefPtr<Gfx::SkiaBackendContext> m_skia_backend_context;
 
     RefPtr<Threading::Thread> m_thread;
     Atomic<bool> m_exit { false };
 
     struct Task {
         NonnullRefPtr<Painting::DisplayList> display_list;
-        NonnullRefPtr<Gfx::PaintingSurface> painting_surface;
+        NonnullRefPtr<Painting::BackingStore> backing_store;
         Function<void()> callback;
     };
     // NOTE: Queue will only contain multiple items in case tasks were scheduled by screenshot requests.
@@ -47,6 +54,9 @@ private:
     Queue<Task> m_rendering_tasks;
     Threading::Mutex m_rendering_task_mutex;
     Threading::ConditionVariable m_rendering_task_ready_wake_condition { m_rendering_task_mutex };
+
+    HashMap<Gfx::Bitmap*, NonnullRefPtr<Gfx::PaintingSurface>> m_bitmap_to_surface;
+    bool m_needs_to_clear_bitmap_to_surface_cache { false };
 };
 
 }

+ 5 - 35
Libraries/LibWeb/HTML/TraversableNavigable.cpp

@@ -62,7 +62,8 @@ TraversableNavigable::TraversableNavigable(GC::Ref<Page> page)
     }
 
     m_rendering_thread.set_skia_player(move(skia_player));
-    m_rendering_thread.start();
+    m_rendering_thread.set_skia_backend_context(m_skia_backend_context);
+    m_rendering_thread.start(display_list_player_type);
 }
 
 TraversableNavigable::~TraversableNavigable() = default;
@@ -1399,38 +1400,7 @@ void TraversableNavigable::set_viewport_size(CSSPixelSize size)
     Navigable::set_viewport_size(size);
 
     // Invalidate the surface cache if the traversable changed size.
-    m_bitmap_to_surface.clear();
-}
-
-NonnullRefPtr<Gfx::PaintingSurface> TraversableNavigable::painting_surface_for_backing_store(Painting::BackingStore& backing_store)
-{
-    auto& bitmap = backing_store.bitmap();
-    auto cached_surface = m_bitmap_to_surface.find(&bitmap);
-    if (cached_surface != m_bitmap_to_surface.end())
-        return cached_surface->value;
-
-    RefPtr<Gfx::PaintingSurface> new_surface;
-    if (page().client().display_list_player_type() == DisplayListPlayerType::SkiaGPUIfAvailable && m_skia_backend_context) {
-#ifdef USE_VULKAN
-        // Vulkan: Try to create an accelerated surface.
-        new_surface = Gfx::PaintingSurface::create_with_size(m_skia_backend_context, backing_store.size(), Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied);
-        new_surface->on_flush = [backing_store = static_cast<NonnullRefPtr<Painting::BackingStore>>(backing_store)](auto& surface) { surface.read_into_bitmap(backing_store->bitmap()); };
-#endif
-#ifdef AK_OS_MACOS
-        // macOS: Wrap an IOSurface if available.
-        if (is<Painting::IOSurfaceBackingStore>(backing_store)) {
-            auto& iosurface_backing_store = static_cast<Painting::IOSurfaceBackingStore&>(backing_store);
-            new_surface = Gfx::PaintingSurface::wrap_iosurface(iosurface_backing_store.iosurface_handle(), *m_skia_backend_context);
-        }
-#endif
-    }
-
-    // CPU and fallback: wrap the backing store bitmap directly.
-    if (!new_surface)
-        new_surface = Gfx::PaintingSurface::wrap_bitmap(bitmap);
-
-    m_bitmap_to_surface.set(&bitmap, *new_surface);
-    return *new_surface;
+    m_rendering_thread.clear_bitmap_to_surface_cache();
 }
 
 RefPtr<Painting::DisplayList> TraversableNavigable::record_display_list(DevicePixelRect const& content_rect, PaintOptions paint_options)
@@ -1454,9 +1424,9 @@ RefPtr<Painting::DisplayList> TraversableNavigable::record_display_list(DevicePi
     return document->record_display_list(paint_config);
 }
 
-void TraversableNavigable::start_display_list_rendering(NonnullRefPtr<Painting::DisplayList> display_list, NonnullRefPtr<Gfx::PaintingSurface> painting_surface, Function<void()>&& callback)
+void TraversableNavigable::start_display_list_rendering(NonnullRefPtr<Painting::DisplayList> display_list, NonnullRefPtr<Painting::BackingStore> backing_store, Function<void()>&& callback)
 {
-    m_rendering_thread.enqueue_rendering_task(move(display_list), move(painting_surface), move(callback));
+    m_rendering_thread.enqueue_rendering_task(move(display_list), move(backing_store), move(callback));
 }
 
 }

+ 3 - 6
Libraries/LibWeb/HTML/TraversableNavigable.h

@@ -98,7 +98,7 @@ public:
     [[nodiscard]] GC::Ptr<DOM::Node> currently_focused_area();
 
     RefPtr<Painting::DisplayList> record_display_list(DevicePixelRect const&, PaintOptions);
-    void start_display_list_rendering(NonnullRefPtr<Painting::DisplayList> display_list, NonnullRefPtr<Gfx::PaintingSurface> painting_surface, Function<void()>&& callback);
+    void start_display_list_rendering(NonnullRefPtr<Painting::DisplayList>, NonnullRefPtr<Painting::BackingStore>, Function<void()>&& callback);
 
     enum class CheckIfUnloadingIsCanceledResult {
         CanceledByBeforeUnload,
@@ -117,8 +117,6 @@ public:
     bool needs_repaint() const { return m_needs_repaint; }
     void set_needs_repaint() { m_needs_repaint = true; }
 
-    NonnullRefPtr<Gfx::PaintingSurface> painting_surface_for_backing_store(Painting::BackingStore&);
-
 private:
     TraversableNavigable(GC::Ref<Page>);
 
@@ -140,6 +138,8 @@ private:
 
     [[nodiscard]] bool can_go_forward() const;
 
+    RenderingThread m_rendering_thread;
+
     // https://html.spec.whatwg.org/multipage/document-sequences.html#tn-current-session-history-step
     int m_current_session_history_step { 0 };
 
@@ -163,11 +163,8 @@ private:
     String m_window_handle;
 
     RefPtr<Gfx::SkiaBackendContext> m_skia_backend_context;
-    HashMap<Gfx::Bitmap*, NonnullRefPtr<Gfx::PaintingSurface>> m_bitmap_to_surface;
 
     bool m_needs_repaint { true };
-
-    RenderingThread m_rendering_thread;
 };
 
 struct BrowsingContextAndDocument {

+ 0 - 5
Meta/CMake/vcpkg/generate_vcpkg_toolchain_variables.cmake

@@ -17,11 +17,6 @@ if (LINUX AND NOT LAGOM_USE_LINKER)
     string(APPEND EXTRA_VCPKG_VARIABLES "set(ENV{LDFLAGS} -Wl,-z,noseparate-code)\n")
 endif()
 
-# Temporary workaround until a version of vcpkg with https://github.com/microsoft/vcpkg/pull/44712 is released
-if (CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
-    string(APPEND EXTRA_VCPKG_VARIABLES "set(ENV{CMAKE_POLICY_VERSION_MINIMUM} 3.5)\n")
-endif()
-
 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/build-vcpkg-variables.cmake" "${EXTRA_VCPKG_VARIABLES}")
 
 # Munge the VCPKG_TRIPLET to correspond to the right one for our presets

+ 1 - 2
Services/WebContent/PageClient.cpp

@@ -246,8 +246,7 @@ void PageClient::start_display_list_rendering(Web::DevicePixelRect const& conten
         callback();
         return;
     }
-    auto painting_surface = traversable.painting_surface_for_backing_store(target);
-    traversable.start_display_list_rendering(*display_list, painting_surface, move(callback));
+    traversable.start_display_list_rendering(*display_list, target, move(callback));
 }
 
 Queue<Web::QueuedInputEvent>& PageClient::input_event_queue()

+ 1 - 1
Toolchain/BuildVcpkg.py

@@ -10,7 +10,7 @@ def main() -> int:
     script_dir = pathlib.Path(__file__).parent.resolve()
 
     git_repo = "https://github.com/microsoft/vcpkg.git"
-    git_rev = "ea2a964f9303270322cf3f2d51c265ba146c422d"  # main on 2025-04-01
+    git_rev = "533a5fda5c0646d1771345fb572e759283444d5f"  # main on 2025-04-03
 
     build_dir = script_dir.parent / "Build"
     build_dir.mkdir(parents=True, exist_ok=True)

+ 1 - 1
vcpkg.json

@@ -1,5 +1,5 @@
 {
-  "builtin-baseline": "ea2a964f9303270322cf3f2d51c265ba146c422d",
+  "builtin-baseline": "533a5fda5c0646d1771345fb572e759283444d5f",
   "dependencies": [
     {
       "name": "angle",