1 /* Copyright (c) 2017-2018 Hans-Kristian Arntzen
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be
12  * included in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #pragma once
24 
25 #include "volatile_source.hpp"
26 #include "image.hpp"
27 #include "async_object_sink.hpp"
28 
29 namespace Granite
30 {
31 namespace SceneFormats
32 {
33 class MemoryMappedTexture;
34 }
35 }
36 
37 namespace Vulkan
38 {
39 class Texture : public Util::VolatileSource<Texture>,
40                 public Util::IntrusiveHashMapEnabled<Texture>
41 {
42 public:
43 	friend class Util::VolatileSource<Texture>;
44 
45 	Texture(Device *device, const std::string &path, VkFormat format = VK_FORMAT_UNDEFINED,
46 	        const VkComponentMapping &swizzle = {
47 			        VK_COMPONENT_SWIZZLE_R,
48 			        VK_COMPONENT_SWIZZLE_G,
49 			        VK_COMPONENT_SWIZZLE_B,
50 			        VK_COMPONENT_SWIZZLE_A });
51 
52 	Texture(Device *device);
53 	void set_path(const std::string &path);
54 
55 	Image *get_image();
56 
57 	void replace_image(ImageHandle handle);
58 	void set_enable_notification(bool enable);
59 
60 private:
61 	Device *device;
62 	Util::AsyncObjectSink<ImageHandle> handle;
63 	VkFormat format;
64 	VkComponentMapping swizzle;
65 	void update_other(const void *data, size_t size);
66 	void update_gtx(std::unique_ptr<Granite::File> file, void *mapped);
67 	void update_gtx(const Granite::SceneFormats::MemoryMappedTexture &texture);
68 	void update_checkerboard();
69 
70 	void load();
71 	void unload();
72 	void update(std::unique_ptr<Granite::File> file);
73 	bool enable_notification = true;
74 };
75 
76 class TextureManager
77 {
78 public:
79 	TextureManager(Device *device);
80 	Texture *request_texture(const std::string &path, VkFormat format = VK_FORMAT_UNDEFINED,
81 	                         const VkComponentMapping &swizzle = {
82 			                         VK_COMPONENT_SWIZZLE_R,
83 			                         VK_COMPONENT_SWIZZLE_G,
84 			                         VK_COMPONENT_SWIZZLE_B,
85 			                         VK_COMPONENT_SWIZZLE_A });
86 
87 	Texture *register_deferred_texture(const std::string &path);
88 
89 	void register_texture_update_notification(const std::string &modified_path,
90 	                                          std::function<void (Texture &)> func);
91 
92 	void notify_updated_texture(const std::string &path, Vulkan::Texture &texture);
93 
94 private:
95 	Device *device;
96 
97 	VulkanCache<Texture> textures;
98 	VulkanCache<Texture> deferred_textures;
99 
100 	std::unordered_map<std::string, std::vector<std::function<void (Texture &)>>> notifications;
101 };
102 }
103