1/*!
2 * \file image_atlas.hpp
3 * \brief file image_atlas.hpp
4 *
5 * Copyright 2016 by Intel.
6 *
7 * Contact: kevin.rogovin@gmail.com
8 *
9 * This Source Code Form is subject to the
10 * terms of the Mozilla Public License, v. 2.0.
11 * If a copy of the MPL was not distributed with
12 * this file, You can obtain one at
13 * http://mozilla.org/MPL/2.0/.
14 *
15 * \author Kevin Rogovin <kevin.rogovin@gmail.com>
16 *
17 */
18
19
20
21#ifndef FASTUIDRAW_IMAGE_ATLAS_HPP
22#define FASTUIDRAW_IMAGE_ATLAS_HPP
23
24#include <fastuidraw/util/reference_counted.hpp>
25#include <fastuidraw/util/util.hpp>
26#include <fastuidraw/util/vecN.hpp>
27#include <fastuidraw/util/c_array.hpp>
28#include <fastuidraw/image.hpp>
29
30namespace fastuidraw
31{
32/*!\addtogroup PainterBackend
33 * @{
34 */
35
36 /*!
37 * \brief
38 * Represents the interface for a backing store for color data of images.
39 *
40 * For example in GL, this can be a GL_TEXTURE_2D_ARRAY. An implementation
41 * of the class does NOT need to be thread safe because the user of the
42 * backing store (ImageAtlas) performs calls to the backing store behind
43 * its own mutex.
44 */
45 class AtlasColorBackingStoreBase:
46 public reference_counted<AtlasColorBackingStoreBase>::concurrent
47 {
48 public:
49 virtual
50 ~AtlasColorBackingStoreBase();
51
52 /*!
53 * To be implemented by a derived class to set color data into the backing store.
54 * \param mimap_level what mipmap level
55 * \param dst_xy x and y coordinates of location to place data in the atlas
56 * \param dst_l layer of position to place data in the atlas
57 * \param src_xy x and y coordinates from which to take data from the ImageSourceBase
58 * \param size width and height of region to copy into the backing store.
59 * \param data ImageSourceBase from which to src data
60 */
61 virtual
62 void
63 set_data(int mimap_level, ivec2 dst_xy, int dst_l, ivec2 src_xy,
64 unsigned int size, const ImageSourceBase &data) = 0;
65
66 /*!
67 * To be implemented by a derived class to set color data into the backing store.
68 * \param mimap_level what mipmap level
69 * \param dst_xy x and y coordinates of location to place data in the atlas
70 * \param dst_l layer of position to place data in the atlas
71 * \param size width and height of region to copy into the backing store.
72 * \param color_value value with which to fill EVERY texel of the
73 */
74 virtual
75 void
76 set_data(int mimap_level, ivec2 dst_xy, int dst_l, unsigned int size, u8vec4 color_value) = 0;
77
78 /*!
79 * To be implemented by a derived class
80 * to flush set_data() to the backing
81 * store.
82 */
83 virtual
84 void
85 flush(void) = 0;
86
87 /*!
88 * Returns the dimensions of the backing store
89 * (as passed in the ctor).
90 */
91 ivec3
92 dimensions(void) const;
93
94 /*!
95 * Resize the object by increasing the number of layers.
96 */
97 void
98 resize(int new_num_layers);
99
100 protected:
101 /*!
102 * Ctor.
103 * \param whl provides the dimensions of the AtlasColorBackingStoreBase
104 */
105 explicit
106 AtlasColorBackingStoreBase(ivec3 whl);
107
108 /*!
109 * Ctor.
110 * \param w width of the backing store
111 * \param h height of the backing store
112 * \param num_layers number of layers of the backing store
113 */
114 AtlasColorBackingStoreBase(int w, int h, int num_layers);
115
116 /*!
117 * To be implemented by a derived class to resize the
118 * object. The resize changes ONLY the number of layers
119 * of the object and only increases the value as well.
120 * When called, the return value of dimensions() is
121 * the size before the resize completes.
122 * \param new_num_layers new number of layers to which
123 * to resize the underlying store.
124 */
125 virtual
126 void
127 resize_implement(int new_num_layers) = 0;
128
129 private:
130 void *m_d;
131 };
132
133 /*!
134 * \brief
135 * Represents the interface for the backing store for index data of images.
136 *
137 * For example in GL, this can be a GL_TEXTURE_2D_ARRAY. An implementation
138 * of the class does NOT need to be thread safe because the user of the
139 * backing store (ImageAtlas) performs calls to the backing store behind
140 * its own mutex.
141 */
142 class AtlasIndexBackingStoreBase:
143 public reference_counted<AtlasIndexBackingStoreBase>::concurrent
144 {
145 public:
146 virtual
147 ~AtlasIndexBackingStoreBase();
148
149 /*!
150 * To be implemented by a derived class to fill index data into the
151 * backing store. The index data passed references back into this
152 * AtlasIndexBackingStore.
153 * \param x horizontal position
154 * \param y vertical position
155 * \param l layer position
156 * \param w width of data
157 * \param h height of data
158 * \param data list of tiles as returned by ImageAtlas::add_index_tile()
159 */
160 virtual
161 void
162 set_data(int x, int y, int l, int w, int h,
163 c_array<const ivec3> data) = 0;
164
165 /*!
166 * To be implemented by a derived class
167 * to flush set_data() to the backing
168 * store.
169 */
170 virtual
171 void
172 flush(void) = 0;
173
174 /*!
175 * Returns the dimensions of the backing store
176 * (as passed in the ctor).
177 */
178 ivec3
179 dimensions(void) const;
180
181 /*!
182 * Resize the object by increasing the number of layers.
183 */
184 void
185 resize(int new_num_layers);
186
187 protected:
188 /*!
189 * Ctor.
190 * \param whl dimensions of the backing store
191 */
192 explicit
193 AtlasIndexBackingStoreBase(ivec3 whl);
194
195 /*!
196 * Ctor.
197 * \param w width of the backing store
198 * \param h height of the backing store
199 * \param l number layers of the backing store
200 */
201 AtlasIndexBackingStoreBase(int w, int h, int l);
202
203 /*!
204 * To be implemented by a derived class to resize the
205 * object. The resize changes ONLY the number of layers
206 * of the object and only increases the value as well.
207 * When called, the return value of dimensions() is
208 * the size before the resize completes.
209 * \param new_num_layers new number of layers to which
210 * to resize the underlying store.
211 */
212 virtual
213 void
214 resize_implement(int new_num_layers) = 0;
215
216 private:
217 void *m_d;
218 };
219/*! @} */
220
221/*!\addtogroup Imaging
222 * @{
223 */
224
225 /*!
226 * \brief
227 * An ImageAtlas is a common location to place images of an application.
228 *
229 * Ideally, all images are placed into a single ImageAtlas (changes of
230 * ImageAtlas force draw-call breaks). Methods of ImageAtlas are
231 * thread safe, locked behind a mutex of the ImageAtlas.
232 */
233 class ImageAtlas:
234 public reference_counted<ImageAtlas>::concurrent
235 {
236 public:
237 virtual
238 ~ImageAtlas();
239
240 /*!
241 * Construct an \ref Image
242 * \param w width of the image
243 * \param h height of the image
244 * \param image_data image data to which to initialize the image
245 * \param type the preferred value for Image::type() for the
246 * returned \ref Image \ref Image::bindless_texture2d
247 * will fallback to \ref Image::on_atlas and \ref
248 * Image::on_atlas will fallback to \ref
249 * Image::context_texture2d
250 */
251 reference_counted_ptr<Image>
252 create(int w, int h, const ImageSourceBase &image_data,
253 enum Image::type_t type = Image::bindless_texture2d);
254
255 /*!
256 * Construct an \ref Image whose \ref Image::type() is NOT
257 * \ref Image::on_atlas. Will first try to construct an \ref
258 * Image whose \ref Image::type() is \ref Image::bindless_texture2d
259 * and if that failes will instead construct an \ref Image
260 * whose \ref Image::type() is \ref Image::context_texture2d
261 * \param w width of the image
262 * \param h height of the image
263 * \param image_data image data to which to initialize the image
264 */
265 reference_counted_ptr<Image>
266 create_non_atlas(int w, int h, const ImageSourceBase &image_data);
267
268 /*!
269 * Returns the size (in texels) used for the index tiles.
270 */
271 int
272 index_tile_size(void) const;
273
274 /*!
275 * Returns the size (in texels) used for the color tiles.
276 */
277 int
278 color_tile_size(void) const;
279
280 /*!
281 * Calls AtlasIndexBackingStoreBase::flush() on
282 * the index backing store (see index_store())
283 * and AtlasColorBackingStoreBase::flush() on
284 * the color backing store (see color_store()).
285 */
286 void
287 flush(void) const;
288
289 /*!
290 * Returns a handle to the backing store for the image data.
291 */
292 const reference_counted_ptr<const AtlasColorBackingStoreBase>&
293 color_store(void) const;
294
295 /*!
296 * Returns a handle to the backing store for the index data.
297 */
298 const reference_counted_ptr<const AtlasIndexBackingStoreBase>&
299 index_store(void) const;
300
301 /*!
302 * Increments an internal counter. If this internal
303 * counter is greater than zero, then the reurning
304 * of tiles to the free store for later use is
305 * -delayed- until the counter reaches zero again
306 * (see unlock_resources()). The use case is for
307 * buffered painting where the GPU calls are delayed
308 * for later (to batch commands) and an Image may go
309 * out of scope before the GPU commands are sent to
310 * the GPU. By delaying the return of an Image's
311 * tiles to the freestore, the image data is valid
312 * still for rendering.
313 */
314 void
315 lock_resources(void);
316
317 /*!
318 * Decrements an internal counter. If this internal
319 * counter reaches zero, those tiles from Image's
320 * that were deleted while the counter was non-zero,
321 * are then returned to the tile free store. See
322 * lock_resources() for more details.
323 */
324 void
325 unlock_resources(void);
326
327 /*!
328 * Queue a ResourceReleaseAction to be executed when resources are
329 * not locked down, see lock_resources() and unlock_resources().
330 */
331 void
332 queue_resource_release_action(const reference_counted_ptr<Image::ResourceReleaseAction> &action);
333
334 protected:
335 /*!
336 * Ctor.
337 * \param pcolor_tile_size size of each color tile, a value of 0 indicates
338 * that atlased Images are not allowed.
339 * \param pindex_tile_size size of each index tile, a value of 0 indicates
340 * that atlased Images are not allowed.
341 * \param pcolor_store color data backing store for atlas, the width and
342 * height of the backing store must be divisible by
343 * pcolor_tile_size.
344 * \param pindex_store index backing store for atlas, the width and
345 * height of the backing store must be divisible by
346 * pindex_tile_size.
347 */
348 ImageAtlas(int pcolor_tile_size, int pindex_tile_size,
349 reference_counted_ptr<AtlasColorBackingStoreBase> pcolor_store,
350 reference_counted_ptr<AtlasIndexBackingStoreBase> pindex_store);
351
352 private:
353 friend class Image;
354
355 /*!
356 * Construct an \ref Image backed by an \ref ImageAtlas. If there is
357 * insufficient room on the atlas, returns a nullptr handle.
358 * \param w width of the image
359 * \param h height of the image
360 * \param image_data image data to which to initialize the image
361 */
362 reference_counted_ptr<Image>
363 create_image_on_atlas(int w, int h, const ImageSourceBase &image_data);
364
365 /*!
366 * To be implemented by a derived class to create an Image whose
367 * Image::type() is \ref Image::bindless_texture2d. If a bindless
368 * API is not supported by the 3D API, then shall return nullptr.
369 * \param w width of the image
370 * \param h height of the image
371 * \param image_data image data to which to initialize the image
372 */
373 virtual
374 reference_counted_ptr<Image>
375 create_image_bindless(int w, int h, const ImageSourceBase &image_data) = 0;
376
377 /*!
378 * To be implemented by a derived class to create an Image whose
379 * Image::type() is \ref Image::context_texture2d. This method cannot
380 * ever fail.
381 * \param w width of the image
382 * \param h height of the image
383 * \param image_data image data to which to initialize the image
384 */
385 virtual
386 reference_counted_ptr<Image>
387 create_image_context_texture2d(int w, int h, const ImageSourceBase &image_data) = 0;
388
389 void *m_d;
390 };
391
392/*! @} */
393
394} //namespace
395
396#endif
397