1 | /*! |
2 | * \file image.cpp |
3 | * \brief file image.cpp |
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 | #include <list> |
21 | #include <map> |
22 | #include <mutex> |
23 | #include <fastuidraw/image.hpp> |
24 | #include <fastuidraw/image_atlas.hpp> |
25 | #include <private/array3d.hpp> |
26 | #include <private/util_private.hpp> |
27 | |
28 | namespace |
29 | { |
30 | /* |
31 | * Copies from src the rectangle: |
32 | * [source_x, source_x + dest_dim) x [source_y, source_y + dest_dim) |
33 | * to dest. |
34 | * |
35 | * If source_x is negative, then pads each line with the value |
36 | * from src at x=0. |
37 | * |
38 | * If source_y is negative, the source for those lines is |
39 | * taken from src at y=0. |
40 | * |
41 | * For pixel (x,y) with x < 0, takes the value |
42 | * from source at (0, y). |
43 | * |
44 | * For pixel (x,y) with y < 0, takes the value |
45 | * from source at (x, 0). |
46 | * |
47 | * For pixels (x,y) with x >= src_dims.x(), takes the value |
48 | * from source at (src_dims.x() - 1, y). |
49 | * |
50 | * For pixels (x,y) with y >= src_dims.y(), takes the value |
51 | * from source at (x, src_dims.y() - 1). |
52 | * |
53 | * \param dest_dim width and height of destination |
54 | * \param src_dims width and height of source |
55 | * \param source_x, source_y location within src from which to copy |
56 | * \param src: src pixels |
57 | * \param dest: destination pixels |
58 | * |
59 | * If all texel are the same value, returns true. |
60 | */ |
61 | template<typename T, typename S> |
62 | void |
63 | copy_sub_data(fastuidraw::c_array<T> dest, |
64 | int w, int h, |
65 | fastuidraw::c_array<const S> src, |
66 | int source_x, int source_y, |
67 | fastuidraw::ivec2 src_dims) |
68 | { |
69 | using namespace fastuidraw; |
70 | |
71 | FASTUIDRAWassert(w > 0); |
72 | FASTUIDRAWassert(h > 0); |
73 | FASTUIDRAWassert(src_dims.x() > 0); |
74 | FASTUIDRAWassert(src_dims.y() > 0); |
75 | |
76 | for(int src_y = source_y, dst_y = 0; dst_y < h; ++src_y, ++dst_y) |
77 | { |
78 | c_array<const S> line_src; |
79 | c_array<T> line_dest; |
80 | int dst_x, src_x, src_start; |
81 | |
82 | line_dest = dest.sub_array(dst_y * w, w); |
83 | if (src_y < 0) |
84 | { |
85 | src_start = 0; |
86 | } |
87 | else if (src_y >= src_dims.y()) |
88 | { |
89 | src_start = (src_dims.y() - 1) * src_dims.x(); |
90 | } |
91 | else |
92 | { |
93 | src_start = src_y * src_dims.x(); |
94 | } |
95 | line_src = src.sub_array(src_start, src_dims.x()); |
96 | |
97 | for(src_x = source_x, dst_x = 0; src_x < 0; ++src_x, ++dst_x) |
98 | { |
99 | line_dest[dst_x] = line_src[0]; |
100 | } |
101 | |
102 | for(src_x = t_max(0, source_x); |
103 | src_x < src_dims.x() && dst_x < w; |
104 | ++src_x, ++dst_x) |
105 | { |
106 | line_dest[dst_x] = line_src[src_x]; |
107 | } |
108 | |
109 | for(;dst_x < w; ++dst_x) |
110 | { |
111 | line_dest[dst_x] = line_src[src_dims.x() - 1]; |
112 | } |
113 | } |
114 | } |
115 | |
116 | fastuidraw::ivec2 |
117 | divide_up(fastuidraw::ivec2 numerator, int denominator) |
118 | { |
119 | fastuidraw::ivec2 R; |
120 | R = numerator / denominator; |
121 | if (numerator.x() % denominator != 0) |
122 | { |
123 | ++R.x(); |
124 | } |
125 | if (numerator.y() % denominator != 0) |
126 | { |
127 | ++R.y(); |
128 | } |
129 | return R; |
130 | } |
131 | |
132 | int |
133 | number_index_tiles_needed(fastuidraw::ivec2 number_color_tiles, |
134 | int index_tile_size) |
135 | { |
136 | int return_value = 1; |
137 | fastuidraw::ivec2 tile_count = divide_up(number_color_tiles, index_tile_size); |
138 | |
139 | while(tile_count.x() > 1 || tile_count.y() > 1) |
140 | { |
141 | return_value += tile_count.x() * tile_count.y(); |
142 | tile_count = divide_up(tile_count, index_tile_size); |
143 | } |
144 | |
145 | return return_value; |
146 | } |
147 | |
148 | class BackingStorePrivate |
149 | { |
150 | public: |
151 | BackingStorePrivate(fastuidraw::ivec3 whl): |
152 | m_dimensions(whl) |
153 | {} |
154 | |
155 | BackingStorePrivate(int w, int h, int num_layers): |
156 | m_dimensions(w, h, num_layers) |
157 | {} |
158 | |
159 | fastuidraw::ivec3 m_dimensions; |
160 | }; |
161 | |
162 | class inited_bool |
163 | { |
164 | public: |
165 | bool m_value; |
166 | inited_bool(bool b = false):m_value(b) {} |
167 | }; |
168 | |
169 | class tile_allocator |
170 | { |
171 | public: |
172 | tile_allocator(int tile_size, fastuidraw::ivec3 store_dimensions); |
173 | |
174 | ~tile_allocator(); |
175 | |
176 | fastuidraw::ivec3 |
177 | allocate_tile(void); |
178 | |
179 | void |
180 | delete_tile(fastuidraw::ivec3 v); |
181 | |
182 | int |
183 | number_free(void) const; |
184 | |
185 | bool |
186 | resize_to_fit(int num_tiles); |
187 | |
188 | void |
189 | lock_resources(void); |
190 | |
191 | void |
192 | unlock_resources(void); |
193 | |
194 | int |
195 | tile_size(void) const |
196 | { |
197 | return m_tile_size; |
198 | } |
199 | |
200 | const fastuidraw::ivec3& |
201 | num_tiles(void) const |
202 | { |
203 | return m_num_tiles; |
204 | } |
205 | |
206 | private: |
207 | void |
208 | delete_tile_implement(fastuidraw::ivec3 v); |
209 | |
210 | int m_tile_size; |
211 | fastuidraw::ivec3 m_next_tile; |
212 | fastuidraw::ivec3 m_num_tiles; |
213 | std::vector<fastuidraw::ivec3> m_free_tiles; |
214 | int m_tile_count; |
215 | |
216 | int m_lock_resources_counter; |
217 | std::vector<fastuidraw::ivec3> m_delayed_free_tiles; |
218 | |
219 | #ifdef FASTUIDRAW_DEBUG |
220 | fastuidraw::array3d<inited_bool> m_tile_allocated; |
221 | #endif |
222 | }; |
223 | |
224 | class ResourceReleaseActionList |
225 | { |
226 | public: |
227 | ResourceReleaseActionList(void): |
228 | m_lock_resources_counter(0) |
229 | {} |
230 | |
231 | ~ResourceReleaseActionList() |
232 | { |
233 | FASTUIDRAWassert(m_lock_resources_counter == 0); |
234 | FASTUIDRAWassert(m_delete_actions.empty()); |
235 | } |
236 | |
237 | void |
238 | add_action(const fastuidraw::reference_counted_ptr<fastuidraw::Image::ResourceReleaseAction> &action) |
239 | { |
240 | if (m_lock_resources_counter != 0u) |
241 | { |
242 | m_delete_actions.push_back(action); |
243 | } |
244 | else |
245 | { |
246 | action->action(); |
247 | } |
248 | } |
249 | |
250 | void |
251 | lock_resources(void) |
252 | { |
253 | ++m_lock_resources_counter; |
254 | } |
255 | |
256 | void |
257 | unlock_resources(void) |
258 | { |
259 | FASTUIDRAWassert(m_lock_resources_counter >= 1); |
260 | --m_lock_resources_counter; |
261 | if (m_lock_resources_counter == 0) |
262 | { |
263 | for (const auto &v : m_delete_actions) |
264 | { |
265 | v->action(); |
266 | } |
267 | m_delete_actions.clear(); |
268 | } |
269 | } |
270 | |
271 | private: |
272 | std::vector<fastuidraw::reference_counted_ptr<fastuidraw::Image::ResourceReleaseAction> > m_delete_actions; |
273 | unsigned int m_lock_resources_counter; |
274 | }; |
275 | |
276 | template<typename T> |
277 | fastuidraw::ivec3 |
278 | dimensions_of_store(const fastuidraw::reference_counted_ptr<T> &store) |
279 | { |
280 | return (store) ? |
281 | store->dimensions() : |
282 | fastuidraw::ivec3(0, 0, 0); |
283 | } |
284 | |
285 | class ImageAtlasPrivate |
286 | { |
287 | public: |
288 | ImageAtlasPrivate(int pcolor_tile_size, int pindex_tile_size, |
289 | const fastuidraw::reference_counted_ptr<fastuidraw::AtlasColorBackingStoreBase> &pcolor_store, |
290 | const fastuidraw::reference_counted_ptr<fastuidraw::AtlasIndexBackingStoreBase> &pindex_store): |
291 | m_color_store(pcolor_store), |
292 | m_color_store_constant(m_color_store), |
293 | m_color_tiles(pcolor_tile_size, dimensions_of_store(pcolor_store)), |
294 | m_index_store(pindex_store), |
295 | m_index_store_constant(m_index_store), |
296 | m_index_tiles(pindex_tile_size, dimensions_of_store(pindex_store)) |
297 | {} |
298 | |
299 | int |
300 | number_free_index_tiles(void); |
301 | |
302 | fastuidraw::ivec3 |
303 | add_index_tile(fastuidraw::c_array<const fastuidraw::ivec3> data); |
304 | |
305 | fastuidraw::ivec3 |
306 | add_index_tile_index_data(fastuidraw::c_array<const fastuidraw::ivec3> data); |
307 | |
308 | void |
309 | delete_index_tile(fastuidraw::ivec3 tile); |
310 | |
311 | fastuidraw::ivec3 |
312 | add_color_tile(fastuidraw::ivec2 src_xy, |
313 | const fastuidraw::ImageSourceBase &image_data); |
314 | |
315 | fastuidraw::ivec3 |
316 | add_color_tile(fastuidraw::u8vec4 color_data); |
317 | |
318 | void |
319 | delete_color_tile(fastuidraw::ivec3 tile); |
320 | |
321 | int |
322 | number_free_color_tiles(void); |
323 | |
324 | void |
325 | resize_to_fit(int num_color_tiles, int num_index_tiles); |
326 | |
327 | int |
328 | index_tile_size(void) |
329 | { |
330 | return m_index_tiles.tile_size(); |
331 | } |
332 | |
333 | int |
334 | color_tile_size(void) |
335 | { |
336 | return m_color_tiles.tile_size(); |
337 | } |
338 | |
339 | std::mutex m_mutex; |
340 | ResourceReleaseActionList m_delete_actions; |
341 | |
342 | fastuidraw::reference_counted_ptr<fastuidraw::AtlasColorBackingStoreBase> m_color_store; |
343 | fastuidraw::reference_counted_ptr<const fastuidraw::AtlasColorBackingStoreBase> m_color_store_constant; |
344 | tile_allocator m_color_tiles; |
345 | |
346 | fastuidraw::reference_counted_ptr<fastuidraw::AtlasIndexBackingStoreBase> m_index_store; |
347 | fastuidraw::reference_counted_ptr<const fastuidraw::AtlasIndexBackingStoreBase> m_index_store_constant; |
348 | tile_allocator m_index_tiles; |
349 | }; |
350 | |
351 | /* TODO: take into account for repeated tile colors. */ |
352 | bool |
353 | enough_room_in_atlas(fastuidraw::ivec2 number_color_tiles, |
354 | ImageAtlasPrivate *C, int &total_index) |
355 | { |
356 | int total_color; |
357 | |
358 | total_color = number_color_tiles.x() * number_color_tiles.y(); |
359 | total_index = number_index_tiles_needed(number_color_tiles, C->index_tile_size()); |
360 | |
361 | //std::cout << "Need " << total_color << " have: " << C->number_free_color_tiles() << "\n" |
362 | // << "Need " << total_index << " have: " << C->number_free_index_tiles() << "\n"; |
363 | |
364 | return total_color <= C->number_free_color_tiles() |
365 | && total_index <= C->number_free_index_tiles(); |
366 | } |
367 | |
368 | class per_color_tile |
369 | { |
370 | public: |
371 | per_color_tile(const fastuidraw::ivec3 t, bool b): |
372 | m_tile(t), m_non_repeat_color(b) |
373 | {} |
374 | |
375 | operator fastuidraw::ivec3() const |
376 | { |
377 | return m_tile; |
378 | } |
379 | |
380 | fastuidraw::ivec3 m_tile; |
381 | bool m_non_repeat_color; |
382 | }; |
383 | |
384 | class ImagePrivate |
385 | { |
386 | public: |
387 | ImagePrivate(fastuidraw::ImageAtlas &patlas, |
388 | ImageAtlasPrivate *atlas_private, |
389 | int w, int h, |
390 | const fastuidraw::ImageSourceBase &image_data); |
391 | |
392 | ImagePrivate(fastuidraw::ImageAtlas &patlas, |
393 | ImageAtlasPrivate *atlas_private, int w, int h, |
394 | unsigned int m, fastuidraw::Image::type_t t, uint64_t handle, |
395 | enum fastuidraw::Image::format_t fmt, |
396 | const fastuidraw::reference_counted_ptr<fastuidraw::Image::ResourceReleaseAction> &action): |
397 | m_atlas(&patlas), |
398 | m_atlas_private(atlas_private), |
399 | m_action(action), |
400 | m_dimensions(w, h), |
401 | m_number_levels(m), |
402 | m_type(t), |
403 | m_format(fmt), |
404 | m_num_color_tiles(-1, -1), |
405 | m_master_index_tile(-1, -1, -1), |
406 | m_master_index_tile_dims(-1.0f, -1.0f), |
407 | m_number_index_lookups(0), |
408 | m_dimensions_index_divisor(-1.0f), |
409 | m_bindless_handle(handle) |
410 | { |
411 | } |
412 | |
413 | ~ImagePrivate(); |
414 | |
415 | void |
416 | create_color_tiles(const fastuidraw::ImageSourceBase &image_data); |
417 | |
418 | void |
419 | create_index_tiles(void); |
420 | |
421 | template<typename T> |
422 | fastuidraw::ivec2 |
423 | create_index_layer(fastuidraw::c_array<const T> src_tiles, |
424 | fastuidraw::ivec2 src_dims, |
425 | std::list<std::vector<fastuidraw::ivec3> > &destination); |
426 | |
427 | fastuidraw::reference_counted_ptr<fastuidraw::ImageAtlas> m_atlas; |
428 | ImageAtlasPrivate *m_atlas_private; |
429 | fastuidraw::reference_counted_ptr<fastuidraw::Image::ResourceReleaseAction> m_action; |
430 | fastuidraw::ivec2 m_dimensions; |
431 | int m_number_levels; |
432 | |
433 | enum fastuidraw::Image::type_t m_type; |
434 | enum fastuidraw::Image::format_t m_format; |
435 | |
436 | /* Data for when the image has type on_atlas */ |
437 | fastuidraw::ivec2 m_num_color_tiles; |
438 | std::map<fastuidraw::u8vec4, fastuidraw::ivec3> m_repeated_tiles; |
439 | std::vector<per_color_tile> m_color_tiles; |
440 | std::list<std::vector<fastuidraw::ivec3> > m_index_tiles; |
441 | fastuidraw::ivec3 m_master_index_tile; |
442 | fastuidraw::vec2 m_master_index_tile_dims; |
443 | unsigned int m_number_index_lookups; |
444 | float m_dimensions_index_divisor; |
445 | |
446 | /* data for when image has different type than on_atlas */ |
447 | uint64_t m_bindless_handle; |
448 | }; |
449 | } |
450 | |
451 | ///////////////////////////////////////////// |
452 | //ImagePrivate methods |
453 | ImagePrivate:: |
454 | ImagePrivate(fastuidraw::ImageAtlas &patlas, |
455 | ImageAtlasPrivate *atlas_private, int w, int h, |
456 | const fastuidraw::ImageSourceBase &image_data): |
457 | m_atlas(&patlas), |
458 | m_atlas_private(atlas_private), |
459 | m_dimensions(w, h), |
460 | m_number_levels(image_data.number_levels()), |
461 | m_type(fastuidraw::Image::on_atlas), |
462 | m_format(image_data.format()), |
463 | m_bindless_handle(-1) |
464 | { |
465 | using namespace fastuidraw; |
466 | |
467 | FASTUIDRAWassert(m_dimensions.x() > 0); |
468 | FASTUIDRAWassert(m_dimensions.y() > 0); |
469 | FASTUIDRAWassert(m_atlas); |
470 | |
471 | create_color_tiles(image_data); |
472 | create_index_tiles(); |
473 | |
474 | /* Mipmap filtering cannot go beyond the tile size or the |
475 | * size of the image. |
476 | */ |
477 | int max_levels; |
478 | max_levels = 1u + uint32_log2(t_min(m_atlas_private->color_tile_size(), t_min(w, h))); |
479 | m_number_levels = t_min(max_levels, m_number_levels); |
480 | } |
481 | |
482 | ImagePrivate:: |
483 | ~ImagePrivate() |
484 | { |
485 | for(const per_color_tile &C : m_color_tiles) |
486 | { |
487 | if (C.m_non_repeat_color) |
488 | { |
489 | m_atlas_private->delete_color_tile(C.m_tile); |
490 | } |
491 | } |
492 | |
493 | for(const auto &C : m_repeated_tiles) |
494 | { |
495 | m_atlas_private->delete_color_tile(C.second); |
496 | } |
497 | |
498 | for(const auto &tile_array: m_index_tiles) |
499 | { |
500 | for(const fastuidraw::ivec3 &index_tile : tile_array) |
501 | { |
502 | m_atlas_private->delete_index_tile(index_tile); |
503 | } |
504 | } |
505 | |
506 | if (m_action) |
507 | { |
508 | m_atlas->queue_resource_release_action(m_action); |
509 | } |
510 | } |
511 | |
512 | void |
513 | ImagePrivate:: |
514 | create_color_tiles(const fastuidraw::ImageSourceBase &image_data) |
515 | { |
516 | int tile_interior_size; |
517 | int color_tile_size; |
518 | |
519 | color_tile_size = m_atlas_private->color_tile_size(); |
520 | tile_interior_size = color_tile_size; |
521 | m_num_color_tiles = divide_up(m_dimensions, tile_interior_size); |
522 | m_master_index_tile_dims = fastuidraw::vec2(m_dimensions) / static_cast<float>(tile_interior_size); |
523 | m_dimensions_index_divisor = static_cast<float>(tile_interior_size); |
524 | |
525 | unsigned int savings(0); |
526 | for(int ty = 0, source_y = 0; |
527 | ty < m_num_color_tiles.y(); |
528 | ++ty, source_y += tile_interior_size) |
529 | { |
530 | for(int tx = 0, source_x = 0; |
531 | tx < m_num_color_tiles.x(); |
532 | ++tx, source_x += tile_interior_size) |
533 | { |
534 | fastuidraw::ivec3 new_tile; |
535 | fastuidraw::ivec2 src_xy(source_x, source_y); |
536 | bool all_same_color; |
537 | fastuidraw::u8vec4 same_color_value; |
538 | |
539 | all_same_color = image_data.all_same_color(src_xy, color_tile_size, &same_color_value); |
540 | |
541 | if (all_same_color) |
542 | { |
543 | std::map<fastuidraw::u8vec4, fastuidraw::ivec3>::iterator iter; |
544 | |
545 | iter = m_repeated_tiles.find(same_color_value); |
546 | if (iter != m_repeated_tiles.end()) |
547 | { |
548 | new_tile = iter->second; |
549 | ++savings; |
550 | } |
551 | else |
552 | { |
553 | new_tile = m_atlas_private->add_color_tile(same_color_value); |
554 | m_repeated_tiles[same_color_value] = new_tile; |
555 | } |
556 | } |
557 | else |
558 | { |
559 | new_tile = m_atlas_private->add_color_tile(src_xy, image_data); |
560 | } |
561 | |
562 | m_color_tiles.push_back(per_color_tile(new_tile, !all_same_color) ); |
563 | } |
564 | } |
565 | |
566 | FASTUIDRAWunused(savings); |
567 | //std::cout << "Saved " << savings << " out of " |
568 | // << m_num_color_tiles.x() * m_num_color_tiles.y() |
569 | // << " tiles from repeat color magicks\n"; |
570 | } |
571 | |
572 | |
573 | /* |
574 | * returns the number of index tiles needed to |
575 | * store the created index data. |
576 | */ |
577 | template<typename T> |
578 | fastuidraw::ivec2 |
579 | ImagePrivate:: |
580 | create_index_layer(fastuidraw::c_array<const T> src_tiles, |
581 | fastuidraw::ivec2 src_dims, |
582 | std::list<std::vector<fastuidraw::ivec3> > &destination) |
583 | { |
584 | int index_tile_size; |
585 | fastuidraw::ivec2 num_index_tiles; |
586 | |
587 | index_tile_size = m_atlas_private->index_tile_size(); |
588 | num_index_tiles = divide_up(src_dims, index_tile_size); |
589 | |
590 | destination.push_back(std::vector<fastuidraw::ivec3>()); |
591 | |
592 | std::vector<fastuidraw::ivec3> vtile_data(index_tile_size * index_tile_size); |
593 | fastuidraw::c_array<fastuidraw::ivec3> tile_data; |
594 | tile_data = fastuidraw::make_c_array(vtile_data); |
595 | |
596 | for(int source_y = 0; source_y < src_dims.y(); source_y += index_tile_size) |
597 | { |
598 | for(int source_x = 0; source_x < src_dims.x(); source_x += index_tile_size) |
599 | { |
600 | fastuidraw::ivec3 new_tile; |
601 | copy_sub_data<fastuidraw::ivec3, T>(tile_data, index_tile_size, index_tile_size, |
602 | src_tiles, source_x, source_y, |
603 | src_dims); |
604 | new_tile = m_atlas_private->add_index_tile(tile_data); |
605 | destination.back().push_back(new_tile); |
606 | } |
607 | } |
608 | return num_index_tiles; |
609 | } |
610 | |
611 | void |
612 | ImagePrivate:: |
613 | create_index_tiles(void) |
614 | { |
615 | fastuidraw::ivec2 num_index_tiles; |
616 | int level(2); |
617 | float findex_tile_size; |
618 | |
619 | findex_tile_size = static_cast<float>(m_atlas_private->index_tile_size()); |
620 | num_index_tiles = create_index_layer<per_color_tile>(fastuidraw::make_c_array(m_color_tiles), |
621 | m_num_color_tiles, m_index_tiles); |
622 | |
623 | for(level = 2; num_index_tiles.x() > 1 || num_index_tiles.y() > 1; ++level) |
624 | { |
625 | num_index_tiles = create_index_layer<fastuidraw::ivec3>(fastuidraw::make_c_array(m_index_tiles.back()), |
626 | num_index_tiles, m_index_tiles); |
627 | m_dimensions_index_divisor *= findex_tile_size; |
628 | m_master_index_tile_dims /= findex_tile_size; |
629 | } |
630 | |
631 | FASTUIDRAWassert(m_index_tiles.back().size() == 1); |
632 | m_master_index_tile = m_index_tiles.back()[0]; |
633 | m_number_index_lookups = m_index_tiles.size(); |
634 | } |
635 | |
636 | /////////////////////////////////////////// |
637 | // tile_allocator methods |
638 | tile_allocator:: |
639 | tile_allocator(int tile_size, fastuidraw::ivec3 store_dimensions): |
640 | m_tile_size(tile_size), |
641 | m_next_tile(0, 0, 0), |
642 | m_num_tiles(tile_size > 0 ? store_dimensions.x() / m_tile_size : 0, |
643 | tile_size > 0 ? store_dimensions.y() / m_tile_size : 0, |
644 | tile_size > 0 ? store_dimensions.z() : 0), |
645 | m_tile_count(0), |
646 | m_lock_resources_counter(0) |
647 | #ifdef FASTUIDRAW_DEBUG |
648 | , |
649 | m_tile_allocated(m_num_tiles.x(), m_num_tiles.y(), m_num_tiles.z()) |
650 | #endif |
651 | { |
652 | FASTUIDRAWassert(m_tile_size == 0 || store_dimensions.x() % m_tile_size == 0); |
653 | FASTUIDRAWassert(m_tile_size == 0 || store_dimensions.y() % m_tile_size == 0); |
654 | } |
655 | |
656 | tile_allocator:: |
657 | ~tile_allocator() |
658 | { |
659 | FASTUIDRAWassert(m_lock_resources_counter == 0); |
660 | FASTUIDRAWassert(m_tile_count == 0); |
661 | } |
662 | |
663 | fastuidraw::ivec3 |
664 | tile_allocator:: |
665 | allocate_tile(void) |
666 | { |
667 | fastuidraw::ivec3 return_value; |
668 | if (m_free_tiles.empty()) |
669 | { |
670 | if (m_next_tile.x() < m_num_tiles.x() || m_next_tile.y() < m_num_tiles.y() || m_next_tile.z() < m_num_tiles.z()) |
671 | { |
672 | return_value = m_next_tile; |
673 | ++m_next_tile.x(); |
674 | if (m_next_tile.x() == m_num_tiles.x()) |
675 | { |
676 | m_next_tile.x() = 0; |
677 | ++m_next_tile.y(); |
678 | if (m_next_tile.y() == m_num_tiles.y()) |
679 | { |
680 | m_next_tile.y() = 0; |
681 | ++m_next_tile.z(); |
682 | } |
683 | } |
684 | } |
685 | else |
686 | { |
687 | FASTUIDRAWassert(!"Color tile room exhausted" ); |
688 | return fastuidraw::ivec3(-1, -1,-1); |
689 | } |
690 | } |
691 | else |
692 | { |
693 | return_value = m_free_tiles.back(); |
694 | m_free_tiles.pop_back(); |
695 | } |
696 | |
697 | #ifdef FASTUIDRAW_DEBUG |
698 | { |
699 | FASTUIDRAWassert(!m_tile_allocated(return_value.x(), return_value.y(), return_value.z()).m_value); |
700 | m_tile_allocated(return_value.x(), return_value.y(), return_value.z()) = true; |
701 | } |
702 | #endif |
703 | |
704 | ++m_tile_count; |
705 | return return_value; |
706 | } |
707 | |
708 | void |
709 | tile_allocator:: |
710 | lock_resources(void) |
711 | { |
712 | ++m_lock_resources_counter; |
713 | } |
714 | |
715 | void |
716 | tile_allocator:: |
717 | unlock_resources(void) |
718 | { |
719 | FASTUIDRAWassert(m_lock_resources_counter >= 1); |
720 | --m_lock_resources_counter; |
721 | if (m_lock_resources_counter == 0) |
722 | { |
723 | for(unsigned int i = 0, endi = m_delayed_free_tiles.size(); i < endi; ++i) |
724 | { |
725 | delete_tile_implement(m_delayed_free_tiles[i]); |
726 | } |
727 | m_delayed_free_tiles.clear(); |
728 | } |
729 | } |
730 | |
731 | void |
732 | tile_allocator:: |
733 | delete_tile(fastuidraw::ivec3 v) |
734 | { |
735 | if (m_lock_resources_counter == 0) |
736 | { |
737 | delete_tile_implement(v); |
738 | } |
739 | else |
740 | { |
741 | m_delayed_free_tiles.push_back(v); |
742 | } |
743 | } |
744 | |
745 | void |
746 | tile_allocator:: |
747 | delete_tile_implement(fastuidraw::ivec3 v) |
748 | { |
749 | FASTUIDRAWassert(m_lock_resources_counter == 0); |
750 | #ifdef FASTUIDRAW_DEBUG |
751 | { |
752 | FASTUIDRAWassert(m_tile_allocated(v.x(), v.y(), v.z()).m_value); |
753 | m_tile_allocated(v.x(), v.y(), v.z()) = false; |
754 | } |
755 | #endif |
756 | |
757 | --m_tile_count; |
758 | m_free_tiles.push_back(v); |
759 | } |
760 | |
761 | int |
762 | tile_allocator:: |
763 | number_free(void) const |
764 | { |
765 | return m_num_tiles.x() * m_num_tiles.y() * m_num_tiles.z() - m_tile_count; |
766 | } |
767 | |
768 | bool |
769 | tile_allocator:: |
770 | resize_to_fit(int num_tiles) |
771 | { |
772 | if (num_tiles > number_free()) |
773 | { |
774 | /* resize to fit the number of needed tiles, |
775 | * compute how many more tiles needed and from |
776 | * there compute how many more layers needed. |
777 | */ |
778 | int needed_tiles, tiles_per_layer, needed_layers; |
779 | needed_tiles = num_tiles - number_free(); |
780 | tiles_per_layer = m_num_tiles.x() * m_num_tiles.y(); |
781 | needed_layers = needed_tiles / tiles_per_layer; |
782 | if (needed_tiles > needed_layers * tiles_per_layer) |
783 | { |
784 | ++needed_layers; |
785 | } |
786 | |
787 | /* TODO: |
788 | * Should we resize at powers of 2, or just to what is |
789 | * needed? |
790 | */ |
791 | m_num_tiles.z() += needed_layers; |
792 | #ifdef FASTUIDRAW_DEBUG |
793 | { |
794 | m_tile_allocated.resize(m_num_tiles.x(), m_num_tiles.y(), m_num_tiles.z()); |
795 | } |
796 | #endif |
797 | |
798 | return true; |
799 | } |
800 | else |
801 | { |
802 | return false; |
803 | } |
804 | } |
805 | |
806 | ///////////////////////////////////////// |
807 | // ImageAtlasPrivate methods |
808 | int |
809 | ImageAtlasPrivate:: |
810 | number_free_index_tiles(void) |
811 | { |
812 | std::lock_guard<std::mutex> M(m_mutex); |
813 | return m_index_tiles.number_free(); |
814 | } |
815 | |
816 | fastuidraw::ivec3 |
817 | ImageAtlasPrivate:: |
818 | add_index_tile(fastuidraw::c_array<const fastuidraw::ivec3> data) |
819 | { |
820 | fastuidraw::ivec3 return_value; |
821 | std::lock_guard<std::mutex> M(m_mutex); |
822 | |
823 | return_value = m_index_tiles.allocate_tile(); |
824 | if (return_value != fastuidraw::ivec3(-1, -1, -1)) |
825 | { |
826 | m_index_store->set_data(return_value.x() * m_index_tiles.tile_size(), |
827 | return_value.y() * m_index_tiles.tile_size(), |
828 | return_value.z(), |
829 | m_index_tiles.tile_size(), |
830 | m_index_tiles.tile_size(), |
831 | data); |
832 | } |
833 | |
834 | return return_value; |
835 | } |
836 | |
837 | void |
838 | ImageAtlasPrivate:: |
839 | delete_index_tile(fastuidraw::ivec3 tile) |
840 | { |
841 | std::lock_guard<std::mutex> M(m_mutex); |
842 | m_index_tiles.delete_tile(tile); |
843 | } |
844 | |
845 | int |
846 | ImageAtlasPrivate:: |
847 | number_free_color_tiles(void) |
848 | { |
849 | std::lock_guard<std::mutex> M(m_mutex); |
850 | return m_color_tiles.number_free(); |
851 | } |
852 | |
853 | fastuidraw::ivec3 |
854 | ImageAtlasPrivate:: |
855 | add_color_tile(fastuidraw::u8vec4 color_data) |
856 | { |
857 | fastuidraw::ivec3 return_value; |
858 | fastuidraw::ivec2 dst_xy; |
859 | int sz; |
860 | |
861 | std::lock_guard<std::mutex> M(m_mutex); |
862 | return_value = m_color_tiles.allocate_tile(); |
863 | if (return_value != fastuidraw::ivec3(-1, -1, -1)) |
864 | { |
865 | dst_xy.x() = return_value.x() * m_color_tiles.tile_size(); |
866 | dst_xy.y() = return_value.y() * m_color_tiles.tile_size(); |
867 | sz = m_color_tiles.tile_size(); |
868 | |
869 | for (int level = 0; sz > 0; ++level, sz /= 2, dst_xy /= 2) |
870 | { |
871 | m_color_store->set_data(level, dst_xy, return_value.z(), |
872 | sz, color_data); |
873 | } |
874 | } |
875 | |
876 | return return_value; |
877 | } |
878 | |
879 | fastuidraw::ivec3 |
880 | ImageAtlasPrivate:: |
881 | add_color_tile(fastuidraw::ivec2 src_xy, |
882 | const fastuidraw::ImageSourceBase &image_data) |
883 | { |
884 | fastuidraw::ivec3 return_value; |
885 | fastuidraw::ivec2 dst_xy; |
886 | int sz, level, end_level; |
887 | |
888 | std::lock_guard<std::mutex> M(m_mutex); |
889 | return_value = m_color_tiles.allocate_tile(); |
890 | if (return_value != fastuidraw::ivec3(-1, -1, -1)) |
891 | { |
892 | dst_xy.x() = return_value.x() * m_color_tiles.tile_size(); |
893 | dst_xy.y() = return_value.y() * m_color_tiles.tile_size(); |
894 | sz = m_color_tiles.tile_size(); |
895 | end_level = image_data.number_levels(); |
896 | |
897 | for (level = 0; level < end_level && sz > 0; ++level, sz /= 2, dst_xy /= 2, src_xy /= 2) |
898 | { |
899 | m_color_store->set_data(level, dst_xy, return_value.z(), src_xy, sz, image_data); |
900 | } |
901 | |
902 | for (; sz > 0; ++level, sz /= 2, dst_xy /= 2, src_xy /= 2, sz /= 2) |
903 | { |
904 | m_color_store->set_data(level, dst_xy, return_value.z(), sz, |
905 | fastuidraw::u8vec4(255u, 255u, 0u, 255u)); |
906 | } |
907 | } |
908 | |
909 | return return_value; |
910 | } |
911 | |
912 | void |
913 | ImageAtlasPrivate:: |
914 | delete_color_tile(fastuidraw::ivec3 tile) |
915 | { |
916 | std::lock_guard<std::mutex> M(m_mutex); |
917 | m_color_tiles.delete_tile(tile); |
918 | } |
919 | |
920 | void |
921 | ImageAtlasPrivate:: |
922 | resize_to_fit(int num_color_tiles, int num_index_tiles) |
923 | { |
924 | std::lock_guard<std::mutex> M(m_mutex); |
925 | if (m_color_tiles.resize_to_fit(num_color_tiles)) |
926 | { |
927 | m_color_store->resize(m_color_tiles.num_tiles().z()); |
928 | } |
929 | if (m_index_tiles.resize_to_fit(num_index_tiles)) |
930 | { |
931 | m_index_store->resize(m_index_tiles.num_tiles().z()); |
932 | } |
933 | } |
934 | |
935 | //////////////////////////////////////// |
936 | // fastuidraw::ImageSourceCArray methods |
937 | fastuidraw::ImageSourceCArray:: |
938 | ImageSourceCArray(uvec2 dimensions, |
939 | c_array<const c_array<const u8vec4> > pdata, |
940 | enum Image::format_t fmt): |
941 | m_dimensions(dimensions), |
942 | m_data(pdata), |
943 | m_format(fmt) |
944 | {} |
945 | |
946 | bool |
947 | fastuidraw::ImageSourceCArray:: |
948 | all_same_color(ivec2 location, int square_size, u8vec4 *dst) const |
949 | { |
950 | location.x() = t_max(location.x(), 0); |
951 | location.y() = t_max(location.y(), 0); |
952 | |
953 | location.x() = t_min(int(m_dimensions.x()) - 1, location.x()); |
954 | location.y() = t_min(int(m_dimensions.y()) - 1, location.y()); |
955 | |
956 | square_size = t_min(int(m_dimensions.x()) - location.x(), square_size); |
957 | square_size = t_min(int(m_dimensions.y()) - location.y(), square_size); |
958 | |
959 | *dst = m_data[0][location.x() + location.y() * m_dimensions.x()]; |
960 | for (int y = 0, sy = location.y(); y < square_size; ++y, ++sy) |
961 | { |
962 | for (int x = 0, sx = location.x(); x < square_size; ++x, ++sx) |
963 | { |
964 | if (*dst != m_data[0][sx + sy * m_dimensions.x()]) |
965 | { |
966 | return false; |
967 | } |
968 | } |
969 | } |
970 | return true; |
971 | } |
972 | |
973 | unsigned int |
974 | fastuidraw::ImageSourceCArray:: |
975 | number_levels(void) const |
976 | { |
977 | return m_data.size(); |
978 | } |
979 | |
980 | void |
981 | fastuidraw::ImageSourceCArray:: |
982 | fetch_texels(unsigned int mipmap_level, ivec2 location, |
983 | unsigned int w, unsigned int h, |
984 | c_array<u8vec4> dst) const |
985 | { |
986 | if (mipmap_level >= m_data.size()) |
987 | { |
988 | std::fill(dst.begin(), dst.end(), u8vec4(255u, 255u, 0u, 255u)); |
989 | } |
990 | else |
991 | { |
992 | copy_sub_data(dst, w, h, |
993 | m_data[mipmap_level], |
994 | location.x(), location.y(), |
995 | ivec2(m_dimensions.x() >> mipmap_level, |
996 | m_dimensions.y() >> mipmap_level)); |
997 | } |
998 | } |
999 | |
1000 | enum fastuidraw::Image::format_t |
1001 | fastuidraw::ImageSourceCArray:: |
1002 | format(void) const |
1003 | { |
1004 | return m_format; |
1005 | } |
1006 | |
1007 | ////////////////////////////////////////////////// |
1008 | // fastuidraw::AtlasColorBackingStoreBase methods |
1009 | fastuidraw::AtlasColorBackingStoreBase:: |
1010 | AtlasColorBackingStoreBase(ivec3 whl) |
1011 | { |
1012 | m_d = FASTUIDRAWnew BackingStorePrivate(whl); |
1013 | } |
1014 | |
1015 | fastuidraw::AtlasColorBackingStoreBase:: |
1016 | AtlasColorBackingStoreBase(int w, int h, int num_layers) |
1017 | { |
1018 | m_d = FASTUIDRAWnew BackingStorePrivate(w, h, num_layers); |
1019 | } |
1020 | |
1021 | fastuidraw::AtlasColorBackingStoreBase:: |
1022 | ~AtlasColorBackingStoreBase() |
1023 | { |
1024 | BackingStorePrivate *d; |
1025 | d = static_cast<BackingStorePrivate*>(m_d); |
1026 | FASTUIDRAWdelete(d); |
1027 | m_d = nullptr; |
1028 | } |
1029 | |
1030 | fastuidraw::ivec3 |
1031 | fastuidraw::AtlasColorBackingStoreBase:: |
1032 | dimensions(void) const |
1033 | { |
1034 | BackingStorePrivate *d; |
1035 | d = static_cast<BackingStorePrivate*>(m_d); |
1036 | return d->m_dimensions; |
1037 | } |
1038 | |
1039 | void |
1040 | fastuidraw::AtlasColorBackingStoreBase:: |
1041 | resize(int new_num_layers) |
1042 | { |
1043 | BackingStorePrivate *d; |
1044 | |
1045 | d = static_cast<BackingStorePrivate*>(m_d); |
1046 | FASTUIDRAWassert(new_num_layers > d->m_dimensions.z()); |
1047 | resize_implement(new_num_layers); |
1048 | d->m_dimensions.z() = new_num_layers; |
1049 | } |
1050 | |
1051 | /////////////////////////////////////////////// |
1052 | // fastuidraw::AtlasIndexBackingStoreBase methods |
1053 | fastuidraw::AtlasIndexBackingStoreBase:: |
1054 | AtlasIndexBackingStoreBase(ivec3 whl) |
1055 | { |
1056 | m_d = FASTUIDRAWnew BackingStorePrivate(whl); |
1057 | } |
1058 | |
1059 | fastuidraw::AtlasIndexBackingStoreBase:: |
1060 | AtlasIndexBackingStoreBase(int w, int h, int l) |
1061 | { |
1062 | m_d = FASTUIDRAWnew BackingStorePrivate(w, h, l); |
1063 | } |
1064 | |
1065 | fastuidraw::AtlasIndexBackingStoreBase:: |
1066 | ~AtlasIndexBackingStoreBase() |
1067 | { |
1068 | BackingStorePrivate *d; |
1069 | d = static_cast<BackingStorePrivate*>(m_d); |
1070 | FASTUIDRAWdelete(d); |
1071 | m_d = nullptr; |
1072 | } |
1073 | |
1074 | fastuidraw::ivec3 |
1075 | fastuidraw::AtlasIndexBackingStoreBase:: |
1076 | dimensions(void) const |
1077 | { |
1078 | BackingStorePrivate *d; |
1079 | d = static_cast<BackingStorePrivate*>(m_d); |
1080 | return d->m_dimensions; |
1081 | } |
1082 | |
1083 | void |
1084 | fastuidraw::AtlasIndexBackingStoreBase:: |
1085 | resize(int new_num_layers) |
1086 | { |
1087 | BackingStorePrivate *d; |
1088 | |
1089 | d = static_cast<BackingStorePrivate*>(m_d); |
1090 | FASTUIDRAWassert(new_num_layers > d->m_dimensions.z()); |
1091 | resize_implement(new_num_layers); |
1092 | d->m_dimensions.z() = new_num_layers; |
1093 | } |
1094 | |
1095 | ////////////////////////////// |
1096 | // fastuidraw::ImageAtlas methods |
1097 | fastuidraw::ImageAtlas:: |
1098 | ImageAtlas(int pcolor_tile_size, int pindex_tile_size, |
1099 | fastuidraw::reference_counted_ptr<AtlasColorBackingStoreBase> pcolor_store, |
1100 | fastuidraw::reference_counted_ptr<AtlasIndexBackingStoreBase> pindex_store) |
1101 | { |
1102 | m_d = FASTUIDRAWnew ImageAtlasPrivate(pcolor_tile_size, pindex_tile_size, |
1103 | pcolor_store, pindex_store); |
1104 | } |
1105 | |
1106 | fastuidraw::ImageAtlas:: |
1107 | ~ImageAtlas() |
1108 | { |
1109 | ImageAtlasPrivate *d; |
1110 | d = static_cast<ImageAtlasPrivate*>(m_d); |
1111 | FASTUIDRAWdelete(d); |
1112 | m_d = nullptr; |
1113 | } |
1114 | |
1115 | void |
1116 | fastuidraw::ImageAtlas:: |
1117 | lock_resources(void) |
1118 | { |
1119 | ImageAtlasPrivate *d; |
1120 | d = static_cast<ImageAtlasPrivate*>(m_d); |
1121 | |
1122 | std::lock_guard<std::mutex> M(d->m_mutex); |
1123 | d->m_color_tiles.lock_resources(); |
1124 | d->m_index_tiles.lock_resources(); |
1125 | d->m_delete_actions.lock_resources(); |
1126 | } |
1127 | |
1128 | void |
1129 | fastuidraw::ImageAtlas:: |
1130 | unlock_resources(void) |
1131 | { |
1132 | ImageAtlasPrivate *d; |
1133 | d = static_cast<ImageAtlasPrivate*>(m_d); |
1134 | |
1135 | std::lock_guard<std::mutex> M(d->m_mutex); |
1136 | d->m_color_tiles.unlock_resources(); |
1137 | d->m_index_tiles.unlock_resources(); |
1138 | d->m_delete_actions.unlock_resources(); |
1139 | } |
1140 | |
1141 | int |
1142 | fastuidraw::ImageAtlas:: |
1143 | color_tile_size(void) const |
1144 | { |
1145 | ImageAtlasPrivate *d; |
1146 | d = static_cast<ImageAtlasPrivate*>(m_d); |
1147 | return d->color_tile_size(); |
1148 | } |
1149 | |
1150 | int |
1151 | fastuidraw::ImageAtlas:: |
1152 | index_tile_size(void) const |
1153 | { |
1154 | ImageAtlasPrivate *d; |
1155 | d = static_cast<ImageAtlasPrivate*>(m_d); |
1156 | return d->index_tile_size(); |
1157 | } |
1158 | |
1159 | void |
1160 | fastuidraw::ImageAtlas:: |
1161 | flush(void) const |
1162 | { |
1163 | ImageAtlasPrivate *d; |
1164 | d = static_cast<ImageAtlasPrivate*>(m_d); |
1165 | std::lock_guard<std::mutex> M(d->m_mutex); |
1166 | |
1167 | if (d->m_index_store) |
1168 | { |
1169 | d->m_index_store->flush(); |
1170 | } |
1171 | |
1172 | if (d->m_color_store) |
1173 | { |
1174 | d->m_color_store->flush(); |
1175 | } |
1176 | } |
1177 | |
1178 | const fastuidraw::reference_counted_ptr<const fastuidraw::AtlasColorBackingStoreBase>& |
1179 | fastuidraw::ImageAtlas:: |
1180 | color_store(void) const |
1181 | { |
1182 | ImageAtlasPrivate *d; |
1183 | d = static_cast<ImageAtlasPrivate*>(m_d); |
1184 | return d->m_color_store_constant; |
1185 | } |
1186 | |
1187 | const fastuidraw::reference_counted_ptr<const fastuidraw::AtlasIndexBackingStoreBase>& |
1188 | fastuidraw::ImageAtlas:: |
1189 | index_store(void) const |
1190 | { |
1191 | ImageAtlasPrivate *d; |
1192 | d = static_cast<ImageAtlasPrivate*>(m_d); |
1193 | return d->m_index_store_constant; |
1194 | } |
1195 | |
1196 | void |
1197 | fastuidraw::ImageAtlas:: |
1198 | queue_resource_release_action(const reference_counted_ptr<Image::ResourceReleaseAction> &action) |
1199 | { |
1200 | if (action) |
1201 | { |
1202 | ImageAtlasPrivate *d; |
1203 | d = static_cast<ImageAtlasPrivate*>(m_d); |
1204 | |
1205 | std::lock_guard<std::mutex> M(d->m_mutex); |
1206 | d->m_delete_actions.add_action(action); |
1207 | } |
1208 | } |
1209 | |
1210 | fastuidraw::reference_counted_ptr<fastuidraw::Image> |
1211 | fastuidraw::ImageAtlas:: |
1212 | create_image_on_atlas(int w, int h, const ImageSourceBase &image_data) |
1213 | { |
1214 | int tile_interior_size; |
1215 | ivec2 num_color_tiles; |
1216 | int index_tiles; |
1217 | ImageAtlasPrivate *d; |
1218 | |
1219 | d = static_cast<ImageAtlasPrivate*>(m_d); |
1220 | if (w <= 0 || h <= 0 || !d->m_color_store || !d->m_index_store) |
1221 | { |
1222 | return reference_counted_ptr<Image>(); |
1223 | } |
1224 | |
1225 | tile_interior_size = color_tile_size(); |
1226 | if (tile_interior_size <= 0) |
1227 | { |
1228 | return reference_counted_ptr<Image>(); |
1229 | } |
1230 | |
1231 | num_color_tiles = divide_up(ivec2(w, h), tile_interior_size); |
1232 | if (!enough_room_in_atlas(num_color_tiles, d, index_tiles)) |
1233 | { |
1234 | /* TODO: |
1235 | * there actually might be enough room if we take into account |
1236 | * the savings from repeated tiles. The correct thing is to |
1237 | * delay this until iamge construction, check if it succeeded |
1238 | * and if not then delete it and return an invalid handle. |
1239 | */ |
1240 | d->resize_to_fit(num_color_tiles.x() * num_color_tiles.y(), index_tiles); |
1241 | } |
1242 | |
1243 | return FASTUIDRAWnew Image(*this, w, h, image_data); |
1244 | } |
1245 | |
1246 | fastuidraw::reference_counted_ptr<fastuidraw::Image> |
1247 | fastuidraw::ImageAtlas:: |
1248 | create_non_atlas(int w, int h, const ImageSourceBase &image_data) |
1249 | { |
1250 | reference_counted_ptr<Image> return_value; |
1251 | |
1252 | return_value = create_image_bindless(w, h, image_data); |
1253 | if (!return_value) |
1254 | { |
1255 | return_value = create_image_context_texture2d(w, h, image_data); |
1256 | } |
1257 | return return_value; |
1258 | } |
1259 | |
1260 | fastuidraw::reference_counted_ptr<fastuidraw::Image> |
1261 | fastuidraw::ImageAtlas:: |
1262 | create(int w, int h, const ImageSourceBase &image_data, |
1263 | enum Image::type_t type) |
1264 | { |
1265 | reference_counted_ptr<Image> return_value; |
1266 | vecN<enum Image::type_t, 2> try_types; |
1267 | |
1268 | try_types[0] = type; |
1269 | switch (type) |
1270 | { |
1271 | case Image::bindless_texture2d: |
1272 | try_types[1] = Image::on_atlas; |
1273 | break; |
1274 | case Image::on_atlas: |
1275 | try_types[1] = Image::bindless_texture2d; |
1276 | break; |
1277 | default: |
1278 | try_types[1] = type; |
1279 | } |
1280 | |
1281 | for (unsigned int i = 0; i < 2 && !return_value; ++i) |
1282 | { |
1283 | if (try_types[i] == Image::bindless_texture2d) |
1284 | { |
1285 | return_value = create_image_bindless(w, h, image_data); |
1286 | } |
1287 | else if (try_types[i] == Image::on_atlas) |
1288 | { |
1289 | return_value = create_image_on_atlas(w, h, image_data); |
1290 | } |
1291 | } |
1292 | |
1293 | if (return_value) |
1294 | { |
1295 | return return_value; |
1296 | } |
1297 | |
1298 | return_value = create_image_context_texture2d(w, h, image_data); |
1299 | return return_value; |
1300 | } |
1301 | |
1302 | ////////////////////////////////////// |
1303 | // fastuidraw::Image methods |
1304 | fastuidraw::Image:: |
1305 | Image(ImageAtlas &patlas, int w, int h, unsigned int m, |
1306 | enum type_t type, uint64_t handle, enum format_t fmt, |
1307 | const reference_counted_ptr<Image::ResourceReleaseAction> &action) |
1308 | { |
1309 | ImageAtlasPrivate *atlas_private; |
1310 | atlas_private = static_cast<ImageAtlasPrivate*>(patlas.m_d); |
1311 | m_d = FASTUIDRAWnew ImagePrivate(patlas, atlas_private, w, h, m, type, handle, fmt, action); |
1312 | } |
1313 | |
1314 | fastuidraw::Image:: |
1315 | Image(ImageAtlas &patlas, int w, int h, |
1316 | const ImageSourceBase &image_data) |
1317 | { |
1318 | ImageAtlasPrivate *atlas_private; |
1319 | atlas_private = static_cast<ImageAtlasPrivate*>(patlas.m_d); |
1320 | m_d = FASTUIDRAWnew ImagePrivate(patlas, atlas_private, w, h, image_data); |
1321 | } |
1322 | |
1323 | fastuidraw::Image:: |
1324 | ~Image() |
1325 | { |
1326 | ImagePrivate *d; |
1327 | d = static_cast<ImagePrivate*>(m_d); |
1328 | FASTUIDRAWdelete(d); |
1329 | m_d = nullptr; |
1330 | } |
1331 | |
1332 | |
1333 | unsigned int |
1334 | fastuidraw::Image:: |
1335 | number_index_lookups(void) const |
1336 | { |
1337 | ImagePrivate *d; |
1338 | d = static_cast<ImagePrivate*>(m_d); |
1339 | return d->m_number_index_lookups; |
1340 | } |
1341 | |
1342 | fastuidraw::ivec2 |
1343 | fastuidraw::Image:: |
1344 | dimensions(void) const |
1345 | { |
1346 | ImagePrivate *d; |
1347 | d = static_cast<ImagePrivate*>(m_d); |
1348 | return d->m_dimensions; |
1349 | } |
1350 | |
1351 | unsigned int |
1352 | fastuidraw::Image:: |
1353 | number_mipmap_levels(void) const |
1354 | { |
1355 | ImagePrivate *d; |
1356 | d = static_cast<ImagePrivate*>(m_d); |
1357 | return d->m_number_levels; |
1358 | } |
1359 | |
1360 | fastuidraw::ivec3 |
1361 | fastuidraw::Image:: |
1362 | master_index_tile(void) const |
1363 | { |
1364 | ImagePrivate *d; |
1365 | d = static_cast<ImagePrivate*>(m_d); |
1366 | return d->m_master_index_tile; |
1367 | } |
1368 | |
1369 | fastuidraw::vec2 |
1370 | fastuidraw::Image:: |
1371 | master_index_tile_dims(void) const |
1372 | { |
1373 | ImagePrivate *d; |
1374 | d = static_cast<ImagePrivate*>(m_d); |
1375 | return d->m_master_index_tile_dims; |
1376 | } |
1377 | |
1378 | float |
1379 | fastuidraw::Image:: |
1380 | dimensions_index_divisor(void) const |
1381 | { |
1382 | ImagePrivate *d; |
1383 | d = static_cast<ImagePrivate*>(m_d); |
1384 | return d->m_dimensions_index_divisor; |
1385 | } |
1386 | |
1387 | enum fastuidraw::Image::type_t |
1388 | fastuidraw::Image:: |
1389 | type(void) const |
1390 | { |
1391 | ImagePrivate *d; |
1392 | d = static_cast<ImagePrivate*>(m_d); |
1393 | return d->m_type; |
1394 | } |
1395 | |
1396 | uint64_t |
1397 | fastuidraw::Image:: |
1398 | bindless_handle(void) const |
1399 | { |
1400 | ImagePrivate *d; |
1401 | d = static_cast<ImagePrivate*>(m_d); |
1402 | return d->m_bindless_handle; |
1403 | } |
1404 | |
1405 | enum fastuidraw::Image::format_t |
1406 | fastuidraw::Image:: |
1407 | format(void) const |
1408 | { |
1409 | ImagePrivate *d; |
1410 | d = static_cast<ImagePrivate*>(m_d); |
1411 | return d->m_format; |
1412 | } |
1413 | |