Cycles: Make all #include statements relative to cycles source directory
[blender.git] / intern / cycles / util / util_progress.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __UTIL_PROGRESS_H__
18 #define __UTIL_PROGRESS_H__
19
20 /* Progress
21  *
22  * Simple class to communicate progress status messages, timing information,
23  * update notifications from a job running in another thread. All methods
24  * except for the constructor/destructor are thread safe. */
25
26 #include "util/util_function.h"
27 #include "util/util_string.h"
28 #include "util/util_time.h"
29 #include "util/util_thread.h"
30
31 CCL_NAMESPACE_BEGIN
32
33 class Progress {
34 public:
35         Progress()
36         {
37                 pixel_samples = 0;
38                 total_pixel_samples = 0;
39                 current_tile_sample = 0;
40                 finished_tiles = 0;
41                 start_time = time_dt();
42                 render_start_time = time_dt();
43                 status = "Initializing";
44                 substatus = "";
45                 sync_status = "";
46                 sync_substatus = "";
47                 update_cb = function_null;
48                 cancel = false;
49                 cancel_message = "";
50                 error = false;
51                 error_message = "";
52                 cancel_cb = function_null;
53         }
54
55         Progress(Progress& progress)
56         {
57                 *this = progress;
58         }
59
60         Progress& operator=(Progress& progress)
61         {
62                 thread_scoped_lock lock(progress.progress_mutex);
63
64                 progress.get_status(status, substatus);
65
66                 pixel_samples = progress.pixel_samples;
67                 total_pixel_samples = progress.total_pixel_samples;
68                 current_tile_sample = progress.get_current_sample();
69
70                 return *this;
71         }
72
73         void reset()
74         {
75                 pixel_samples = 0;
76                 total_pixel_samples = 0;
77                 current_tile_sample = 0;
78                 finished_tiles = 0;
79                 start_time = time_dt();
80                 render_start_time = time_dt();
81                 status = "Initializing";
82                 substatus = "";
83                 sync_status = "";
84                 sync_substatus = "";
85                 cancel = false;
86                 cancel_message = "";
87                 error = false;
88                 error_message = "";
89         }
90
91         /* cancel */
92         void set_cancel(const string& cancel_message_)
93         {
94                 thread_scoped_lock lock(progress_mutex);
95                 cancel_message = cancel_message_;
96                 cancel = true;
97         }
98
99         bool get_cancel()
100         {
101                 if(!cancel && cancel_cb)
102                         cancel_cb();
103
104                 return cancel;
105         }
106
107         string get_cancel_message()
108         {
109                 thread_scoped_lock lock(progress_mutex);
110                 return cancel_message;
111         }
112
113         void set_cancel_callback(function<void(void)> function)
114         {
115                 cancel_cb = function;
116         }
117
118         /* error */
119         void set_error(const string& error_message_)
120         {
121                 thread_scoped_lock lock(progress_mutex);
122                 error_message = error_message_;
123                 error = true;
124                 /* If error happens we also stop rendering. */
125                 cancel_message = error_message_;
126                 cancel = true;
127         }
128
129         bool get_error()
130         {
131                 return error;
132         }
133
134         string get_error_message()
135         {
136                 thread_scoped_lock lock(progress_mutex);
137                 return error_message;
138         }
139
140         /* tile and timing information */
141
142         void set_start_time()
143         {
144                 thread_scoped_lock lock(progress_mutex);
145
146                 start_time = time_dt();
147         }
148
149         void set_render_start_time()
150         {
151                 thread_scoped_lock lock(progress_mutex);
152
153                 render_start_time = time_dt();
154         }
155
156         void add_skip_time(const scoped_timer &start_timer, bool only_render)
157         {
158                 double skip_time = time_dt() - start_timer.get_start();
159
160                 render_start_time += skip_time;
161                 if(!only_render) {
162                         start_time += skip_time;
163                 }
164         }
165
166         void get_time(double& total_time_, double& render_time_)
167         {
168                 thread_scoped_lock lock(progress_mutex);
169
170                 total_time_ = time_dt() - start_time;
171                 render_time_ = time_dt() - render_start_time;
172         }
173
174         void reset_sample()
175         {
176                 thread_scoped_lock lock(progress_mutex);
177
178                 pixel_samples = 0;
179                 current_tile_sample = 0;
180                 finished_tiles = 0;
181         }
182
183         void set_total_pixel_samples(uint64_t total_pixel_samples_)
184         {
185                 thread_scoped_lock lock(progress_mutex);
186
187                 total_pixel_samples = total_pixel_samples_;
188         }
189
190         float get_progress()
191         {
192                 if(total_pixel_samples > 0) {
193                         return ((float) pixel_samples) / total_pixel_samples;
194                 }
195                 return 0.0f;
196         }
197
198         void add_samples(uint64_t pixel_samples_, int tile_sample)
199         {
200                 thread_scoped_lock lock(progress_mutex);
201
202                 pixel_samples += pixel_samples_;
203                 current_tile_sample = tile_sample;
204         }
205
206         void add_samples_update(uint64_t pixel_samples_, int tile_sample)
207         {
208                 add_samples(pixel_samples_, tile_sample);
209                 set_update();
210         }
211
212         void add_finished_tile()
213         {
214                 thread_scoped_lock lock(progress_mutex);
215
216                 finished_tiles++;
217         }
218
219         int get_current_sample()
220         {
221                 /* Note that the value here always belongs to the last tile that updated,
222                  * so it's only useful if there is only one active tile. */
223                 return current_tile_sample;
224         }
225
226         int get_finished_tiles()
227         {
228                 return finished_tiles;
229         }
230
231         /* status messages */
232
233         void set_status(const string& status_, const string& substatus_ = "")
234         {
235                 {
236                         thread_scoped_lock lock(progress_mutex);
237                         status = status_;
238                         substatus = substatus_;
239                 }
240
241                 set_update();
242         }
243
244         void set_substatus(const string& substatus_)
245         {
246                 {
247                         thread_scoped_lock lock(progress_mutex);
248                         substatus = substatus_;
249                 }
250
251                 set_update();
252         }
253
254         void set_sync_status(const string& status_, const string& substatus_ = "")
255         {
256                 {
257                         thread_scoped_lock lock(progress_mutex);
258                         sync_status = status_;
259                         sync_substatus = substatus_;
260                 }
261
262                 set_update();
263
264         }
265
266         void set_sync_substatus(const string& substatus_)
267         {
268                 {
269                         thread_scoped_lock lock(progress_mutex);
270                         sync_substatus = substatus_;
271                 }
272
273                 set_update();
274         }
275
276         void get_status(string& status_, string& substatus_)
277         {
278                 thread_scoped_lock lock(progress_mutex);
279
280                 if(sync_status != "") {
281                         status_ = sync_status;
282                         substatus_ = sync_substatus;
283                 }
284                 else {
285                         status_ = status;
286                         substatus_ = substatus;
287                 }
288         }
289
290         /* callback */
291
292         void set_update()
293         {
294                 if(update_cb) {
295                         thread_scoped_lock lock(update_mutex);
296                         update_cb();
297                 }
298         }
299
300         void set_update_callback(function<void(void)> function)
301         {
302                 update_cb = function;
303         }
304
305 protected:
306         thread_mutex progress_mutex;
307         thread_mutex update_mutex;
308         function<void(void)> update_cb;
309         function<void(void)> cancel_cb;
310
311         /* pixel_samples counts how many samples have been rendered over all pixel, not just per pixel.
312          * This makes the progress estimate more accurate when tiles with different sizes are used.
313          *
314          * total_pixel_samples is the total amount of pixel samples that will be rendered. */
315         uint64_t pixel_samples, total_pixel_samples;
316         /* Stores the current sample count of the last tile that called the update function.
317          * It's used to display the sample count if only one tile is active. */
318         int current_tile_sample;
319         /* Stores the number of tiles that's already finished.
320          * Used to determine whether all but the last tile are finished rendering, in which case the current_tile_sample is displayed. */
321         int finished_tiles;
322
323         double start_time, render_start_time;
324
325         string status;
326         string substatus;
327
328         string sync_status;
329         string sync_substatus;
330
331         volatile bool cancel;
332         string cancel_message;
333
334         volatile bool error;
335         string error_message;
336 };
337
338 CCL_NAMESPACE_END
339
340 #endif /* __UTIL_PROGRESS_H__ */
341