mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 11:12:45 +00:00 
			
		
		
		
	LibWeb: Share decoded images at the Resource level :^)
This patch adds ImageResource as a subclass of Resource. This new class also keeps a Gfx::ImageDecoder so that we can share decoded bitmaps between all clients of an image resource inside LibWeb. With this, we now share both encoded and decoded data for images. :^) I had to change how the purgeable-volatile flag is updated to keep the volatile-images-outside-the-visible-viewport optimization working. HTMLImageElement now inherits from ImageResourceClient (a subclass of ResourceClient with additional image-specific stuff) and informs its ImageResource about whether it's inside the viewport or outside. This is pretty awesome! :^)
This commit is contained in:
		
							parent
							
								
									1c6e4e04a8
								
							
						
					
					
						commit
						d4ddb0013c
					
				
					 14 changed files with 200 additions and 30 deletions
				
			
		
							
								
								
									
										80
									
								
								Libraries/LibWeb/Loader/ImageResource.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								Libraries/LibWeb/Loader/ImageResource.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,80 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  * | ||||
|  * 1. Redistributions of source code must retain the above copyright notice, this | ||||
|  *    list of conditions and the following disclaimer. | ||||
|  * | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
|  *    this list of conditions and the following disclaimer in the documentation | ||||
|  *    and/or other materials provided with the distribution. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
|  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
|  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
|  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
|  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #include <AK/Function.h> | ||||
| #include <LibGfx/Bitmap.h> | ||||
| #include <LibGfx/ImageDecoder.h> | ||||
| #include <LibWeb/Loader/ImageResource.h> | ||||
| 
 | ||||
