1 /// @brief Include to use generic textures which can represent any texture target but they don't have target specific built-in caches making accesses slower.
2 /// @file gli/texture.hpp
3 
4 #pragma once
5 
6 #include "image.hpp"
7 #include "target.hpp"
8 #include "levels.hpp"
9 #include <array>
10 
11 namespace gli
12 {
13 	/// Genetic texture class. It can support any target.
14 	class texture
15 	{
16 	public:
17 		typedef size_t size_type;
18 		typedef gli::target target_type;
19 		typedef gli::format format_type;
20 		typedef gli::swizzles swizzles_type;
21 		typedef storage_linear storage_type;
22 		typedef storage_type::data_type data_type;
23 		typedef storage_type::extent_type extent_type;
24 
25 		/// Create an empty texture instance
26 		texture();
27 
28 		/// Create a texture object and allocate a texture storage for it
29 		/// @param Target Type/Shape of the texture storage_linear
30 		/// @param Format Texel format
31 		/// @param Extent Size of the texture: width, height and depth.
32 		/// @param Layers Number of one-dimensional or two-dimensional images of identical size and format
33 		/// @param Faces 6 for cube map textures otherwise 1.
34 		/// @param Levels Number of images in the texture mipmap chain.
35 		/// @param Swizzles A mechanism to swizzle the components of a texture before they are applied according to the texture environment.
36 		texture(
37 			target_type Target,
38 			format_type Format,
39 			extent_type const& Extent,
40 			size_type Layers,
41 			size_type Faces,
42 			size_type Levels,
43 			swizzles_type const& Swizzles = swizzles_type(SWIZZLE_RED, SWIZZLE_GREEN, SWIZZLE_BLUE, SWIZZLE_ALPHA));
44 
45 		/// Create a texture object by sharing an existing texture storage_type from another texture instance.
46 		/// This texture object is effectively a texture view where the layer, the face and the level allows identifying
47 		/// a specific subset of the texture storage_linear source.
48 		/// This texture object is effectively a texture view where the target and format can be reinterpreted
49 		/// with a different compatible texture target and texture format.
50 		texture(
51 			texture const& Texture,
52 			target_type Target,
53 			format_type Format,
54 			size_type BaseLayer, size_type MaxLayer,
55 			size_type BaseFace, size_type MaxFace,
56 			size_type BaseLevel, size_type MaxLevel,
57 			swizzles_type const& Swizzles = swizzles_type(SWIZZLE_RED, SWIZZLE_GREEN, SWIZZLE_BLUE, SWIZZLE_ALPHA));
58 
59 		/// Create a texture object by sharing an existing texture storage_type from another texture instance.
60 		/// This texture object is effectively a texture view where the target and format can be reinterpreted
61 		/// with a different compatible texture target and texture format.
62 		texture(
63 			texture const& Texture,
64 			target_type Target,
65 			format_type Format,
66 			swizzles_type const& Swizzles = swizzles_type(SWIZZLE_RED, SWIZZLE_GREEN, SWIZZLE_BLUE, SWIZZLE_ALPHA));
67 
~texture()68 		virtual ~texture(){}
69 
70 		/// Return whether the texture instance is empty, no storage_type or description have been assigned to the instance.
71 		bool empty() const;
72 
73 		/// Return the target of a texture instance.
target() const74 		target_type target() const{return this->Target;}
75 
76 		/// Return the texture instance format
77 		format_type format() const;
78 
79 		swizzles_type swizzles() const;
80 
81 		/// Return the base layer of the texture instance, effectively a memory offset in the actual texture storage_type to identify where to start reading the layers.
82 		size_type base_layer() const;
83 
84 		/// Return the max layer of the texture instance, effectively a memory offset to the beginning of the last layer in the actual texture storage_type that the texture instance can access.
85 		size_type max_layer() const;
86 
87 		/// Return max_layer() - base_layer() + 1
88 		size_type layers() const;
89 
90 		/// Return the base face of the texture instance, effectively a memory offset in the actual texture storage_type to identify where to start reading the faces.
91 		size_type base_face() const;
92 
93 		/// Return the max face of the texture instance, effectively a memory offset to the beginning of the last face in the actual texture storage_type that the texture instance can access.
94 		size_type max_face() const;
95 
96 		/// Return max_face() - base_face() + 1
97 		size_type faces() const;
98 
99 		/// Return the base level of the texture instance, effectively a memory offset in the actual texture storage_type to identify where to start reading the levels.
100 		size_type base_level() const;
101 
102 		/// Return the max level of the texture instance, effectively a memory offset to the beginning of the last level in the actual texture storage_type that the texture instance can access.
103 		size_type max_level() const;
104 
105 		/// Return max_level() - base_level() + 1.
106 		size_type levels() const;
107 
108 		/// Return the size of a texture instance: width, height and depth.
109 		extent_type extent(size_type Level = 0) const;
110 
111 		/// Return the memory size of a texture instance storage_type in bytes.
112 		size_type size() const;
113 
114 		/// Return the number of blocks contained in a texture instance storage_type.
115 		/// genType size must match the block size conresponding to the texture format.
116 		template <typename genType>
117 		size_type size() const;
118 
119 		/// Return the memory size of a specific level identified by Level.
120 		size_type size(size_type Level) const;
121 
122 		/// Return the memory size of a specific level identified by Level.
123 		/// genType size must match the block size conresponding to the texture format.
124 		template <typename gen_type>
125 		size_type size(size_type Level) const;
126 
127 		/// Return a pointer to the beginning of the texture instance data.
128 		void* data();
129 
130 		/// Return a pointer of type genType which size must match the texture format block size
131 		template <typename gen_type>
132 		gen_type* data();
133 
134 		/// Return a pointer to the beginning of the texture instance data.
135 		void const* data() const;
136 
137 		/// Return a pointer of type genType which size must match the texture format block size
138 		template <typename gen_type>
139 		gen_type const* data() const;
140 
141 		/// Return a pointer to the beginning of the texture instance data.
142 		void* data(size_type Layer, size_type Face, size_type Level);
143 
144 		/// Return a pointer to the beginning of the texture instance data.
145 		void const* const data(size_type Layer, size_type Face, size_type Level) const;
146 
147 		/// Return a pointer of type genType which size must match the texture format block size
148 		template <typename gen_type>
149 		gen_type* data(size_type Layer, size_type Face, size_type Level);
150 
151 		/// Return a pointer of type genType which size must match the texture format block size
152 		template <typename gen_type>
153 		gen_type const* const data(size_type Layer, size_type Face, size_type Level) const;
154 
155 		/// Clear the entire texture storage_linear with zeros
156 		void clear();
157 
158 		/// Clear the entire texture storage_linear with Texel which type must match the texture storage_linear format block size
159 		/// If the type of gen_type doesn't match the type of the texture format, no conversion is performed and the data will be reinterpreted as if is was of the texture format.
160 		template <typename gen_type>
161 		void clear(gen_type const& Texel);
162 
163 		/// Clear a specific image of a texture.
164 		template <typename gen_type>
165 		void clear(size_type Layer, size_type Face, size_type Level, gen_type const& BlockData);
166 
167 		/// Clear a subset of a specific image of a texture.
168 		template <typename gen_type>
169 		void clear(size_type Layer, size_type Face, size_type Level, extent_type const& TexelOffset, extent_type const& TexelExtent, gen_type const& BlockData);
170 
171 		/// Copy a specific image of a texture
172 		void copy(
173 			texture const& TextureSrc,
174 			size_t LayerSrc, size_t FaceSrc, size_t LevelSrc,
175 			size_t LayerDst, size_t FaceDst, size_t LevelDst);
176 
177 		/// Copy a subset of a specific image of a texture
178 		void copy(
179 			texture const& TextureSrc,
180 			size_t LayerSrc, size_t FaceSrc, size_t LevelSrc, extent_type const& OffsetSrc,
181 			size_t LayerDst, size_t FaceDst, size_t LevelDst, extent_type const& OffsetDst,
182 			extent_type const& Extent);
183 
184 		/// Reorder the component in texture memory.
185 		template <typename gen_type>
186 		void swizzle(gli::swizzles const& Swizzles);
187 
188 		/// Fetch a texel from a texture. The texture format must be uncompressed.
189 		template <typename gen_type>
190 		gen_type load(extent_type const & TexelCoord, size_type Layer, size_type Face, size_type Level) const;
191 
192 		/// Write a texel to a texture. The texture format must be uncompressed.
193 		template <typename gen_type>
194 		void store(extent_type const& TexelCoord, size_type Layer, size_type Face, size_type Level, gen_type const& Texel);
195 
196 	protected:
197 		std::shared_ptr<storage_type> Storage;
198 		target_type Target;
199 		format_type Format;
200 		size_type BaseLayer;
201 		size_type MaxLayer;
202 		size_type BaseFace;
203 		size_type MaxFace;
204 		size_type BaseLevel;
205 		size_type MaxLevel;
206 		swizzles_type Swizzles;
207 
208 		// Pre compute at texture instance creation some information for faster access to texels
209 		struct cache
210 		{
211 		public:
212 			enum ctor
213 			{
214 				DEFAULT
215 			};
216 
cachegli::texture::cache217 			explicit cache(ctor)
218 			{}
219 
cachegli::texture::cache220 			cache
221 			(
222 				storage_type& Storage,
223 				format_type Format,
224 				size_type BaseLayer, size_type Layers,
225 				size_type BaseFace, size_type MaxFace,
226 				size_type BaseLevel, size_type MaxLevel
227 			)
228 				: Faces(MaxFace - BaseFace + 1)
229 				, Levels(MaxLevel - BaseLevel + 1)
230 			{
231 				GLI_ASSERT(static_cast<size_t>(gli::levels(Storage.extent(0))) < this->ImageMemorySize.size());
232 
233 				this->BaseAddresses.resize(Layers * this->Faces * this->Levels);
234 
235 				for(size_type Layer = 0; Layer < Layers; ++Layer)
236 				for(size_type Face = 0; Face < this->Faces; ++Face)
237 				for(size_type Level = 0; Level < this->Levels; ++Level)
238 				{
239 					size_type const Index = index_cache(Layer, Face, Level);
240 					this->BaseAddresses[Index] = Storage.data() + Storage.base_offset(
241 						BaseLayer + Layer, BaseFace + Face, BaseLevel + Level);
242 				}
243 
244 				for(size_type Level = 0; Level < this->Levels; ++Level)
245 				{
246 					extent_type const& SrcExtent = Storage.extent(BaseLevel + Level);
247 					extent_type const& DstExtent = SrcExtent * block_extent(Format) / Storage.block_extent();
248 
249 					this->ImageExtent[Level] = glm::max(DstExtent, extent_type(1));
250 					this->ImageMemorySize[Level] = Storage.level_size(BaseLevel + Level);
251 				}
252 
253 				this->GlobalMemorySize = Storage.layer_size(BaseFace, MaxFace, BaseLevel, MaxLevel) * Layers;
254 			}
255 
256 			// Base addresses of each images of a texture.
get_base_addressgli::texture::cache257 			data_type* get_base_address(size_type Layer, size_type Face, size_type Level) const
258 			{
259 				return this->BaseAddresses[index_cache(Layer, Face, Level)];
260 			}
261 
262 			// In texels
get_extentgli::texture::cache263 			extent_type get_extent(size_type Level) const
264 			{
265 				return this->ImageExtent[Level];
266 			};
267 
268 			// In bytes
get_memory_sizegli::texture::cache269 			size_type get_memory_size(size_type Level) const
270 			{
271 				return this->ImageMemorySize[Level];
272 			};
273 
274 			// In bytes
get_memory_sizegli::texture::cache275 			size_type get_memory_size() const
276 			{
277 				return this->GlobalMemorySize;
278 			};
279 
280 		private:
index_cachegli::texture::cache281 			size_type index_cache(size_type Layer, size_type Face, size_type Level) const
282 			{
283 				return ((Layer * this->Faces) + Face) * this->Levels + Level;
284 			}
285 
286 			size_type Faces;
287 			size_type Levels;
288 			std::vector<data_type*> BaseAddresses;
289 			std::array<extent_type, 16> ImageExtent;
290 			std::array<size_type, 16> ImageMemorySize;
291 			size_type GlobalMemorySize;
292 		} Cache;
293 	};
294 }//namespace gli
295 
296 #include "./core/texture.inl"
297 
298