Camera tracking: improvements of track preview widget
[blender.git] / intern / cycles / device / device.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 <stdlib.h>
20 #include <string.h>
21
22 #include "device.h"
23 #include "device_intern.h"
24
25 #include "util_cuda.h"
26 #include "util_debug.h"
27 #include "util_foreach.h"
28 #include "util_math.h"
29 #include "util_opencl.h"
30 #include "util_opengl.h"
31 #include "util_types.h"
32 #include "util_vector.h"
33
34 CCL_NAMESPACE_BEGIN
35
36 /* Device Task */
37
38 DeviceTask::DeviceTask(Type type_)
39 : type(type_), x(0), y(0), w(0), h(0), rng_state(0), rgba(0), buffer(0),
40   sample(0), resolution(0),
41   displace_input(0), displace_offset(0), displace_x(0), displace_w(0)
42 {
43 }
44
45 void DeviceTask::split_max_size(list<DeviceTask>& tasks, int max_size)
46 {
47         int num;
48
49         if(type == DISPLACE) {
50                 num = (displace_w + max_size - 1)/max_size;
51         }
52         else {
53                 max_size = max(1, max_size/w);
54                 num = (h + max_size - 1)/max_size;
55         }
56
57         split(tasks, num);
58 }
59
60 void DeviceTask::split(ThreadQueue<DeviceTask>& queue, int num)
61 {
62         list<DeviceTask> tasks;
63         split(tasks, num);
64
65         foreach(DeviceTask& task, tasks)
66                 queue.push(task);
67 }
68
69 void DeviceTask::split(list<DeviceTask>& tasks, int num)
70 {
71         if(type == DISPLACE) {
72                 num = min(displace_w, num);
73
74                 for(int i = 0; i < num; i++) {
75                         int tx = displace_x + (displace_w/num)*i;
76                         int tw = (i == num-1)? displace_w - i*(displace_w/num): displace_w/num;
77
78                         DeviceTask task = *this;
79
80                         task.displace_x = tx;
81                         task.displace_w = tw;
82
83                         tasks.push_back(task);
84                 }
85         }
86         else {
87                 num = min(h, num);
88
89                 for(int i = 0; i < num; i++) {
90                         int ty = y + (h/num)*i;
91                         int th = (i == num-1)? h - i*(h/num): h/num;
92
93                         DeviceTask task = *this;
94
95                         task.y = ty;
96                         task.h = th;
97
98                         tasks.push_back(task);
99                 }
100         }
101 }
102
103 /* Device */
104
105 void Device::pixels_alloc(device_memory& mem)
106 {
107         mem_alloc(mem, MEM_READ_WRITE);
108 }
109
110 void Device::pixels_copy_from(device_memory& mem, int y, int w, int h)
111 {
112         mem_copy_from(mem, sizeof(uint8_t)*4*y*w, sizeof(uint8_t)*4*w*h);
113 }
114
115 void Device::pixels_free(device_memory& mem)
116 {
117         mem_free(mem);
118 }
119
120 void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int width, int height, bool transparent)
121 {
122         pixels_copy_from(rgba, y, w, h);
123
124         if(transparent) {
125                 glEnable(GL_BLEND);
126                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
127         }
128
129         glPixelZoom((float)width/(float)w, (float)height/(float)h);
130         glRasterPos2f(0, y);
131
132         uint8_t *pixels = (uint8_t*)rgba.data_pointer;
133
134         /* for multi devices, this assumes the ineffecient method that we allocate
135            all pixels on the device even though we only render to a subset */
136         pixels += 4*y*w;
137
138         glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
139
140         glRasterPos2f(0.0f, 0.0f);
141         glPixelZoom(1.0f, 1.0f);
142
143         if(transparent)
144                 glDisable(GL_BLEND);
145 }
146
147 Device *Device::create(DeviceType type, bool background, int threads)
148 {
149         Device *device;
150
151         switch(type) {
152                 case DEVICE_CPU:
153                         device = device_cpu_create(threads);
154                         break;
155 #ifdef WITH_CUDA
156                 case DEVICE_CUDA:
157                         if(cuLibraryInit())
158                                 device = device_cuda_create(background);
159                         else
160                                 device = NULL;
161                         break;
162 #endif
163 #ifdef WITH_MULTI
164                 case DEVICE_MULTI:
165                         device = device_multi_create(background);
166                         break;
167 #endif
168 #ifdef WITH_NETWORK
169                 case DEVICE_NETWORK:
170                         device = device_network_create("127.0.0.1");
171                         break;
172 #endif
173 #ifdef WITH_OPENCL
174                 case DEVICE_OPENCL:
175                         if(clLibraryInit())
176                                 device = device_opencl_create(background);
177                         else
178                                 device = NULL;
179                         break;
180 #endif
181                 default:
182                         return NULL;
183         }
184
185         return device;
186 }
187
188 DeviceType Device::type_from_string(const char *name)
189 {
190         if(strcmp(name, "cpu") == 0)
191                 return DEVICE_CPU;
192         else if(strcmp(name, "cuda") == 0)
193                 return DEVICE_CUDA;
194         else if(strcmp(name, "opencl") == 0)
195                 return DEVICE_OPENCL;
196         else if(strcmp(name, "network") == 0)
197                 return DEVICE_NETWORK;
198         else if(strcmp(name, "multi") == 0)
199                 return DEVICE_MULTI;
200         
201         return DEVICE_NONE;
202 }
203
204 string Device::string_from_type(DeviceType type)
205 {
206         if(type == DEVICE_CPU)
207                 return "cpu";
208         else if(type == DEVICE_CUDA)
209                 return "cuda";
210         else if(type == DEVICE_OPENCL)
211                 return "opencl";
212         else if(type == DEVICE_NETWORK)
213                 return "network";
214         else if(type == DEVICE_MULTI)
215                 return "multi";
216         
217         return "";
218 }
219
220 vector<DeviceType> Device::available_types()
221 {
222         vector<DeviceType> types;
223
224         types.push_back(DEVICE_CPU);
225
226 #ifdef WITH_CUDA
227         if(cuLibraryInit())
228                 types.push_back(DEVICE_CUDA);
229 #endif
230
231 #ifdef WITH_OPENCL
232         if(clLibraryInit())
233                 types.push_back(DEVICE_OPENCL);
234 #endif
235
236 #ifdef WITH_NETWORK
237         types.push_back(DEVICE_NETWORK);
238 #endif
239 #ifdef WITH_MULTI
240         types.push_back(DEVICE_MULTI);
241 #endif
242
243         return types;
244 }
245
246 CCL_NAMESPACE_END
247