Merging r48971 through r48980 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
23 CCL_NAMESPACE_BEGIN
24
25 TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int min_size_, int num_devices_)
26 {
27         progressive = progressive_;
28         tile_size = tile_size_;
29         min_size = min_size_;
30         num_devices = num_devices_;
31
32         BufferParams buffer_params;
33         reset(buffer_params, 0);
34 }
35
36 TileManager::~TileManager()
37 {
38 }
39
40 void TileManager::reset(BufferParams& params_, int num_samples_)
41 {
42         params = params_;
43
44         start_resolution = 1;
45
46         int w = params.width, h = params.height;
47
48         if(min_size != INT_MAX) {
49                 while(w*h > min_size*min_size) {
50                         w = max(1, w/2); 
51                         h = max(1, h/2); 
52
53                         start_resolution *= 2;
54                 }
55         }
56
57         num_samples = num_samples_;
58
59         state.buffer = BufferParams();
60         state.sample = -1;
61         state.num_tiles = 0;
62         state.num_samples = 0;
63         state.resolution = start_resolution;
64         state.tiles.clear();
65 }
66
67 void TileManager::set_samples(int num_samples_)
68 {
69         num_samples = num_samples_;
70 }
71
72 void TileManager::set_tiles()
73 {
74         int resolution = state.resolution;
75         int image_w = max(1, params.width/resolution);
76         int image_h = max(1, params.height/resolution);
77
78         state.tiles.clear();
79
80         int num = min(image_h, num_devices);
81
82         for(int device = 0; device < num; device++) {
83                 int device_y = (image_h/num)*device;
84                 int device_h = (device == num-1)? image_h - device*(image_h/num): image_h/num;
85
86                 int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
87                 int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y;
88                 int sub_w = (image_w + tile_w - 1)/tile_w;
89                 int sub_h = (device_h + tile_h - 1)/tile_h;
90
91                 for(int tile_y = 0; tile_y < tile_h; tile_y++) {
92                         for(int tile_x = 0; tile_x < tile_w; tile_x++) {
93                                 int x = tile_x * sub_w;
94                                 int y = tile_y * sub_h;
95                                 int w = (tile_x == tile_w-1)? image_w - x: sub_w;
96                                 int h = (tile_y == tile_h-1)? device_h - y: sub_h;
97
98                                 state.tiles.push_back(Tile(x, y + device_y, w, h, device));
99                         }
100                 }
101         }
102
103         state.num_tiles = state.tiles.size();
104
105         state.buffer.width = image_w;
106         state.buffer.height = image_h;
107
108         state.buffer.full_x = params.full_x/resolution;
109         state.buffer.full_y = params.full_y/resolution;
110         state.buffer.full_width = max(1, params.full_width/resolution);
111         state.buffer.full_height = max(1, params.full_height/resolution);
112 }
113
114 bool TileManager::next_tile(Tile& tile, int device)
115 {
116         list<Tile>::iterator iter;
117
118         for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
119                 if(iter->device == device) {
120                         tile = *iter;
121                         state.tiles.erase(iter);
122                         return true;
123                 }
124         }
125
126         return false;
127 }
128
129 bool TileManager::done()
130 {
131         return (state.sample+state.num_samples >= num_samples && state.resolution == 1);
132 }
133
134 bool TileManager::next()
135 {
136         if(done())
137                 return false;
138
139         if(progressive && state.resolution > 1) {
140                 state.sample = 0;
141                 state.resolution /= 2;
142                 state.num_samples = 1;
143                 set_tiles();
144         }
145         else {
146                 state.sample++;
147
148                 if(progressive)
149                         state.num_samples = 1;
150                 else
151                         state.num_samples = num_samples;
152
153                 state.resolution = 1;
154                 set_tiles();
155         }
156
157         return true;
158 }
159
160 CCL_NAMESPACE_END
161