Merging r50049 through r50076 from trunk into soc-2011-tomato
[blender.git] / intern / cycles / render / tile.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "tile.h"
20
21 #include "util_algorithm.h"
22 #include "util_types.h"
23
24 CCL_NAMESPACE_BEGIN
25
26 TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int resolution_, int num_devices_)
27 {
28         progressive = progressive_;
29         tile_size = tile_size_;
30         resolution = resolution_;
31         num_devices = num_devices_;
32
33         BufferParams buffer_params;
34         reset(buffer_params, 0);
35 }
36
37 TileManager::~TileManager()
38 {
39 }
40
41 void TileManager::reset(BufferParams& params_, int num_samples_)
42 {
43         params = params_;
44
45         num_samples = num_samples_;
46
47         state.buffer = BufferParams();
48         state.sample = -1;
49         state.num_tiles = 0;
50         state.num_rendered_tiles = 0;
51         state.num_samples = 0;
52         state.resolution = resolution;
53         state.tiles.clear();
54 }
55
56 void TileManager::set_samples(int num_samples_)
57 {
58         num_samples = num_samples_;
59 }
60
61 void TileManager::set_tiles()
62 {
63         int resolution = state.resolution;
64         int image_w = max(1, params.width/resolution);
65         int image_h = max(1, params.height/resolution);
66
67         state.tiles.clear();
68
69         int num = min(image_h, num_devices);
70
71         for(int device = 0; device < num; device++) {
72                 int device_y = (image_h/num)*device;
73                 int device_h = (device == num-1)? image_h - device*(image_h/num): image_h/num;
74
75                 int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
76                 int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y;
77                 int sub_w = (image_w + tile_w - 1)/tile_w;
78                 int sub_h = (device_h + tile_h - 1)/tile_h;
79
80                 for(int tile_y = 0; tile_y < tile_h; tile_y++) {
81                         for(int tile_x = 0; tile_x < tile_w; tile_x++) {
82                                 int x = tile_x * sub_w;
83                                 int y = tile_y * sub_h;
84                                 int w = (tile_x == tile_w-1)? image_w - x: sub_w;
85                                 int h = (tile_y == tile_h-1)? device_h - y: sub_h;
86
87                                 state.tiles.push_back(Tile(x, y + device_y, w, h, device));
88                         }
89                 }
90         }
91
92         state.num_tiles = state.tiles.size();
93
94         state.buffer.width = image_w;
95         state.buffer.height = image_h;
96
97         state.buffer.full_x = params.full_x/resolution;
98         state.buffer.full_y = params.full_y/resolution;
99         state.buffer.full_width = max(1, params.full_width/resolution);
100         state.buffer.full_height = max(1, params.full_height/resolution);
101 }
102
103 list<Tile>::iterator TileManager::next_center_tile(int device)
104 {
105         list<Tile>::iterator iter, best = state.tiles.end();
106
107         int resolution = state.resolution;
108         int image_w = max(1, params.width/resolution);
109         int image_h = max(1, params.height/resolution);
110
111         int num = min(image_h, num_devices);
112
113         int device_y = (image_h / num) * device;
114         int device_h = (device == num - 1) ? image_h - device * (image_h / num) : image_h / num;
115
116         int64_t centx = image_w / 2, centy = device_y + device_h / 2, tot = 1;
117         int64_t mindist = (int64_t) image_w * (int64_t) device_h;
118
119         /* find center of rendering tiles, image center counts for 1 too */
120         for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
121                 if(iter->rendering) {
122                         Tile &cur_tile = *iter;
123                         centx += cur_tile.x + cur_tile.w / 2;
124                         centy += cur_tile.y + cur_tile.h / 2;
125                         tot++;
126                 }
127         }
128
129         centx /= tot;
130         centy /= tot;
131
132         /* closest of the non-rendering tiles */
133         for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
134                 if(iter->device == device && iter->rendering == false) {
135                         Tile &cur_tile = *iter;
136
137                         int64_t distx = centx - (cur_tile.x + cur_tile.w / 2);
138                         int64_t disty = centy - (cur_tile.y + cur_tile.h / 2);
139                         distx = (int64_t) sqrt((double)distx * distx + disty * disty);
140
141                         if(distx < mindist) {
142                                 best = iter;
143                                 mindist = distx;
144                         }
145                 }
146         }
147
148         return best;
149 }
150
151 bool TileManager::next_tile(Tile& tile, int device)
152 {
153         list<Tile>::iterator tile_it;
154
155         tile_it = next_center_tile(device);
156
157         if(tile_it != state.tiles.end()) {
158                 tile_it->rendering = true;
159                 tile = *tile_it;
160                 state.num_rendered_tiles++;
161
162                 return true;
163         }
164
165         return false;
166 }
167
168 bool TileManager::done()
169 {
170         return (state.sample+state.num_samples >= num_samples && state.resolution == 1);
171 }
172
173 bool TileManager::next()
174 {
175         if(done())
176                 return false;
177
178         if(progressive && state.resolution > 1) {
179                 state.sample = 0;
180                 state.resolution /= 2;
181                 state.num_samples = 1;
182                 set_tiles();
183         }
184         else {
185                 state.sample++;
186
187                 if(progressive)
188                         state.num_samples = 1;
189                 else
190                         state.num_samples = num_samples;
191
192                 state.resolution = 1;
193                 set_tiles();
194         }
195
196         return true;
197 }
198
199 CCL_NAMESPACE_END
200