LibWeb: Stop using VideoFrameSource for video frame updates
Future compositor-process work needs to push video frame updates without going through VideoFrameSource. That object cannot be shared through IPC, so video display-list resources now use stable VideoFrameResourceId values and the current frame is sent through explicit resource/update commands.
This commit is contained in:
parent
22fc50e606
commit
6063650261
21 changed files with 157 additions and 165 deletions
|
|
@ -875,7 +875,6 @@ set(SOURCES
|
|||
Painting/RadioButtonPaintable.cpp
|
||||
Painting/ReplacedElementCommon.cpp
|
||||
Painting/ResolvedCSSFilter.cpp
|
||||
Painting/VideoFrameSource.cpp
|
||||
Painting/ResizeHandle.cpp
|
||||
Painting/Scrollbar.cpp
|
||||
Painting/ScrollFrame.cpp
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <LibGfx/PaintingSurface.h>
|
||||
#include <LibGfx/SharedImage.h>
|
||||
#include <LibGfx/SkiaBackendContext.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
#include <LibThreading/Thread.h>
|
||||
#include <LibWeb/Compositor/AsyncScrollTree.h>
|
||||
#include <LibWeb/Compositor/AsyncScrollingState.h>
|
||||
|
|
@ -63,6 +64,15 @@ struct UpdateScrollStateCommand {
|
|||
Painting::ScrollStateSnapshot scroll_state_snapshot;
|
||||
};
|
||||
|
||||
struct UpdateVideoFrameCommand {
|
||||
Painting::VideoFrameResourceId frame_id;
|
||||
NonnullRefPtr<Media::VideoFrame const> frame;
|
||||
};
|
||||
|
||||
struct ClearVideoFrameCommand {
|
||||
Painting::VideoFrameResourceId frame_id;
|
||||
};
|
||||
|
||||
struct UpdateCompositorSurfaceCommand {
|
||||
Painting::CompositorSurfaceId surface_id;
|
||||
Gfx::SharedImage shared_image;
|
||||
|
|
@ -88,8 +98,8 @@ struct ScreenshotCommand {
|
|||
};
|
||||
|
||||
using CompositorCommand = Variant<UpdateDisplayListCommand, AsyncScrollByCommand, ViewportScrollbarDragCommand,
|
||||
UpdateScrollStateCommand, UpdateCompositorSurfaceCommand, ClearCompositorSurfaceCommand, ViewportSizeUpdatedCommand,
|
||||
PresentFrameCommand, ScreenshotCommand>;
|
||||
UpdateScrollStateCommand, UpdateVideoFrameCommand, ClearVideoFrameCommand, UpdateCompositorSurfaceCommand,
|
||||
ClearCompositorSurfaceCommand, ViewportSizeUpdatedCommand, PresentFrameCommand, ScreenshotCommand>;
|
||||
|
||||
struct CompositorCommandEnvelope {
|
||||
CompositorContextId context_id;
|
||||
|
|
@ -610,6 +620,12 @@ public:
|
|||
}
|
||||
}
|
||||
},
|
||||
[&context](UpdateVideoFrameCommand& cmd) {
|
||||
context.display_list_resource_storage.update_video_frame(cmd.frame_id, move(cmd.frame));
|
||||
},
|
||||
[&context](ClearVideoFrameCommand& cmd) {
|
||||
context.display_list_resource_storage.clear_video_frame(cmd.frame_id);
|
||||
},
|
||||
[&context](UpdateCompositorSurfaceCommand& cmd) {
|
||||
context.display_list_resource_storage.update_compositor_surface(cmd.surface_id, move(cmd.shared_image));
|
||||
},
|
||||
|
|
@ -1304,6 +1320,16 @@ void CompositorThread::Context::update_display_list(
|
|||
m_thread_data->enqueue_command(m_context_id, UpdateDisplayListCommand { move(display_list), move(resource_transaction), move(scroll_state_snapshot) });
|
||||
}
|
||||
|
||||
void CompositorThread::Context::update_video_frame(Painting::VideoFrameResourceId frame_id, NonnullRefPtr<Media::VideoFrame const> frame)
|
||||
{
|
||||
m_thread_data->enqueue_command(m_context_id, UpdateVideoFrameCommand { frame_id, move(frame) });
|
||||
}
|
||||
|
||||
void CompositorThread::Context::clear_video_frame(Painting::VideoFrameResourceId frame_id)
|
||||
{
|
||||
m_thread_data->enqueue_command(m_context_id, ClearVideoFrameCommand { frame_id });
|
||||
}
|
||||
|
||||
void CompositorThread::Context::update_compositor_surface(Painting::CompositorSurfaceId surface_id, Gfx::SharedImage&& shared_image)
|
||||
{
|
||||
m_thread_data->enqueue_command(m_context_id, UpdateCompositorSurfaceCommand { surface_id, move(shared_image) });
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <LibGfx/Rect.h>
|
||||
#include <LibGfx/SharedImage.h>
|
||||
#include <LibGfx/Size.h>
|
||||
#include <LibMedia/Forward.h>
|
||||
#include <LibSync/ConditionVariable.h>
|
||||
#include <LibThreading/Forward.h>
|
||||
#include <LibWeb/Compositor/AsyncScrollingState.h>
|
||||
|
|
@ -81,6 +82,8 @@ public:
|
|||
void set_presentation_mode(PresentationMode);
|
||||
|
||||
void update_display_list(NonnullRefPtr<Painting::DisplayList>, Painting::DisplayListResourceTransaction&&, Painting::ScrollStateSnapshot&&);
|
||||
void update_video_frame(Painting::VideoFrameResourceId, NonnullRefPtr<Media::VideoFrame const>);
|
||||
void clear_video_frame(Painting::VideoFrameResourceId);
|
||||
void update_compositor_surface(Painting::CompositorSurfaceId, Gfx::SharedImage&&);
|
||||
void clear_compositor_surface(Painting::CompositorSurfaceId);
|
||||
void update_scroll_state(Painting::ScrollStateSnapshot&&);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ class DisplayList;
|
|||
class DisplayListPlayerSkia;
|
||||
class DisplayListRecorder;
|
||||
class DisplayListResourceStorage;
|
||||
class VideoFrameSource;
|
||||
struct GradientPaintStyle;
|
||||
struct PatternPaintStyle;
|
||||
class ScrollStateSnapshot;
|
||||
|
|
|
|||
|
|
@ -131,6 +131,8 @@ void HTMLMediaElement::finalize()
|
|||
// already cleared.
|
||||
m_controls.clear();
|
||||
|
||||
clear_compositor_video_frame();
|
||||
|
||||
document().page().unregister_media_element({}, unique_id());
|
||||
}
|
||||
|
||||
|
|
@ -1549,11 +1551,37 @@ void HTMLMediaElement::set_audio_track_enabled(Badge<AudioTrack>, GC::Ptr<HTML::
|
|||
m_playback_manager->disable_an_audio_track(audio_track->track_in_playback_manager());
|
||||
}
|
||||
|
||||
Painting::VideoFrameSource& HTMLMediaElement::ensure_video_frame_source()
|
||||
Painting::VideoFrameResourceId HTMLMediaElement::ensure_video_frame_resource_id()
|
||||
{
|
||||
if (!m_video_frame_source)
|
||||
m_video_frame_source = Painting::VideoFrameSource::create();
|
||||
return *m_video_frame_source;
|
||||
if (!m_video_frame_resource_id.has_value())
|
||||
m_video_frame_resource_id = Painting::allocate_video_frame_resource_id();
|
||||
return *m_video_frame_resource_id;
|
||||
}
|
||||
|
||||
void HTMLMediaElement::update_compositor_video_frame(NonnullRefPtr<Media::VideoFrame const> frame)
|
||||
{
|
||||
auto frame_id = ensure_video_frame_resource_id();
|
||||
if (auto navigable = document().navigable(); navigable && navigable->has_compositor_context())
|
||||
navigable->compositor_context().update_video_frame(frame_id, move(frame));
|
||||
}
|
||||
|
||||
void HTMLMediaElement::clear_compositor_video_frame()
|
||||
{
|
||||
if (!m_video_frame_resource_id.has_value())
|
||||
return;
|
||||
if (auto navigable = document().navigable(); navigable && navigable->has_compositor_context())
|
||||
navigable->compositor_context().clear_video_frame(*m_video_frame_resource_id);
|
||||
}
|
||||
|
||||
void HTMLMediaElement::update_current_video_frame()
|
||||
{
|
||||
if (auto current_frame = m_selected_video_track_sink->current_frame())
|
||||
update_compositor_video_frame(NonnullRefPtr<Media::VideoFrame const> { *current_frame });
|
||||
else
|
||||
clear_compositor_video_frame();
|
||||
|
||||
auto intrinsic_dimensions_changed = update_intrinsic_video_dimensions();
|
||||
set_needs_repaint(intrinsic_dimensions_changed ? InvalidateDisplayList::Yes : InvalidateDisplayList::No);
|
||||
}
|
||||
|
||||
void HTMLMediaElement::set_selected_video_track(Badge<VideoTrack>, GC::Ptr<HTML::VideoTrack> video_track)
|
||||
|
|
@ -1563,8 +1591,7 @@ void HTMLMediaElement::set_selected_video_track(Badge<VideoTrack>, GC::Ptr<HTML:
|
|||
if (video_track && !m_playback_manager->video_tracks().contains_slow(video_track->track_in_playback_manager()))
|
||||
return;
|
||||
|
||||
if (m_video_frame_source)
|
||||
m_video_frame_source->clear();
|
||||
clear_compositor_video_frame();
|
||||
|
||||
auto previous_track = m_selected_video_track;
|
||||
|
||||
|
|
@ -1573,12 +1600,7 @@ void HTMLMediaElement::set_selected_video_track(Badge<VideoTrack>, GC::Ptr<HTML:
|
|||
m_selected_video_track_sink = m_playback_manager->get_or_create_the_displaying_video_sink_for_track(video_track->track_in_playback_manager());
|
||||
auto sink_update_result = m_selected_video_track_sink->update();
|
||||
if (sink_update_result == Media::DisplayingVideoSinkUpdateResult::NewFrameAvailable) {
|
||||
if (auto current_frame = m_selected_video_track_sink->current_frame())
|
||||
ensure_video_frame_source().update(move(current_frame));
|
||||
else if (m_video_frame_source)
|
||||
m_video_frame_source->clear();
|
||||
update_intrinsic_video_dimensions();
|
||||
set_needs_repaint();
|
||||
update_current_video_frame();
|
||||
} else if (auto* video_element = as_if<HTMLVideoElement>(this)) {
|
||||
auto const& video_data = video_track->track_in_playback_manager().video_data();
|
||||
video_element->set_intrinsic_video_dimensions(Gfx::Size<u32>(video_data.pixel_width, video_data.pixel_height));
|
||||
|
|
@ -1598,14 +1620,8 @@ void HTMLMediaElement::update_video_frame_and_timeline()
|
|||
|
||||
if (m_selected_video_track_sink) {
|
||||
auto sink_update_result = m_selected_video_track_sink->update();
|
||||
if (sink_update_result == Media::DisplayingVideoSinkUpdateResult::NewFrameAvailable) {
|
||||
if (auto current_frame = m_selected_video_track_sink->current_frame())
|
||||
ensure_video_frame_source().update(move(current_frame));
|
||||
else if (m_video_frame_source)
|
||||
m_video_frame_source->clear();
|
||||
update_intrinsic_video_dimensions();
|
||||
set_needs_repaint();
|
||||
}
|
||||
if (sink_update_result == Media::DisplayingVideoSinkUpdateResult::NewFrameAvailable)
|
||||
update_current_video_frame();
|
||||
}
|
||||
|
||||
// Wait for the seek to complete before updating the timestamp, otherwise we'll display the timestamp from
|
||||
|
|
@ -2008,6 +2024,7 @@ void HTMLMediaElement::forget_media_resource_specific_tracks()
|
|||
m_audio_tracks->remove_all_tracks();
|
||||
m_video_tracks->remove_all_tracks();
|
||||
m_playback_manager.clear();
|
||||
clear_compositor_video_frame();
|
||||
|
||||
// NB: At this point, we no longer have any selected tracks to derive the video dimensions from.
|
||||
update_intrinsic_video_dimensions();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/Time.h>
|
||||
#include <AK/Variant.h>
|
||||
|
|
@ -21,7 +22,7 @@
|
|||
#include <LibWeb/HTML/EventLoop/Task.h>
|
||||
#include <LibWeb/HTML/HTMLElement.h>
|
||||
#include <LibWeb/HTML/MediaControls.h>
|
||||
#include <LibWeb/Painting/VideoFrameSource.h>
|
||||
#include <LibWeb/Painting/DisplayListResourceIds.h>
|
||||
#include <LibWeb/PixelUnits.h>
|
||||
#include <LibWeb/WebIDL/DOMException.h>
|
||||
|
||||
|
|
@ -170,9 +171,10 @@ public:
|
|||
|
||||
RefPtr<Media::DisplayingVideoSink> const& selected_video_track_sink() const { return m_selected_video_track_sink; }
|
||||
|
||||
Painting::VideoFrameSource& ensure_video_frame_source();
|
||||
Painting::VideoFrameResourceId ensure_video_frame_resource_id();
|
||||
Optional<Painting::VideoFrameResourceId> video_frame_resource_id() const { return m_video_frame_resource_id; }
|
||||
|
||||
virtual void update_intrinsic_video_dimensions() { }
|
||||
virtual bool update_intrinsic_video_dimensions() { return false; }
|
||||
virtual void update_natural_dimensions() { }
|
||||
|
||||
protected:
|
||||
|
|
@ -245,6 +247,9 @@ private:
|
|||
|
||||
void volume_or_muted_attribute_changed();
|
||||
void update_volume();
|
||||
void update_compositor_video_frame(NonnullRefPtr<Media::VideoFrame const>);
|
||||
void clear_compositor_video_frame();
|
||||
void update_current_video_frame();
|
||||
|
||||
bool is_eligible_for_autoplay() const;
|
||||
|
||||
|
|
@ -380,7 +385,7 @@ private:
|
|||
bool m_has_enabled_preferred_audio_track { false };
|
||||
bool m_has_selected_preferred_video_track { false };
|
||||
|
||||
RefPtr<Painting::VideoFrameSource> m_video_frame_source;
|
||||
Optional<Painting::VideoFrameResourceId> m_video_frame_resource_id;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,21 +138,23 @@ u32 HTMLVideoElement::video_height() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void HTMLVideoElement::update_intrinsic_video_dimensions()
|
||||
bool HTMLVideoElement::update_intrinsic_video_dimensions()
|
||||
{
|
||||
if (selected_video_track_sink() == nullptr) {
|
||||
auto had_intrinsic_video_dimensions = m_intrinsic_video_dimensions.has_value();
|
||||
set_intrinsic_video_dimensions({});
|
||||
return;
|
||||
return had_intrinsic_video_dimensions;
|
||||
}
|
||||
|
||||
auto current_frame = selected_video_track_sink()->current_frame();
|
||||
if (current_frame == nullptr)
|
||||
return;
|
||||
return false;
|
||||
|
||||
auto current_frame_size = current_frame->size();
|
||||
if (current_frame_size == m_intrinsic_video_dimensions)
|
||||
return;
|
||||
return false;
|
||||
set_intrinsic_video_dimensions(current_frame_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void HTMLVideoElement::update_natural_dimensions()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public:
|
|||
u32 video_width() const;
|
||||
u32 video_height() const;
|
||||
|
||||
virtual void update_intrinsic_video_dimensions() override;
|
||||
virtual bool update_intrinsic_video_dimensions() override;
|
||||
virtual void update_natural_dimensions() override;
|
||||
Optional<Gfx::Size<u32>> natural_media_size() const;
|
||||
Optional<CSSPixelSize> natural_element_size() const;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include <LibWeb/Painting/DisplayListCommand.h>
|
||||
#include <LibWeb/Painting/DisplayListResourceStorage.h>
|
||||
#include <LibWeb/Painting/ScrollState.h>
|
||||
#include <LibWeb/Painting/VideoFrameSource.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
|
|
@ -97,7 +96,7 @@ private:
|
|||
virtual void draw_scaled_decoded_image_frame(DrawScaledDecodedImageFrame const&) = 0;
|
||||
virtual void draw_repeated_decoded_image_frame(DrawRepeatedDecodedImageFrame const&) = 0;
|
||||
virtual void draw_compositor_surface(DrawCompositorSurface const&) = 0;
|
||||
virtual void draw_video_frame_source(DrawVideoFrameSource const&) = 0;
|
||||
virtual void draw_video_frame(DrawVideoFrame const&) = 0;
|
||||
virtual void save(Save const&) = 0;
|
||||
virtual void save_layer(SaveLayer const&) = 0;
|
||||
virtual void restore(Restore const&) = 0;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ void DrawCompositorSurface::dump(StringBuilder& builder) const
|
|||
builder.appendff(" dst_rect={}", dst_rect);
|
||||
}
|
||||
|
||||
void DrawVideoFrameSource::dump(StringBuilder& builder) const
|
||||
void DrawVideoFrame::dump(StringBuilder& builder) const
|
||||
{
|
||||
builder.appendff(" dst_rect={}", dst_rect);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class DisplayList;
|
|||
V(DrawScaledDecodedImageFrame, draw_scaled_decoded_image_frame) \
|
||||
V(DrawRepeatedDecodedImageFrame, draw_repeated_decoded_image_frame) \
|
||||
V(DrawCompositorSurface, draw_compositor_surface) \
|
||||
V(DrawVideoFrameSource, draw_video_frame_source) \
|
||||
V(DrawVideoFrame, draw_video_frame) \
|
||||
V(Save, save) \
|
||||
V(SaveLayer, save_layer) \
|
||||
V(Restore, restore) \
|
||||
|
|
@ -177,12 +177,12 @@ struct DrawCompositorSurface {
|
|||
void dump(StringBuilder&) const;
|
||||
};
|
||||
|
||||
struct DrawVideoFrameSource {
|
||||
static constexpr StringView command_name = "DrawVideoFrameSource"sv;
|
||||
static constexpr DisplayListCommandType command_type = DisplayListCommandType::DrawVideoFrameSource;
|
||||
struct DrawVideoFrame {
|
||||
static constexpr StringView command_name = "DrawVideoFrame"sv;
|
||||
static constexpr DisplayListCommandType command_type = DisplayListCommandType::DrawVideoFrame;
|
||||
|
||||
Gfx::IntRect dst_rect;
|
||||
VideoFrameResourceId source_id;
|
||||
VideoFrameResourceId video_frame_id;
|
||||
Gfx::ScalingMode scaling_mode;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return dst_rect; }
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
#include <LibGfx/YUVData.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
#include <LibWeb/Painting/DisplayListPlayerSkia.h>
|
||||
#include <LibWeb/Painting/VideoFrameSource.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
|
|
@ -183,9 +182,9 @@ void DisplayListPlayerSkia::draw_compositor_surface(DrawCompositorSurface const&
|
|||
canvas.drawImageRect(image.get(), src_rect, dst_rect, to_skia_sampling_options(command.scaling_mode), &paint, SkCanvas::kStrict_SrcRectConstraint);
|
||||
}
|
||||
|
||||
void DisplayListPlayerSkia::draw_video_frame_source(DrawVideoFrameSource const& command)
|
||||
void DisplayListPlayerSkia::draw_video_frame(DrawVideoFrame const& command)
|
||||
{
|
||||
auto frame = resource_storage().video_frame_source(command.source_id).current_frame();
|
||||
auto frame = resource_storage().video_frame(command.video_frame_id);
|
||||
if (!frame)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ private:
|
|||
void draw_scaled_decoded_image_frame(DrawScaledDecodedImageFrame const&) override;
|
||||
void draw_repeated_decoded_image_frame(DrawRepeatedDecodedImageFrame const&) override;
|
||||
void draw_compositor_surface(DrawCompositorSurface const&) override;
|
||||
void draw_video_frame_source(DrawVideoFrameSource const&) override;
|
||||
void draw_video_frame(DrawVideoFrame const&) override;
|
||||
void add_clip_rect(AddClipRect const&) override;
|
||||
void save(Save const&) override;
|
||||
void save_layer(SaveLayer const&) override;
|
||||
|
|
|
|||
|
|
@ -510,13 +510,13 @@ void DisplayListRecorder::draw_compositor_surface(Gfx::IntRect const& dst_rect,
|
|||
});
|
||||
}
|
||||
|
||||
void DisplayListRecorder::draw_video_frame_source(Gfx::IntRect const& dst_rect, NonnullRefPtr<VideoFrameSource> source, Gfx::ScalingMode scaling_mode)
|
||||
void DisplayListRecorder::draw_video_frame(Gfx::IntRect const& dst_rect, VideoFrameResourceId frame_id, RefPtr<Media::VideoFrame const> frame, Gfx::ScalingMode scaling_mode)
|
||||
{
|
||||
if (dst_rect.is_empty())
|
||||
return;
|
||||
append_command(DrawVideoFrameSource {
|
||||
append_command(DrawVideoFrame {
|
||||
.dst_rect = dst_rect,
|
||||
.source_id = resource_storage().add_video_frame_source(move(source)),
|
||||
.video_frame_id = resource_storage().add_video_frame(frame_id, move(frame)),
|
||||
.scaling_mode = scaling_mode,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <LibGfx/Point.h>
|
||||
#include <LibGfx/Rect.h>
|
||||
#include <LibGfx/ScalingMode.h>
|
||||
#include <LibMedia/Forward.h>
|
||||
#include <LibWeb/Export.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/Painting/AccumulatedVisualContext.h>
|
||||
|
|
@ -73,7 +74,7 @@ public:
|
|||
|
||||
void draw_scaled_decoded_image_frame(Gfx::IntRect const& dst_rect, Gfx::IntRect const& clip_rect, Gfx::DecodedImageFrame frame, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
|
||||
void draw_compositor_surface(Gfx::IntRect const& dst_rect, CompositorSurfaceId, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
|
||||
void draw_video_frame_source(Gfx::IntRect const& dst_rect, NonnullRefPtr<VideoFrameSource>, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
|
||||
void draw_video_frame(Gfx::IntRect const& dst_rect, VideoFrameResourceId, RefPtr<Media::VideoFrame const>, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
|
||||
|
||||
void draw_repeated_decoded_image_frame(Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, Gfx::DecodedImageFrame frame, Gfx::ScalingMode scaling_mode, bool repeat_x, bool repeat_y);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@ AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, VideoFrameResourceId);
|
|||
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, DisplayListResourceId);
|
||||
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, CompositorSurfaceId);
|
||||
|
||||
inline VideoFrameResourceId allocate_video_frame_resource_id()
|
||||
{
|
||||
static Atomic<u64> s_next_id { 1 };
|
||||
return VideoFrameResourceId { s_next_id.fetch_add(1, AK::MemoryOrder::memory_order_relaxed) };
|
||||
}
|
||||
|
||||
inline CompositorSurfaceId allocate_compositor_surface_id()
|
||||
{
|
||||
static Atomic<u64> s_next_id { 1 };
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <LibGfx/Filter.h>
|
||||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibGfx/SharedImageBuffer.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
#include <LibWeb/Painting/DisplayList.h>
|
||||
#include <LibWeb/Painting/DisplayListResourceStorage.h>
|
||||
|
||||
|
|
@ -28,11 +29,10 @@ ImageFrameResourceId DisplayListResourceStorage::add_image_frame(Gfx::DecodedIma
|
|||
return { id };
|
||||
}
|
||||
|
||||
VideoFrameResourceId DisplayListResourceStorage::add_video_frame_source(NonnullRefPtr<VideoFrameSource const> source)
|
||||
VideoFrameResourceId DisplayListResourceStorage::add_video_frame(VideoFrameResourceId id, RefPtr<Media::VideoFrame const> frame)
|
||||
{
|
||||
auto id = source->id();
|
||||
m_video_frame_sources.ensure(id, [&] { return move(source); });
|
||||
return { id };
|
||||
m_video_frames.set(id.value(), move(frame), AK::HashSetExistingEntryBehavior::Keep);
|
||||
return id;
|
||||
}
|
||||
|
||||
DisplayListResourceId DisplayListResourceStorage::add_display_list(NonnullRefPtr<DisplayList const> display_list)
|
||||
|
|
@ -57,8 +57,8 @@ void DisplayListResourceStorage::append_referenced_resources_from(
|
|||
add_font(source.font(id));
|
||||
for (auto id : referenced_resources.image_frames)
|
||||
add_image_frame(source.image_frame(id));
|
||||
for (auto id : referenced_resources.video_frame_sources)
|
||||
add_video_frame_source(source.video_frame_source(id));
|
||||
for (auto id : referenced_resources.video_frames)
|
||||
add_video_frame(id, source.video_frame(id));
|
||||
for (auto id : referenced_resources.display_lists)
|
||||
add_display_list(source.display_list(id));
|
||||
}
|
||||
|
|
@ -80,8 +80,8 @@ void DisplayListResourceStorage::collect_referenced_resources(
|
|||
referenced_resources.fonts.set(command.font_id, AK::HashSetExistingEntryBehavior::Keep);
|
||||
if constexpr (requires { command.frame_id; })
|
||||
referenced_resources.image_frames.set(command.frame_id, AK::HashSetExistingEntryBehavior::Keep);
|
||||
if constexpr (requires { video_frame_source(command.source_id); })
|
||||
referenced_resources.video_frame_sources.set(command.source_id, AK::HashSetExistingEntryBehavior::Keep);
|
||||
if constexpr (requires { command.video_frame_id; })
|
||||
referenced_resources.video_frames.set(command.video_frame_id, AK::HashSetExistingEntryBehavior::Keep);
|
||||
if constexpr (requires { command.paint_style; command.paint_kind; }) {
|
||||
if (command.paint_kind == decltype(command.paint_kind)::PaintStyle
|
||||
&& command.paint_style.type == DisplayListPaintStyleType::Pattern)
|
||||
|
|
@ -139,9 +139,9 @@ DisplayListResourceTransaction DisplayListResourceStorage::create_transaction(
|
|||
if (!previous.image_frames.contains(id))
|
||||
transaction.image_frames.append(image_frame(id));
|
||||
}
|
||||
for (auto id : current.video_frame_sources) {
|
||||
if (!previous.video_frame_sources.contains(id))
|
||||
transaction.video_frame_sources.append(video_frame_source(id));
|
||||
for (auto id : current.video_frames) {
|
||||
if (!previous.video_frames.contains(id))
|
||||
transaction.video_frames.append({ id, video_frame(id) });
|
||||
}
|
||||
for (auto id : current.display_lists) {
|
||||
if (!previous.display_lists.contains(id))
|
||||
|
|
@ -156,9 +156,9 @@ DisplayListResourceTransaction DisplayListResourceStorage::create_transaction(
|
|||
if (!current.image_frames.contains(id))
|
||||
transaction.image_frame_ids_to_remove.append(id);
|
||||
}
|
||||
for (auto id : previous.video_frame_sources) {
|
||||
if (!current.video_frame_sources.contains(id))
|
||||
transaction.video_frame_source_ids_to_remove.append(id);
|
||||
for (auto id : previous.video_frames) {
|
||||
if (!current.video_frames.contains(id))
|
||||
transaction.video_frame_ids_to_remove.append(id);
|
||||
}
|
||||
for (auto id : previous.display_lists) {
|
||||
if (!current.display_lists.contains(id))
|
||||
|
|
@ -173,8 +173,8 @@ void DisplayListResourceStorage::apply_transaction(DisplayListResourceTransactio
|
|||
add_font(*font);
|
||||
for (auto const& frame : transaction.image_frames)
|
||||
add_image_frame(frame);
|
||||
for (auto& source : transaction.video_frame_sources)
|
||||
add_video_frame_source(move(source));
|
||||
for (auto& video_frame : transaction.video_frames)
|
||||
add_video_frame(video_frame.id, move(video_frame.frame));
|
||||
for (auto& display_list : transaction.display_lists)
|
||||
add_display_list(move(display_list));
|
||||
|
||||
|
|
@ -182,8 +182,8 @@ void DisplayListResourceStorage::apply_transaction(DisplayListResourceTransactio
|
|||
m_fonts.remove(id.value());
|
||||
for (auto id : transaction.image_frame_ids_to_remove)
|
||||
m_image_frames.remove(id.value());
|
||||
for (auto id : transaction.video_frame_source_ids_to_remove)
|
||||
m_video_frame_sources.remove(id.value());
|
||||
for (auto id : transaction.video_frame_ids_to_remove)
|
||||
m_video_frames.remove(id.value());
|
||||
for (auto id : transaction.display_list_ids_to_remove)
|
||||
m_display_lists.remove(id.value());
|
||||
}
|
||||
|
|
@ -192,10 +192,21 @@ void DisplayListResourceStorage::retain_only(DisplayListResourceSet const& resou
|
|||
{
|
||||
m_fonts.remove_all_matching([&](auto id, auto const&) { return !resource_set.fonts.contains(FontResourceId { id }); });
|
||||
m_image_frames.remove_all_matching([&](auto id, auto const&) { return !resource_set.image_frames.contains(ImageFrameResourceId { id }); });
|
||||
m_video_frame_sources.remove_all_matching([&](auto id, auto const&) { return !resource_set.video_frame_sources.contains(VideoFrameResourceId { id }); });
|
||||
m_video_frames.remove_all_matching([&](auto id, auto const&) { return !resource_set.video_frames.contains(VideoFrameResourceId { id }); });
|
||||
m_display_lists.remove_all_matching([&](auto id, auto const&) { return !resource_set.display_lists.contains(DisplayListResourceId { id }); });
|
||||
}
|
||||
|
||||
void DisplayListResourceStorage::update_video_frame(VideoFrameResourceId frame_id, NonnullRefPtr<Media::VideoFrame const> frame)
|
||||
{
|
||||
m_video_frames.set(frame_id.value(), move(frame));
|
||||
}
|
||||
|
||||
void DisplayListResourceStorage::clear_video_frame(VideoFrameResourceId frame_id)
|
||||
{
|
||||
if (m_video_frames.contains(frame_id.value()))
|
||||
m_video_frames.set(frame_id.value(), nullptr);
|
||||
}
|
||||
|
||||
void DisplayListResourceStorage::update_compositor_surface(CompositorSurfaceId surface_id, Gfx::SharedImage&& shared_image)
|
||||
{
|
||||
auto shared_image_buffer = Gfx::SharedImageBuffer::import_from_shared_image(move(shared_image));
|
||||
|
|
|
|||
|
|
@ -12,32 +12,38 @@
|
|||
#include <AK/Noncopyable.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/Span.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibGfx/DecodedImageFrame.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/Painting/DisplayListResourceIds.h>
|
||||
#include <LibWeb/Painting/VideoFrameSource.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
struct DisplayListResourceSet {
|
||||
HashTable<FontResourceId> fonts;
|
||||
HashTable<ImageFrameResourceId> image_frames;
|
||||
HashTable<VideoFrameResourceId> video_frame_sources;
|
||||
HashTable<VideoFrameResourceId> video_frames;
|
||||
HashTable<DisplayListResourceId> display_lists;
|
||||
};
|
||||
|
||||
struct DisplayListVideoFrameResource {
|
||||
VideoFrameResourceId id;
|
||||
RefPtr<Media::VideoFrame const> frame;
|
||||
};
|
||||
|
||||
struct DisplayListResourceTransaction {
|
||||
Vector<NonnullRefPtr<Gfx::Font const>> fonts;
|
||||
Vector<Gfx::DecodedImageFrame> image_frames;
|
||||
Vector<NonnullRefPtr<VideoFrameSource const>> video_frame_sources;
|
||||
Vector<DisplayListVideoFrameResource> video_frames;
|
||||
Vector<NonnullRefPtr<DisplayList const>> display_lists;
|
||||
|
||||
Vector<FontResourceId> font_ids_to_remove;
|
||||
Vector<ImageFrameResourceId> image_frame_ids_to_remove;
|
||||
Vector<VideoFrameResourceId> video_frame_source_ids_to_remove;
|
||||
Vector<VideoFrameResourceId> video_frame_ids_to_remove;
|
||||
Vector<DisplayListResourceId> display_list_ids_to_remove;
|
||||
};
|
||||
|
||||
|
|
@ -51,7 +57,7 @@ public:
|
|||
|
||||
FontResourceId add_font(Gfx::Font const&);
|
||||
ImageFrameResourceId add_image_frame(Gfx::DecodedImageFrame const&);
|
||||
VideoFrameResourceId add_video_frame_source(NonnullRefPtr<VideoFrameSource const>);
|
||||
VideoFrameResourceId add_video_frame(VideoFrameResourceId, RefPtr<Media::VideoFrame const> = nullptr);
|
||||
DisplayListResourceId add_display_list(NonnullRefPtr<DisplayList const>);
|
||||
void append_referenced_resources_from(DisplayListResourceStorage const& source, ReadonlyBytes command_bytes);
|
||||
void apply_transaction(DisplayListResourceTransaction&&);
|
||||
|
|
@ -59,12 +65,14 @@ public:
|
|||
DisplayListResourceSet collect_referenced_resources(DisplayList const&) const;
|
||||
DisplayListResourceSet collect_referenced_resources(ReadonlyBytes command_bytes) const;
|
||||
void retain_only(DisplayListResourceSet const&);
|
||||
void update_video_frame(VideoFrameResourceId, NonnullRefPtr<Media::VideoFrame const>);
|
||||
void clear_video_frame(VideoFrameResourceId);
|
||||
void update_compositor_surface(CompositorSurfaceId, Gfx::SharedImage&&);
|
||||
void clear_compositor_surface(CompositorSurfaceId);
|
||||
|
||||
Gfx::Font const& font(FontResourceId id) const { return *m_fonts.get(id.value()).value(); }
|
||||
Gfx::DecodedImageFrame const& image_frame(ImageFrameResourceId id) const { return m_image_frames.get(id.value()).value(); }
|
||||
VideoFrameSource const& video_frame_source(VideoFrameResourceId id) const { return *m_video_frame_sources.get(id.value()).value(); }
|
||||
RefPtr<Media::VideoFrame const> video_frame(VideoFrameResourceId id) const { return m_video_frames.get(id.value()).value(); }
|
||||
DisplayList const& display_list(DisplayListResourceId id) const { return *m_display_lists.get(id.value()).value(); }
|
||||
Optional<Gfx::DecodedImageFrame const&> compositor_surface(CompositorSurfaceId id) const { return m_compositor_surfaces.get(id.value()); }
|
||||
|
||||
|
|
@ -73,7 +81,7 @@ private:
|
|||
|
||||
HashMap<u64, NonnullRefPtr<Gfx::Font const>> m_fonts;
|
||||
HashMap<u64, Gfx::DecodedImageFrame> m_image_frames;
|
||||
HashMap<u64, NonnullRefPtr<VideoFrameSource const>> m_video_frame_sources;
|
||||
HashMap<u64, RefPtr<Media::VideoFrame const>> m_video_frames;
|
||||
HashMap<u64, NonnullRefPtr<DisplayList const>> m_display_lists;
|
||||
HashMap<u64, Gfx::DecodedImageFrame> m_compositor_surfaces;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Atomic.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
#include <LibWeb/Painting/VideoFrameSource.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
static Atomic<u64> s_next_id { 1 };
|
||||
|
||||
NonnullRefPtr<VideoFrameSource> VideoFrameSource::create()
|
||||
{
|
||||
return adopt_ref(*new VideoFrameSource());
|
||||
}
|
||||
|
||||
VideoFrameSource::VideoFrameSource()
|
||||
: m_id(s_next_id.fetch_add(1, AK::MemoryOrder::memory_order_relaxed))
|
||||
{
|
||||
}
|
||||
|
||||
VideoFrameSource::~VideoFrameSource() = default;
|
||||
|
||||
void VideoFrameSource::update(RefPtr<Media::VideoFrame> frame)
|
||||
{
|
||||
RefPtr<Media::VideoFrame> old;
|
||||
{
|
||||
Sync::MutexLocker const locker { m_mutex };
|
||||
old = move(m_frame);
|
||||
m_frame = move(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoFrameSource::clear()
|
||||
{
|
||||
RefPtr<Media::VideoFrame> old;
|
||||
{
|
||||
Sync::MutexLocker const locker { m_mutex };
|
||||
old = move(m_frame);
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<Media::VideoFrame> VideoFrameSource::current_frame() const
|
||||
{
|
||||
Sync::MutexLocker const locker { m_mutex };
|
||||
return m_frame;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/AtomicRefCounted.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <LibMedia/Forward.h>
|
||||
#include <LibSync/Mutex.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
class VideoFrameSource final : public AtomicRefCounted<VideoFrameSource> {
|
||||
public:
|
||||
static NonnullRefPtr<VideoFrameSource> create();
|
||||
~VideoFrameSource();
|
||||
|
||||
u64 id() const { return m_id; }
|
||||
|
||||
void update(RefPtr<Media::VideoFrame>);
|
||||
void clear();
|
||||
RefPtr<Media::VideoFrame> current_frame() const;
|
||||
|
||||
private:
|
||||
VideoFrameSource();
|
||||
|
||||
u64 m_id { 0 };
|
||||
mutable Sync::Mutex m_mutex;
|
||||
RefPtr<Media::VideoFrame> m_frame;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/DecodedImageFrame.h>
|
||||
#include <LibMedia/Sinks/DisplayingVideoSink.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/HTML/HTMLMediaElement.h>
|
||||
|
|
@ -61,8 +62,9 @@ void VideoPaintable::paint(DisplayListRecordingContext& context, PaintPhase phas
|
|||
};
|
||||
|
||||
auto paint_video_frame = [&]() {
|
||||
auto& source = const_cast<HTML::HTMLVideoElement&>(video_element).ensure_video_frame_source();
|
||||
auto current = source.current_frame();
|
||||
RefPtr<Media::VideoFrame> current;
|
||||
if (auto const& sink = video_element.selected_video_track_sink())
|
||||
current = sink->current_frame();
|
||||
|
||||
Gfx::IntSize src_size;
|
||||
if (current)
|
||||
|
|
@ -76,7 +78,9 @@ void VideoPaintable::paint(DisplayListRecordingContext& context, PaintPhase phas
|
|||
if (dst_rect.is_empty())
|
||||
return;
|
||||
auto scaling_mode = to_gfx_scaling_mode(computed_values().image_rendering(), src_size, dst_rect.size());
|
||||
context.display_list_recorder().draw_video_frame_source(dst_rect, source, scaling_mode);
|
||||
RefPtr<Media::VideoFrame const> frame = current;
|
||||
auto frame_id = const_cast<HTML::HTMLVideoElement&>(video_element).ensure_video_frame_resource_id();
|
||||
context.display_list_recorder().draw_video_frame(dst_rect, frame_id, move(frame), scaling_mode);
|
||||
};
|
||||
|
||||
auto paint_transparent_black = [&]() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue