Cycles:
[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_opengl.h"
28 #include "util_types.h"
29 #include "util_vector.h"
30
31 CCL_NAMESPACE_BEGIN
32
33 /* Device Task */
34
35 DeviceTask::DeviceTask(Type type_)
36 : type(type_), x(0), y(0), w(0), h(0), rng_state(0), rgba(0), buffer(0),
37   pass(0), resolution(0),
38   displace_input(0), displace_offset(0), displace_x(0), displace_w(0)
39 {
40 }
41
42 void DeviceTask::split(ThreadQueue<DeviceTask>& tasks, int num)
43 {
44         if(type == DISPLACE) {
45                 for(int i = 0; i < num; i++) {
46                         int tx = displace_x + (displace_w/num)*i;
47                         int tw = (i == num-1)? displace_w - i*(displace_w/num): displace_w/num;
48
49                         DeviceTask task = *this;
50
51                         task.displace_x = tx;
52                         task.displace_w = tw;
53
54                         tasks.push(task);
55                 }
56         }
57         else {
58                 for(int i = 0; i < num; i++) {
59                         int ty = y + (h/num)*i;
60                         int th = (i == num-1)? h - i*(h/num): h/num;
61
62                         DeviceTask task = *this;
63
64                         task.y = ty;
65                         task.h = th;
66
67                         tasks.push(task);
68                 }
69         }
70 }
71
72 /* Device */
73
74 void Device::pixels_alloc(device_memory& mem)
75 {
76         mem_alloc(mem, MEM_READ_WRITE);
77 }
78
79 void Device::pixels_copy_from(device_memory& mem, int y, int w, int h)
80 {
81         mem_copy_from(mem, sizeof(uchar)*4*y*w, sizeof(uchar)*4*w*h);
82 }
83
84 void Device::pixels_free(device_memory& mem)
85 {
86         mem_free(mem);
87 }
88
89 void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int width, int height, bool transparent)
90 {
91         pixels_copy_from(rgba, y, w, h);
92
93         if(transparent) {
94                 glEnable(GL_BLEND);
95                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
96         }
97
98         glPixelZoom((float)width/(float)w, (float)height/(float)h);
99         glRasterPos2f(0, y);
100
101         glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)rgba.data_pointer);
102
103         glRasterPos2f(0.0f, 0.0f);
104         glPixelZoom(1.0f, 1.0f);
105
106         if(transparent)
107                 glDisable(GL_BLEND);
108 }
109
110 Device *Device::create(DeviceType type, bool background, int threads)
111 {
112         Device *device;
113
114         switch(type) {
115                 case DEVICE_CPU:
116                         device = device_cpu_create(threads);
117                         break;
118 #ifdef WITH_CUDA
119                 case DEVICE_CUDA:
120                         if(cuLibraryInit())
121                                 device = device_cuda_create(background);
122                         else
123                                 device = NULL;
124                         break;
125 #endif
126 #ifdef WITH_MULTI
127                 case DEVICE_MULTI:
128                         device = device_multi_create(background);
129                         break;
130 #endif
131 #ifdef WITH_NETWORK
132                 case DEVICE_NETWORK:
133                         device = device_network_create("127.0.0.1");
134                         break;
135 #endif
136 #ifdef WITH_OPENCL
137                 case DEVICE_OPENCL:
138                         device = device_opencl_create(background);
139                         break;
140 #endif
141                 default:
142                         return NULL;
143         }
144
145         return device;
146 }
147
148 DeviceType Device::type_from_string(const char *name)
149 {
150         if(strcmp(name, "cpu") == 0)
151                 return DEVICE_CPU;
152         else if(strcmp(name, "cuda") == 0)
153                 return DEVICE_CUDA;
154         else if(strcmp(name, "opencl") == 0)
155                 return DEVICE_OPENCL;
156         else if(strcmp(name, "network") == 0)
157                 return DEVICE_NETWORK;
158         else if(strcmp(name, "multi") == 0)
159                 return DEVICE_MULTI;
160         
161         return DEVICE_NONE;
162 }
163
164 string Device::string_from_type(DeviceType type)
165 {
166         if(type == DEVICE_CPU)
167                 return "cpu";
168         else if(type == DEVICE_CUDA)
169                 return "cuda";
170         else if(type == DEVICE_OPENCL)
171                 return "opencl";
172         else if(type == DEVICE_NETWORK)
173                 return "network";
174         else if(type == DEVICE_MULTI)
175                 return "multi";
176         
177         return "";
178 }
179
180 vector<DeviceType> Device::available_types()
181 {
182         vector<DeviceType> types;
183
184         types.push_back(DEVICE_CPU);
185
186 #ifdef WITH_CUDA
187         if(cuLibraryInit())
188                 types.push_back(DEVICE_CUDA);
189 #endif
190
191 #ifdef WITH_OPENCL
192         types.push_back(DEVICE_OPENCL);
193 #endif
194
195 #ifdef WITH_NETWORK
196         types.push_back(DEVICE_NETWORK);
197 #endif
198 #ifdef WITH_MULTI
199         types.push_back(DEVICE_MULTI);
200 #endif
201
202         return types;
203 }
204
205 CCL_NAMESPACE_END
206