| namespace Web { | ||||
| 
 | ||||
| ImageResource::ImageResource(const LoadRequest& request) | ||||
|     : Resource(Type::Image, request) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| ImageResource::~ImageResource() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| Gfx::ImageDecoder& ImageResource::ensure_decoder() | ||||
| { | ||||
|     if (!m_decoder) | ||||
|         m_decoder = Gfx::ImageDecoder::create(encoded_data()); | ||||
|     return *m_decoder; | ||||
| } | ||||
| 
 | ||||
| void ImageResource::update_volatility() | ||||
| { | ||||
|     if (!m_decoder) | ||||
|         return; | ||||
| 
 | ||||
|     bool visible_in_viewport = false; | ||||
|     for_each_client([&](auto& client) { | ||||
|         if (static_cast<const ImageResourceClient&>(client).is_visible_in_viewport()) | ||||
|             visible_in_viewport = true; | ||||
|     }); | ||||
| 
 | ||||
|     if (!visible_in_viewport) { | ||||
|         m_decoder->set_volatile(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     bool still_has_decoded_image = m_decoder->set_nonvolatile(); | ||||
|     if (still_has_decoded_image) | ||||
|         return; | ||||
| 
 | ||||
|     m_decoder = nullptr; | ||||
|     for_each_client([&](auto& client) { | ||||
|         static_cast<ImageResourceClient&>(client).resource_did_replace_decoder(); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| ImageResourceClient::~ImageResourceClient() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										59
									
								
								Libraries/LibWeb/Loader/ImageResource.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								Libraries/LibWeb/Loader/ImageResource.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  * | ||||
|  * 1. Redistributions of source code must retain the above copyright notice, this | ||||
|  *    list of conditions and the following disclaimer. | ||||
|  * | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
|  *    this list of conditions and the following disclaimer in the documentation | ||||
|  *    and/or other materials provided with the distribution. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
|  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
|  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
|  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
|  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <LibWeb/Loader/Resource.h> | ||||
| 
 | ||||
| namespace Web { | ||||
| 
 | ||||
| class ImageResource final : public Resource { | ||||
|     friend class Resource; | ||||
| 
 | ||||
| public: | ||||
|     virtual ~ImageResource() override; | ||||
|     Gfx::ImageDecoder& ensure_decoder(); | ||||
| 
 | ||||
|     void update_volatility(); | ||||
| 
 | ||||
| private: | ||||
|     explicit ImageResource(const LoadRequest&); | ||||
|     RefPtr<Gfx::ImageDecoder> m_decoder; | ||||
| }; | ||||
| 
 | ||||
| class ImageResourceClient : public ResourceClient { | ||||
| public: | ||||
|     virtual ~ImageResourceClient(); | ||||
| 
 | ||||
|     virtual bool is_visible_in_viewport() const { return false; } | ||||
|     virtual void resource_did_replace_decoder() {} | ||||
| 
 | ||||
| protected: | ||||
|     ImageResource* resource() { return static_cast<ImageResource*>(ResourceClient::resource()); } | ||||
|     const ImageResource* resource() const { return static_cast<const ImageResource*>(ResourceClient::resource()); } | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | @ -30,13 +30,16 @@ | |||
| 
 | ||||
| namespace Web { | ||||
| 
 | ||||
| NonnullRefPtr<Resource> Resource::create(Badge<ResourceLoader>, const LoadRequest& request) | ||||
| NonnullRefPtr<Resource> Resource::create(Badge<ResourceLoader>, Type type, const LoadRequest& request) | ||||
| { | ||||
|     return adopt(*new Resource(request)); | ||||
|     if (type == Type::Image) | ||||
|         return adopt(*new ImageResource(request)); | ||||
|     return adopt(*new Resource(type, request)); | ||||
| } | ||||
| 
 | ||||
| Resource::Resource(const LoadRequest& request) | ||||
| Resource::Resource(Type type, const LoadRequest& request) | ||||
|     : m_request(request) | ||||
|     , m_type(type) | ||||
| { | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -34,6 +34,7 @@ | |||
| #include <AK/URL.h> | ||||
| #include <AK/WeakPtr.h> | ||||
| #include <AK/Weakable.h> | ||||
| #include <LibGfx/Forward.h> | ||||
| #include <LibWeb/Forward.h> | ||||
| #include <LibWeb/Loader/LoadRequest.h> | ||||
| 
 | ||||
|  | @ -46,8 +47,13 @@ class Resource : public RefCounted<Resource> { | |||
|     AK_MAKE_NONMOVABLE(Resource); | ||||
| 
 | ||||
| public: | ||||
|     static NonnullRefPtr<Resource> create(Badge<ResourceLoader>, const LoadRequest&); | ||||
|     ~Resource(); | ||||
|     enum class Type { | ||||
|         Generic, | ||||
|         Image, | ||||
|     }; | ||||
| 
 | ||||
|     static NonnullRefPtr<Resource> create(Badge<ResourceLoader>, Type, const LoadRequest&); | ||||
|     virtual ~Resource(); | ||||
| 
 | ||||
|     bool is_loaded() const { return m_loaded; } | ||||
| 
 | ||||
|  | @ -67,11 +73,13 @@ public: | |||
|     void did_load(Badge<ResourceLoader>, const ByteBuffer& data, const HashMap<String, String, CaseInsensitiveStringTraits>& headers); | ||||
|     void did_fail(Badge<ResourceLoader>, const String& error); | ||||
| 
 | ||||
| private: | ||||
|     explicit Resource(const LoadRequest&); | ||||
| protected: | ||||
|     explicit Resource(Type, const LoadRequest&); | ||||
| 
 | ||||
| private: | ||||
|     LoadRequest m_request; | ||||
|     ByteBuffer m_encoded_data; | ||||
|     Type m_type { Type::Generic }; | ||||
|     bool m_loaded { false }; | ||||
|     bool m_failed { false }; | ||||
|     String m_error; | ||||
|  |  | |||
|  | @ -72,7 +72,7 @@ void ResourceLoader::load_sync(const URL& url, Function<void(const ByteBuffer&, | |||
| 
 | ||||
| static HashMap<LoadRequest, NonnullRefPtr<Resource>> s_resource_cache; | ||||
| 
 | ||||
| RefPtr<Resource> ResourceLoader::load_resource(const LoadRequest& request) | ||||
| RefPtr<Resource> ResourceLoader::load_resource(Resource::Type type, const LoadRequest& request) | ||||
| { | ||||
|     if (!request.is_valid()) | ||||
|         return nullptr; | ||||
|  | @ -83,7 +83,7 @@ RefPtr<Resource> ResourceLoader::load_resource(const LoadRequest& request) | |||
|         return it->value; | ||||
|     } | ||||
| 
 | ||||
|     auto resource = Resource::create({}, request); | ||||
|     auto resource = Resource::create({}, type, request); | ||||
| 
 | ||||
|     s_resource_cache.set(request, resource); | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ | |||
| #include <AK/Function.h> | ||||
| #include <AK/URL.h> | ||||
| #include <LibCore/Object.h> | ||||
| #include <LibWeb/Forward.h> | ||||
| #include <LibWeb/Loader/Resource.h> | ||||
| 
 | ||||
| namespace Protocol { | ||||
| class Client; | ||||
|  | @ -42,7 +42,7 @@ class ResourceLoader : public Core::Object { | |||
| public: | ||||
|     static ResourceLoader& the(); | ||||
| 
 | ||||
|     RefPtr<Resource> load_resource(const LoadRequest&); | ||||
|     RefPtr<Resource> load_resource(Resource::Type, const LoadRequest&); | ||||
| 
 | ||||
|     void load(const URL&, Function<void(const ByteBuffer&, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers)> success_callback, Function<void(const String&)> error_callback = nullptr); | ||||
|     void load_sync(const URL&, Function<void(const ByteBuffer&, const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers)> success_callback, Function<void(const String&)> error_callback = nullptr); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling