Cycles: Code cleanup, spaces around keywords
[blender-staging.git] / intern / cycles / render / tile.cpp
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 #include "tile.h"
18
19 #include "util_algorithm.h"
20 #include "util_types.h"
21
22 CCL_NAMESPACE_BEGIN
23
24 TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_,
25                          bool preserve_tile_device_, bool background_, TileOrder tile_order_, int num_devices_)
26 {
27         progressive = progressive_;
28         tile_size = tile_size_;
29         tile_order = tile_order_;
30         start_resolution = start_resolution_;
31         num_samples = num_samples_;
32         num_devices = num_devices_;
33         preserve_tile_device = preserve_tile_device_;
34         background = background_;
35
36         BufferParams buffer_params;
37         reset(buffer_params, 0);
38 }
39
40 TileManager::~TileManager()
41 {
42 }
43
44 void TileManager::reset(BufferParams& params_, int num_samples_)
45 {
46         params = params_;
47
48         int divider = 1;
49         int w = params.width, h = params.height;
50
51         if(start_resolution != INT_MAX) {
52                 while(w*h > start_resolution*start_resolution) {
53                         w = max(1, w/2); 
54                         h = max(1, h/2); 
55
56                         divider *= 2;
57                 }
58         }
59
60         num_samples = num_samples_;
61
62         state.buffer = BufferParams();
63         state.sample = -1;
64         state.num_tiles = 0;
65         state.num_rendered_tiles = 0;
66         state.num_samples = 0;
67         state.resolution_divider = divider;
68         state.tiles.clear();
69 }
70
71 void TileManager::set_samples(int num_samples_)
72 {
73         num_samples = num_samples_;
74 }
75
76 /* splits image into tiles and assigns equal amount of tiles to every render device */
77 void TileManager::gen_tiles_global()
78 {
79         int resolution = state.resolution_divider;
80         int image_w = max(1, params.width/resolution);
81         int image_h = max(1, params.height/resolution);
82
83         state.tiles.clear();
84
85         int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
86         int tile_h = (tile_size.y >= image_h)? 1: (image_h + tile_size.y - 1)/tile_size.y;
87
88         int num_logical_devices = preserve_tile_device? num_devices: 1;
89         int num = min(image_h, num_logical_devices);
90         int tile_index = 0;
91
92         int tiles_per_device = (tile_w * tile_h + num - 1) / num;
93         int cur_device = 0, cur_tiles = 0;
94
95         for(int tile_y = 0; tile_y < tile_h; tile_y++) {
96                 for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
97                         int x = tile_x * tile_size.x;
98                         int y = tile_y * tile_size.y;
99                         int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
100                         int h = (tile_y == tile_h-1)? image_h - y: tile_size.y;
101
102                         state.tiles.push_back(Tile(tile_index, x, y, w, h, cur_device));
103                         cur_tiles++;
104
105                         if(cur_tiles == tiles_per_device) {
106                                 cur_tiles = 0;
107                                 cur_device++;
108                         }
109                 }
110         }
111 }
112
113 /* slices image into as much pieces as how many devices are rendering this image */
114 void TileManager::gen_tiles_sliced()
115 {
116         int resolution = state.resolution_divider;
117         int image_w = max(1, params.width/resolution);
118         int image_h = max(1, params.height/resolution);
119
120         state.tiles.clear();
121
122         int num_logical_devices = preserve_tile_device? num_devices: 1;
123         int num = min(image_h, num_logical_devices);
124         int tile_index = 0;
125
126         for(int device = 0; device < num; device++) {
127                 int device_y = (image_h/num)*device;
128                 int device_h = (device == num-1)? image_h - device*(image_h/num): image_h/num;
129
130                 int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
131                 int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y;
132
133                 for(int tile_y = 0; tile_y < tile_h; tile_y++) {
134                         for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
135                                 int x = tile_x * tile_size.x;
136                                 int y = tile_y * tile_size.y;
137                                 int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
138                                 int h = (tile_y == tile_h-1)? device_h - y: tile_size.y;
139
140                                 state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device));
141                         }
142                 }
143         }
144 }
145
146 void TileManager::set_tiles()
147 {
148         int resolution = state.resolution_divider;
149         int image_w = max(1, params.width/resolution);
150         int image_h = max(1, params.height/resolution);
151
152         if(background)
153                 gen_tiles_global();
154         else
155                 gen_tiles_sliced();
156
157         state.num_tiles = state.tiles.size();
158
159         state.buffer.width = image_w;
160         state.buffer.height = image_h;
161
162         state.buffer.full_x = params.full_x/resolution;
163         state.buffer.full_y = params.full_y/resolution;
164         state.buffer.full_width = max(1, params.full_width/resolution);
165         state.buffer.full_height = max(1, params.full_height/resolution);
166 }
167
168 list<Tile>::iterator TileManager::next_viewport_tile(int device)
169 {
170         list<Tile>::iterator iter;
171
172         int logical_device = preserve_tile_device? device: 0;
173
174         for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
175                 if(iter->device == logical_device && iter->rendering == false)
176                 return iter;
177         }
178
179         return state.tiles.end();
180 }
181
182 list<Tile>::iterator TileManager::next_background_tile(int device, TileOrder tile_order)
183 {
184         list<Tile>::iterator iter, best = state.tiles.end();
185
186         int resolution = state.resolution_divider;
187         int logical_device = preserve_tile_device? device: 0;
188
189         int64_t cordx = max(1, params.width/resolution);
190         int64_t cordy = max(1, params.height/resolution);
191         int64_t mindist = INT_MAX;
192         
193         int64_t centx = cordx / 2, centy = cordy / 2;
194
195         for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
196                 if(iter->device == logical_device && iter->rendering == false) {
197                         Tile &cur_tile = *iter;
198                         
199                         int64_t distx = cordx;
200                         int64_t disty = cordy;
201                         
202                         switch (tile_order) {
203                                 case TILE_CENTER:
204                                         distx = centx - (cur_tile.x + (cur_tile.w / 2));
205                                         disty = centy - (cur_tile.y + (cur_tile.h / 2));
206                                         distx = (int64_t)sqrt((double)(distx * distx + disty * disty));
207                                         break;
208                                 case TILE_RIGHT_TO_LEFT:
209                                         distx = cordx - cur_tile.x;
210                                         break;
211                                 case TILE_LEFT_TO_RIGHT:
212                                         distx = cordx + cur_tile.x;     
213                                         break;
214                                 case TILE_TOP_TO_BOTTOM:
215                                         distx = cordx - cur_tile.y;
216                                         break;
217                                 case TILE_BOTTOM_TO_TOP:
218                                         distx = cordx + cur_tile.y;
219                                         break; 
220                                 default:
221                                         break;
222                         }
223
224                         if(distx < mindist) {
225                                 best = iter;
226                                 mindist = distx;
227                         }
228                 }
229         }
230
231         return best;
232 }
233
234 bool TileManager::next_tile(Tile& tile, int device)
235 {
236         list<Tile>::iterator tile_it;
237         
238         if(background)
239                 tile_it = next_background_tile(device, tile_order);
240         else
241                 tile_it = next_viewport_tile(device);
242
243         if(tile_it != state.tiles.end()) {
244                 tile_it->rendering = true;
245                 tile = *tile_it;
246                 state.num_rendered_tiles++;
247
248                 return true;
249         }
250
251         return false;
252 }
253
254 bool TileManager::done()
255 {
256         return (state.sample+state.num_samples >= num_samples && state.resolution_divider == 1);
257 }
258
259 bool TileManager::next()
260 {
261         if(done())
262                 return false;
263
264         if(progressive && state.resolution_divider > 1) {
265                 state.sample = 0;
266                 state.resolution_divider /= 2;
267                 state.num_samples = 1;
268                 set_tiles();
269         }
270         else {
271                 state.sample++;
272
273                 if(progressive)
274                         state.num_samples = 1;
275                 else
276                         state.num_samples = num_samples;
277
278                 state.resolution_divider = 1;
279                 set_tiles();
280         }
281
282         return true;
283 }
284
285 CCL_NAMESPACE_END
286