1/*!
2 * \file colorstop_atlas.hpp
3 * \brief file colorstop_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#ifndef FASTUIDRAW_COLORSTOP_ATLAS_HPP
21#define FASTUIDRAW_COLORSTOP_ATLAS_HPP
22
23#include <fastuidraw/util/reference_counted.hpp>
24#include <fastuidraw/colorstop.hpp>
25
26namespace fastuidraw
27{
28/*!\addtogroup PainterBackend
29 * @{
30 */
31
32 /*!
33 * \brief
34 * Represents the interface for the backing store for the texels
35 * of a sequence of color stops. The expectation is that linear
36 * filtering acting on the underlying backing store is all that
37 * is needed for correct color interpolation from a gradient
38 * interpolate. For example in GL, this can be GL_TEXTURE_1D_ARRAY
39 * with both minification and magnification filters set as GL_LINEAR.
40 * An implementation of the class does NOT need to be thread safe
41 * because the user of the backing store (ColorStopAtlas) performs
42 * calls to the backing store behind its own mutex.
43 */
44 class ColorStopBackingStore:
45 public reference_counted<ColorStopBackingStore>::concurrent
46 {
47 public:
48 virtual
49 ~ColorStopBackingStore();
50
51 /*!
52 * To be implemented by a derived class to set color data into the
53 * backing store.
54 * \param x horizontal position
55 * \param l length of data
56 * \param w width of data
57 * \param data RGBA8 values
58 */
59 virtual
60 void
61 set_data(int x, int l, int w,
62 c_array<const u8vec4> data)=0;
63
64 /*!
65 * To be implemented by a derived class to flush set_data() to
66 * the backing store.
67 */
68 virtual
69 void
70 flush(void)
71 {}
72
73 /*!
74 * Returns the dimensions of the backing store (as passed in the
75 * ctor).
76 */
77 ivec2
78 dimensions(void) const;
79
80 /*!
81 * Returns the product of dimensions().x()
82 * against dimensions().y()
83 */
84 int
85 width_times_height(void) const;
86
87 /*!
88 * Resize the object by increasing the number of layers.
89 */
90 void
91 resize(int new_num_layers);
92
93 protected:
94 /*!
95 * Ctor.
96 * \param wl provides the dimensions of the ColorStopBackingStore
97 */
98 explicit
99 ColorStopBackingStore(ivec2 wl);
100
101 /*!
102 * Ctor
103 * \param w width of backing store
104 * \param num_layers number of layers of backing store
105 */
106 ColorStopBackingStore(int w, int num_layers);
107
108 /*!
109 * To be implemented by a derived class to resize the
110 * object. The resize changes ONLY the number of layers
111 * of the object and only increases the value as well.
112 * When called, the return value of dimensions() is
113 * the size before the resize completes.
114 * \param new_num_layers new number of layers to which
115 * to resize the underlying store.
116 */
117 virtual
118 void
119 resize_implement(int new_num_layers) = 0;
120
121 private:
122 void *m_d;
123 };
124
125 /*!
126 * \brief
127 * A ColorStopAtlas is a common location to all color stop data of an
128 * application. Ideally, all color stop sequences are placed into a single
129 * ColorStopAtlas (changes of ColorStopAtlas force draw-call breaks).
130 */
131 class ColorStopAtlas:
132 public reference_counted<ColorStopAtlas>::concurrent
133 {
134 public:
135 /*!
136 * Ctor.
137 * \param pbacking_store handle to the ColorStopBackingStore
138 * object to which the atlas will store color stops
139 */
140 explicit
141 ColorStopAtlas(reference_counted_ptr<ColorStopBackingStore> pbacking_store);
142
143 virtual
144 ~ColorStopAtlas();
145
146 /*!
147 * Create a \ref ColorStopSequence onto this \ref ColorStopAtlas.
148 * \param color_stops source color stops to use
149 * \param pwidth specifies number of texels to occupy on the ColorStopAtlas.
150 * The discretization of the color stop values is specified by
151 * the width. Additionally, the width is clamped to \ref
152 * max_width().
153 */
154 reference_counted_ptr<ColorStopSequence>
155 create(const ColorStopArray &color_stops, unsigned int pwidth);
156
157 /*!
158 * Returns the width of the ColorStopBackingStore
159 * of the atlas.
160 */
161 unsigned int
162 max_width(void) const;
163
164 /*!
165 * Returns a handle to the backing store of the atlas.
166 */
167 reference_counted_ptr<const ColorStopBackingStore>
168 backing_store(void) const;
169
170 /*!
171 * Increments an internal counter. If this internal
172 * counter is greater than zero, then the reurning
173 * of interval to the free store for later use is
174 * -delayed- until the counter reaches zero again
175 * (see unlock_resources()). The use case is
176 * for buffered painting where the GPU calls are delayed
177 * for later (to batch commands) and an Image may go
178 * out of scope before the GPU commands are sent to
179 * the GPU. By delaying the return of intervals to the
180 * freestore, the color stop data is valid still for
181 * rendering even if the owning ColorStopSequence
182 * has been deleted.
183 */
184 void
185 lock_resources(void);
186
187 /*!
188 * Decrements an internal counter. If this internal
189 * counter reaches zero, those intervals from those
190 * ColorStopSequence objects that were deleted
191 * while the counter was non-zero, are then returned
192 * to the interval free store. See lock_resources()
193 * for more details.
194 */
195 void
196 unlock_resources(void);
197
198 /*!
199 * Calls ColorStopBackingStore::flush() on
200 * the backing store (see backing_store()).
201 */
202 void
203 flush(void) const;
204
205 private:
206 friend class ColorStopSequence;
207
208 /*!
209 * Allocate and set on the atlas a sequence of color values
210 * to be stored continuously in a common layer. Returns
211 * the offset into the layer in ivec2::x() and the which
212 * layer in ivec2::y().
213 * \param data data to place on atlas
214 */
215 ivec2
216 allocate(c_array<const u8vec4> data);
217
218 /*!
219 * Mark a region to be free on the atlas
220 * \param location .x() gives the offset into the layer to
221 * mark as free and .y() gives the layer
222 * \param width number of elements to mark as free
223 */
224 void
225 deallocate(ivec2 location, int width);
226
227 /*!
228 * Returns the total number of color stops that are available
229 * in the atlas without resizing the ColorStopBackingStore
230 * of the ColorStopAtlas.
231 */
232 int
233 total_available(void) const;
234
235 void *m_d;
236 };
237
238/*! @} */
239}
240
241#endif
242