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 | |
30 | namespace 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 | |