mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
LibWeb: Return ImmutableBitmap from PaintingSurface::create_snapshot()
This is a preparation for upcoming changes where ImmutableBitmap will own SkImage allowing Skia to cache GPU textures across repaints.
This commit is contained in:
parent
31bf40b659
commit
a2c33ea4e1
Notes:
github-actions[bot]
2024-11-09 20:21:16 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/a2c33ea4e1a Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2254
13 changed files with 33 additions and 20 deletions
|
@ -28,6 +28,7 @@ class Line;
|
|||
class AntiAliasingPainter;
|
||||
class DeprecatedPainter;
|
||||
class Painter;
|
||||
class PaintingSurface;
|
||||
class Palette;
|
||||
class PaletteImpl;
|
||||
class DeprecatedPath;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
* Copyright (c) 2023-2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
* Copyright (c) 2023-2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/ImmutableBitmap.h>
|
||||
#include <LibGfx/PaintingSurface.h>
|
||||
|
||||
#include <core/SkColorSpace.h>
|
||||
|
@ -91,13 +92,13 @@ PaintingSurface::PaintingSurface(NonnullOwnPtr<Impl>&& impl)
|
|||
|
||||
PaintingSurface::~PaintingSurface() = default;
|
||||
|
||||
RefPtr<Bitmap> PaintingSurface::create_snapshot() const
|
||||
NonnullRefPtr<ImmutableBitmap> PaintingSurface::create_snapshot() const
|
||||
{
|
||||
auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied, size()).value();
|
||||
auto image_info = SkImageInfo::Make(bitmap->width(), bitmap->height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType);
|
||||
SkPixmap const pixmap(image_info, bitmap->begin(), bitmap->pitch());
|
||||
sk_surface().readPixels(pixmap, 0, 0);
|
||||
return bitmap;
|
||||
return ImmutableBitmap::create(bitmap);
|
||||
}
|
||||
|
||||
void PaintingSurface::read_into_bitmap(Gfx::Bitmap& bitmap)
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
static NonnullRefPtr<PaintingSurface> wrap_metal_surface(Gfx::MetalTexture&, RefPtr<SkiaBackendContext>);
|
||||
#endif
|
||||
|
||||
RefPtr<Bitmap> create_snapshot() const;
|
||||
NonnullRefPtr<ImmutableBitmap> create_snapshot() const;
|
||||
void read_into_bitmap(Bitmap&);
|
||||
|
||||
IntSize size() const;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2023, MacDue <macdue@dueutil.tech>
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -130,7 +131,10 @@ WebIDL::ExceptionOr<JS::GCPtr<CanvasPattern>> CanvasPattern::create(JS::Realm& r
|
|||
auto bitmap = image.visit(
|
||||
[](JS::Handle<HTMLImageElement> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); },
|
||||
[](JS::Handle<SVG::SVGImageElement> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); },
|
||||
[](JS::Handle<HTMLCanvasElement> const& source) -> RefPtr<Gfx::Bitmap> { return source->surface()->create_snapshot(); },
|
||||
[](JS::Handle<HTMLCanvasElement> const& source) -> RefPtr<Gfx::Bitmap> {
|
||||
auto snapshot = source->surface()->create_snapshot();
|
||||
return snapshot->bitmap();
|
||||
},
|
||||
[](JS::Handle<HTMLVideoElement> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); },
|
||||
[](JS::Handle<ImageBitmap> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); });
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) 2020-2024, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2023, MacDue <macdue@dueutil.tech>
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -125,7 +126,10 @@ WebIDL::ExceptionOr<void> CanvasRenderingContext2D::draw_image_internal(CanvasIm
|
|||
auto bitmap = image.visit(
|
||||
[](JS::Handle<HTMLImageElement> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); },
|
||||
[](JS::Handle<SVG::SVGImageElement> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); },
|
||||
[](JS::Handle<HTMLCanvasElement> const& source) -> RefPtr<Gfx::Bitmap> { return source->surface()->create_snapshot(); },
|
||||
[](JS::Handle<HTMLCanvasElement> const& source) -> RefPtr<Gfx::Bitmap> {
|
||||
auto snapshot = source->surface()->create_snapshot();
|
||||
return snapshot->bitmap();
|
||||
},
|
||||
[](JS::Handle<HTMLVideoElement> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); },
|
||||
[](JS::Handle<ImageBitmap> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); });
|
||||
if (!bitmap)
|
||||
|
@ -389,10 +393,10 @@ WebIDL::ExceptionOr<JS::GCPtr<ImageData>> CanvasRenderingContext2D::get_image_da
|
|||
// NOTE: We don't attempt to create the underlying bitmap here; if it doesn't exist, it's like copying only transparent black pixels (which is a no-op).
|
||||
if (!canvas_element().surface())
|
||||
return image_data;
|
||||
auto const bitmap = canvas_element().surface()->create_snapshot();
|
||||
auto const snapshot = canvas_element().surface()->create_snapshot();
|
||||
auto const& bitmap = snapshot->bitmap();
|
||||
|
||||
// 5. Let the source rectangle be the rectangle whose corners are the four points (sx, sy), (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh).
|
||||
//<<<<<<< HEAD
|
||||
auto source_rect = Gfx::Rect { x, y, abs_width, abs_height };
|
||||
|
||||
// NOTE: The spec doesn't seem to define this behavior, but MDN does and the WPT tests
|
||||
|
@ -401,17 +405,17 @@ WebIDL::ExceptionOr<JS::GCPtr<ImageData>> CanvasRenderingContext2D::get_image_da
|
|||
if (width < 0 || height < 0) {
|
||||
source_rect = source_rect.translated(min(width, 0), min(height, 0));
|
||||
}
|
||||
auto source_rect_intersected = source_rect.intersected(bitmap->rect());
|
||||
auto source_rect_intersected = source_rect.intersected(bitmap.rect());
|
||||
|
||||
// 6. Set the pixel values of imageData to be the pixels of this's output bitmap in the area specified by the source rectangle in the bitmap's coordinate space units, converted from this's color space to imageData's colorSpace using 'relative-colorimetric' rendering intent.
|
||||
// NOTE: Internally we must use premultiplied alpha, but ImageData should hold unpremultiplied alpha. This conversion
|
||||
// might result in a loss of precision, but is according to spec.
|
||||
// See: https://html.spec.whatwg.org/multipage/canvas.html#premultiplied-alpha-and-the-2d-rendering-context
|
||||
ASSERT(bitmap->alpha_type() == Gfx::AlphaType::Premultiplied);
|
||||
ASSERT(bitmap.alpha_type() == Gfx::AlphaType::Premultiplied);
|
||||
ASSERT(image_data->bitmap().alpha_type() == Gfx::AlphaType::Unpremultiplied);
|
||||
|
||||
auto painter = Gfx::Painter::create(image_data->bitmap());
|
||||
painter->draw_bitmap(image_data->bitmap().rect().to_type<float>(), *bitmap, source_rect_intersected, Gfx::ScalingMode::NearestNeighbor, drawing_state().global_alpha);
|
||||
painter->draw_bitmap(image_data->bitmap().rect().to_type<float>(), bitmap, source_rect_intersected, Gfx::ScalingMode::NearestNeighbor, drawing_state().global_alpha);
|
||||
|
||||
// 7. Set the pixels values of imageData for areas of the source rectangle that are outside of the output bitmap to transparent black.
|
||||
// NOTE: No-op, already done during creation.
|
||||
|
|
|
@ -268,7 +268,8 @@ String HTMLCanvasElement::to_data_url(StringView type, Optional<double> quality)
|
|||
return "data:,"_string;
|
||||
|
||||
// 3. Let file be a serialization of this canvas element's bitmap as a file, passing type and quality if given.
|
||||
auto file = serialize_bitmap(*m_surface->create_snapshot(), type, move(quality));
|
||||
auto snapshot = m_surface->create_snapshot();
|
||||
auto file = serialize_bitmap(snapshot->bitmap(), type, move(quality));
|
||||
|
||||
// 4. If file is null then return "data:,".
|
||||
if (file.is_error()) {
|
||||
|
@ -300,7 +301,8 @@ WebIDL::ExceptionOr<void> HTMLCanvasElement::to_blob(JS::NonnullGCPtr<WebIDL::Ca
|
|||
// 3. If this canvas element's bitmap has pixels (i.e., neither its horizontal dimension nor its vertical dimension is zero),
|
||||
// then set result to a copy of this canvas element's bitmap.
|
||||
if (m_surface) {
|
||||
bitmap_result = m_surface->create_snapshot();
|
||||
auto snapshot = m_surface->create_snapshot();
|
||||
bitmap_result = snapshot->bitmap();
|
||||
}
|
||||
|
||||
// 4. Run these steps in parallel:
|
||||
|
|
|
@ -52,7 +52,7 @@ ErrorOr<JS::NonnullGCPtr<HTML::HTMLCanvasElement>, WebDriver::Error> draw_boundi
|
|||
// - Height: paint height
|
||||
Gfx::IntRect paint_rect { rect.x(), rect.y(), paint_width, paint_height };
|
||||
|
||||
auto backing_store = Web::Painting::BitmapBackingStore(canvas.surface()->create_snapshot());
|
||||
auto backing_store = Web::Painting::BitmapBackingStore(canvas.surface()->create_snapshot()->bitmap());
|
||||
browsing_context.page().client().paint(paint_rect.to_type<Web::DevicePixels>(), backing_store);
|
||||
|
||||
// 7. Return success with canvas.
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
#include <LibWeb/WebGL/OpenGLContext.h>
|
||||
|
||||
namespace Web::WebGL {
|
||||
|
||||
OwnPtr<OpenGLContext> OpenGLContext::create(Gfx::Bitmap& bitmap)
|
||||
OwnPtr<OpenGLContext> OpenGLContext::create(Gfx::PaintingSurface& bitmap)
|
||||
{
|
||||
(void)bitmap;
|
||||
return {};
|
||||
|
|
|
@ -13,9 +13,9 @@ namespace Web::WebGL {
|
|||
|
||||
class OpenGLContext {
|
||||
public:
|
||||
static OwnPtr<OpenGLContext> create(Gfx::Bitmap&);
|
||||
static OwnPtr<OpenGLContext> create(Gfx::PaintingSurface&);
|
||||
|
||||
virtual void present(Gfx::Bitmap&) = 0;
|
||||
virtual void present(Gfx::Bitmap const&) = 0;
|
||||
void clear_buffer_to_default_values();
|
||||
|
||||
virtual GLenum gl_get_error() = 0;
|
||||
|
|
|
@ -46,7 +46,7 @@ JS::ThrowCompletionOr<JS::GCPtr<WebGLRenderingContext>> WebGLRenderingContext::c
|
|||
}
|
||||
|
||||
VERIFY(canvas_element.surface());
|
||||
auto context = OpenGLContext::create(*canvas_element.surface()->create_snapshot());
|
||||
auto context = OpenGLContext::create(*canvas_element.surface());
|
||||
|
||||
if (!context) {
|
||||
fire_webgl_context_creation_error(canvas_element);
|
||||
|
|
|
@ -53,7 +53,7 @@ void WebGLRenderingContextBase::present()
|
|||
// FIXME: Is this the operation it means?
|
||||
m_context->gl_flush();
|
||||
|
||||
m_context->present(*canvas_element().surface()->create_snapshot());
|
||||
m_context->present(canvas_element().surface()->create_snapshot()->bitmap());
|
||||
|
||||
// "By default, after compositing the contents of the drawing buffer shall be cleared to their default values, as shown in the table above.
|
||||
// This default behavior can be changed by setting the preserveDrawingBuffer attribute of the WebGLContextAttributes object.
|
||||
|
|
Loading…
Reference in a new issue