mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-14 21:42:19 +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: a2c33ea4e1
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 AntiAliasingPainter;
|
||||||
class DeprecatedPainter;
|
class DeprecatedPainter;
|
||||||
class Painter;
|
class Painter;
|
||||||
|
class PaintingSurface;
|
||||||
class Palette;
|
class Palette;
|
||||||
class PaletteImpl;
|
class PaletteImpl;
|
||||||
class DeprecatedPath;
|
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
|
* 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
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
|
#include <LibGfx/ImmutableBitmap.h>
|
||||||
#include <LibGfx/PaintingSurface.h>
|
#include <LibGfx/PaintingSurface.h>
|
||||||
|
|
||||||
#include <core/SkColorSpace.h>
|
#include <core/SkColorSpace.h>
|
||||||
|
@ -91,13 +92,13 @@ PaintingSurface::PaintingSurface(NonnullOwnPtr<Impl>&& impl)
|
||||||
|
|
||||||
PaintingSurface::~PaintingSurface() = default;
|
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 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);
|
auto image_info = SkImageInfo::Make(bitmap->width(), bitmap->height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType);
|
||||||
SkPixmap const pixmap(image_info, bitmap->begin(), bitmap->pitch());
|
SkPixmap const pixmap(image_info, bitmap->begin(), bitmap->pitch());
|
||||||
sk_surface().readPixels(pixmap, 0, 0);
|
sk_surface().readPixels(pixmap, 0, 0);
|
||||||
return bitmap;
|
return ImmutableBitmap::create(bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintingSurface::read_into_bitmap(Gfx::Bitmap& bitmap)
|
void PaintingSurface::read_into_bitmap(Gfx::Bitmap& bitmap)
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
static NonnullRefPtr<PaintingSurface> wrap_metal_surface(Gfx::MetalTexture&, RefPtr<SkiaBackendContext>);
|
static NonnullRefPtr<PaintingSurface> wrap_metal_surface(Gfx::MetalTexture&, RefPtr<SkiaBackendContext>);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RefPtr<Bitmap> create_snapshot() const;
|
NonnullRefPtr<ImmutableBitmap> create_snapshot() const;
|
||||||
void read_into_bitmap(Bitmap&);
|
void read_into_bitmap(Bitmap&);
|
||||||
|
|
||||||
IntSize size() const;
|
IntSize size() const;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, MacDue <macdue@dueutil.tech>
|
* Copyright (c) 2023, MacDue <macdue@dueutil.tech>
|
||||||
|
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -130,7 +131,10 @@ WebIDL::ExceptionOr<JS::GCPtr<CanvasPattern>> CanvasPattern::create(JS::Realm& r
|
||||||
auto bitmap = image.visit(
|
auto bitmap = image.visit(
|
||||||
[](JS::Handle<HTMLImageElement> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); },
|
[](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<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<HTMLVideoElement> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); },
|
||||||
[](JS::Handle<ImageBitmap> 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) 2020-2024, Andreas Kling <andreas@ladybird.org>
|
||||||
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
|
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
|
||||||
* Copyright (c) 2023, MacDue <macdue@dueutil.tech>
|
* Copyright (c) 2023, MacDue <macdue@dueutil.tech>
|
||||||
|
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -125,7 +126,10 @@ WebIDL::ExceptionOr<void> CanvasRenderingContext2D::draw_image_internal(CanvasIm
|
||||||
auto bitmap = image.visit(
|
auto bitmap = image.visit(
|
||||||
[](JS::Handle<HTMLImageElement> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); },
|
[](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<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<HTMLVideoElement> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); },
|
||||||
[](JS::Handle<ImageBitmap> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); });
|
[](JS::Handle<ImageBitmap> const& source) -> RefPtr<Gfx::Bitmap> { return *source->bitmap(); });
|
||||||
if (!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).
|
// 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())
|
if (!canvas_element().surface())
|
||||||
return image_data;
|
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).
|
// 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 };
|
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
|
// 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) {
|
if (width < 0 || height < 0) {
|
||||||
source_rect = source_rect.translated(min(width, 0), min(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.
|
// 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
|
// 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.
|
// 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
|
// 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);
|
ASSERT(image_data->bitmap().alpha_type() == Gfx::AlphaType::Unpremultiplied);
|
||||||
|
|
||||||
auto painter = Gfx::Painter::create(image_data->bitmap());
|
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.
|
// 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.
|
// NOTE: No-op, already done during creation.
|
||||||
|
|
|
@ -268,7 +268,8 @@ String HTMLCanvasElement::to_data_url(StringView type, Optional<double> quality)
|
||||||
return "data:,"_string;
|
return "data:,"_string;
|
||||||
|
|
||||||
// 3. Let file be a serialization of this canvas element's bitmap as a file, passing type and quality if given.
|
// 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:,".
|
// 4. If file is null then return "data:,".
|
||||||
if (file.is_error()) {
|
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),
|
// 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.
|
// then set result to a copy of this canvas element's bitmap.
|
||||||
if (m_surface) {
|
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:
|
// 4. Run these steps in parallel:
|
||||||
|
|
|
@ -52,7 +52,7 @@ ErrorOr<JS::NonnullGCPtr<HTML::HTMLCanvasElement>, WebDriver::Error> draw_boundi
|
||||||
// - Height: paint height
|
// - Height: paint height
|
||||||
Gfx::IntRect paint_rect { rect.x(), rect.y(), paint_width, 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);
|
browsing_context.page().client().paint(paint_rect.to_type<Web::DevicePixels>(), backing_store);
|
||||||
|
|
||||||
// 7. Return success with canvas.
|
// 7. Return success with canvas.
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
|
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
|
#include <LibGfx/Forward.h>
|
||||||
#include <LibWeb/WebGL/OpenGLContext.h>
|
#include <LibWeb/WebGL/OpenGLContext.h>
|
||||||
|
|
||||||
namespace Web::WebGL {
|
namespace Web::WebGL {
|
||||||
|
|
||||||
OwnPtr<OpenGLContext> OpenGLContext::create(Gfx::Bitmap& bitmap)
|
OwnPtr<OpenGLContext> OpenGLContext::create(Gfx::PaintingSurface& bitmap)
|
||||||
{
|
{
|
||||||
(void)bitmap;
|
(void)bitmap;
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -13,9 +13,9 @@ namespace Web::WebGL {
|
||||||
|
|
||||||
class OpenGLContext {
|
class OpenGLContext {
|
||||||
public:
|
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();
|
void clear_buffer_to_default_values();
|
||||||
|
|
||||||
virtual GLenum gl_get_error() = 0;
|
virtual GLenum gl_get_error() = 0;
|
||||||
|
|
|
@ -46,7 +46,7 @@ JS::ThrowCompletionOr<JS::GCPtr<WebGLRenderingContext>> WebGLRenderingContext::c
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY(canvas_element.surface());
|
VERIFY(canvas_element.surface());
|
||||||
auto context = OpenGLContext::create(*canvas_element.surface()->create_snapshot());
|
auto context = OpenGLContext::create(*canvas_element.surface());
|
||||||
|
|
||||||
if (!context) {
|
if (!context) {
|
||||||
fire_webgl_context_creation_error(canvas_element);
|
fire_webgl_context_creation_error(canvas_element);
|
||||||
|
|
|
@ -53,7 +53,7 @@ void WebGLRenderingContextBase::present()
|
||||||
// FIXME: Is this the operation it means?
|
// FIXME: Is this the operation it means?
|
||||||
m_context->gl_flush();
|
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.
|
// "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.
|
// This default behavior can be changed by setting the preserveDrawingBuffer attribute of the WebGLContextAttributes object.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue