Code cleanup: tweaks to image manager code found while looking into previous bug.
[blender-staging.git] / intern / cycles / render / image.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 "device.h"
18 #include "image.h"
19 #include "scene.h"
20
21 #include "util_foreach.h"
22 #include "util_image.h"
23 #include "util_path.h"
24 #include "util_progress.h"
25 #include "util_texture.h"
26
27 #ifdef WITH_OSL
28 #include <OSL/oslexec.h>
29 #endif
30
31 CCL_NAMESPACE_BEGIN
32
33 ImageManager::ImageManager(const DeviceInfo& info)
34 {
35         need_update = true;
36         pack_images = false;
37         osl_texture_system = NULL;
38         animation_frame = 0;
39
40         /* Set image limits */
41
42         /* CPU */
43         if(info.type == DEVICE_CPU) {
44                 tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE_IMAGES_CPU;
45                 tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CPU;
46                 tex_image_byte_start = TEX_IMAGE_BYTE_START_CPU;
47         }
48         /* CUDA (Fermi) */
49         else if((info.type == DEVICE_CUDA || info.type == DEVICE_MULTI) && !info.extended_images) {
50                 tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE_IMAGES_CUDA;
51                 tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CUDA;
52                 tex_image_byte_start = TEX_IMAGE_BYTE_START_CUDA;
53         }
54         /* CUDA (Kepler and above) */
55         else if((info.type == DEVICE_CUDA || info.type == DEVICE_MULTI) && info.extended_images) {
56                 tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE_IMAGES_CUDA_KEPLER;
57                 tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER;
58                 tex_image_byte_start = TEX_IMAGE_BYTE_START_CUDA_KELPER;
59         }
60         /* OpenCL */
61         else if(info.pack_images) {
62                 tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE_IMAGES_OPENCL;
63                 tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_OPENCL;
64                 tex_image_byte_start = TEX_IMAGE_BYTE_START_OPENCL;
65         }
66         /* Should never happen */
67         else {
68                 tex_num_images[IMAGE_DATA_TYPE_BYTE4] = 0;
69                 tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = 0;
70                 tex_image_byte_start = 0;
71                 assert(0);
72         }
73 }
74
75 ImageManager::~ImageManager()
76 {
77         for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
78                 for(size_t slot = 0; slot < images[type].size(); slot++)
79                         assert(!images[type][slot]);
80         }
81 }
82
83 void ImageManager::set_pack_images(bool pack_images_)
84 {
85         pack_images = pack_images_;
86 }
87
88 void ImageManager::set_osl_texture_system(void *texture_system)
89 {
90         osl_texture_system = texture_system;
91 }
92
93 bool ImageManager::set_animation_frame_update(int frame)
94 {
95         if(frame != animation_frame) {
96                 animation_frame = frame;
97
98                 for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
99                         for(size_t slot = 0; slot < images[type].size(); slot++) {
100                                 if(images[type][slot] && images[type][slot]->animated)
101                                         return true;
102                         }
103                 }
104         }
105
106         return false;
107 }
108
109 bool ImageManager::is_float_image(const string& filename, void *builtin_data, bool& is_linear)
110 {
111         bool is_float = false;
112         is_linear = false;
113
114         if(builtin_data) {
115                 if(builtin_image_info_cb) {
116                         int width, height, depth, channels;
117                         builtin_image_info_cb(filename, builtin_data, is_float, width, height, depth, channels);
118                 }
119
120                 if(is_float)
121                         is_linear = true;
122
123                 return is_float;
124         }
125
126         ImageInput *in = ImageInput::create(filename);
127
128         if(in) {
129                 ImageSpec spec;
130
131                 if(in->open(filename, spec)) {
132                         /* check the main format, and channel formats;
133                          * if any take up more than one byte, we'll need a float texture slot */
134                         if(spec.format.basesize() > 1) {
135                                 is_float = true;
136                                 is_linear = true;
137                         }
138
139                         for(size_t channel = 0; channel < spec.channelformats.size(); channel++) {
140                                 if(spec.channelformats[channel].basesize() > 1) {
141                                         is_float = true;
142                                         is_linear = true;
143                                 }
144                         }
145
146                         /* basic color space detection, not great but better than nothing
147                          * before we do OpenColorIO integration */
148                         if(is_float) {
149                                 string colorspace = spec.get_string_attribute("oiio:ColorSpace");
150
151                                 is_linear = !(colorspace == "sRGB" ||
152                                               colorspace == "GammaCorrected" ||
153                                               (colorspace == "" &&
154                                                   (strcmp(in->format_name(), "png") == 0 ||
155                                                    strcmp(in->format_name(), "tiff") == 0 ||
156                                                    strcmp(in->format_name(), "dpx") == 0 ||
157                                                    strcmp(in->format_name(), "jpeg2000") == 0)));
158                         }
159                         else {
160                                 is_linear = false;
161                         }
162
163                         in->close();
164                 }
165
166                 delete in;
167         }
168
169         return is_float;
170 }
171
172 int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type)
173 {
174         if(type == IMAGE_DATA_TYPE_BYTE4)
175                 return slot + tex_image_byte_start;
176         else
177                 return slot;
178 }
179
180 int ImageManager::flattened_slot_to_type_index(int slot, ImageDataType *type)
181 {
182         if(slot >= tex_image_byte_start) {
183                 *type = IMAGE_DATA_TYPE_BYTE4;
184                 return slot - tex_image_byte_start;
185         }
186         else {
187                 *type = IMAGE_DATA_TYPE_FLOAT4;
188                 return slot;
189         }
190 }
191
192 string ImageManager::name_from_type(int type)
193 {
194         if(type == IMAGE_DATA_TYPE_FLOAT4)
195                 return "float";
196         else
197                 return "byte";
198 }
199
200 static bool image_equals(ImageManager::Image *image,
201                          const string& filename,
202                          void *builtin_data,
203                          InterpolationType interpolation,
204                          ExtensionType extension)
205 {
206         return image->filename == filename &&
207                image->builtin_data == builtin_data &&
208                image->interpolation == interpolation &&
209                image->extension == extension;
210 }
211
212 int ImageManager::add_image(const string& filename,
213                             void *builtin_data,
214                             bool animated,
215                             float frame,
216                             bool& is_float,
217                             bool& is_linear,
218                             InterpolationType interpolation,
219                             ExtensionType extension,
220                             bool use_alpha)
221 {
222         Image *img;
223         size_t slot;
224
225         /* Load image info and find out if we need a float texture. */
226         is_float = (pack_images)? false: is_float_image(filename, builtin_data, is_linear);
227
228         ImageDataType type = is_float? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_BYTE4;
229
230         /* Fnd existing image. */
231         for(slot = 0; slot < images[type].size(); slot++) {
232                 img = images[type][slot];
233                 if(img && image_equals(img,
234                                            filename,
235                                            builtin_data,
236                                            interpolation,
237                                            extension))
238                 {
239                         if(img->frame != frame) {
240                                 img->frame = frame;
241                                 img->need_load = true;
242                         }
243                         if(img->use_alpha != use_alpha) {
244                                 img->use_alpha = use_alpha;
245                                 img->need_load = true;
246                         }
247                         img->users++;
248                         return type_index_to_flattened_slot(slot, type);
249                 }
250         }
251
252         /* Find free slot. */
253         for(slot = 0; slot < images[type].size(); slot++) {
254                 if(!images[type][slot])
255                         break;
256         }
257
258         if(slot == images[type].size()) {
259                 /* Max images limit reached. */
260                 if(images[type].size() == tex_num_images[type]) {
261                         printf("ImageManager::add_image: Reached %s image limit (%d), skipping '%s'\n",
262                                name_from_type(type).c_str(), tex_num_images[type], filename.c_str());
263                         return -1;
264                 }
265
266                 images[type].resize(images[type].size() + 1);
267         }
268
269         /* Add new image. */
270         img = new Image();
271         img->filename = filename;
272         img->builtin_data = builtin_data;
273         img->need_load = true;
274         img->animated = animated;
275         img->frame = frame;
276         img->interpolation = interpolation;
277         img->extension = extension;
278         img->users = 1;
279         img->use_alpha = use_alpha;
280
281         images[type][slot] = img;
282
283         need_update = true;
284
285         return type_index_to_flattened_slot(slot, type);
286 }
287
288 void ImageManager::remove_image(int slot)
289 {
290         ImageDataType type;
291         slot = flattened_slot_to_type_index(slot, &type);
292
293         Image *image = images[type][slot];
294         assert(image && image->users >= 1);
295
296         /* decrement user count */
297         image->users--;
298
299         /* don't remove immediately, rather do it all together later on. one of
300          * the reasons for this is that on shader changes we add and remove nodes
301          * that use them, but we do not want to reload the image all the time. */
302         if(image->users == 0)
303                 need_update = true;
304 }
305
306 void ImageManager::remove_image(const string& filename,
307                                 void *builtin_data,
308                                 InterpolationType interpolation,
309                                 ExtensionType extension)
310 {
311         size_t slot;
312
313         for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
314                 for(slot = 0; slot < images[type].size(); slot++) {
315                         if(images[type][slot] && image_equals(images[type][slot],
316                                                           filename,
317                                                           builtin_data,
318                                                           interpolation,
319                                                           extension))
320                         {
321                                 remove_image(type_index_to_flattened_slot(slot, (ImageDataType)type));
322                                 return;
323                         }
324                 }
325         }
326 }
327
328 /* TODO(sergey): Deduplicate with the iteration above, but make it pretty,
329  * without bunch of arguments passing around making code readability even
330  * more cluttered.
331  */
332 void ImageManager::tag_reload_image(const string& filename,
333                                     void *builtin_data,
334                                     InterpolationType interpolation,
335                                     ExtensionType extension)
336 {
337         for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
338                 for(size_t slot = 0; slot < images[type].size(); slot++) {
339                         if(images[type][slot] && image_equals(images[type][slot],
340                                                           filename,
341                                                           builtin_data,
342                                                           interpolation,
343                                                           extension))
344                         {
345                                 images[type][slot]->need_load = true;
346                                 break;
347                         }
348                 }
349         }
350 }
351
352 bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
353 {
354         if(img->filename == "")
355                 return false;
356
357         ImageInput *in = NULL;
358         int width, height, depth, components;
359
360         if(!img->builtin_data) {
361                 /* load image from file through OIIO */
362                 in = ImageInput::create(img->filename);
363
364                 if(!in)
365                         return false;
366
367                 ImageSpec spec = ImageSpec();
368                 ImageSpec config = ImageSpec();
369
370                 if(img->use_alpha == false)
371                         config.attribute("oiio:UnassociatedAlpha", 1);
372
373                 if(!in->open(img->filename, spec, config)) {
374                         delete in;
375                         return false;
376                 }
377
378                 width = spec.width;
379                 height = spec.height;
380                 depth = spec.depth;
381                 components = spec.nchannels;
382         }
383         else {
384                 /* load image using builtin images callbacks */
385                 if(!builtin_image_info_cb || !builtin_image_pixels_cb)
386                         return false;
387
388                 bool is_float;
389                 builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components);
390         }
391
392         /* we only handle certain number of components */
393         if(!(components >= 1 && components <= 4)) {
394                 if(in) {
395                         in->close();
396                         delete in;
397                 }
398
399                 return false;
400         }
401
402         /* read RGBA pixels */
403         uchar *pixels = (uchar*)tex_img.resize(width, height, depth);
404         if(pixels == NULL) {
405                 return false;
406         }
407         bool cmyk = false;
408
409         if(in) {
410                 if(depth <= 1) {
411                         int scanlinesize = width*components*sizeof(uchar);
412
413                         in->read_image(TypeDesc::UINT8,
414                                 (uchar*)pixels + (((size_t)height)-1)*scanlinesize,
415                                 AutoStride,
416                                 -scanlinesize,
417                                 AutoStride);
418                 }
419                 else {
420                         in->read_image(TypeDesc::UINT8, (uchar*)pixels);
421                 }
422
423                 cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;
424
425                 in->close();
426                 delete in;
427         }
428         else {
429                 builtin_image_pixels_cb(img->filename, img->builtin_data, pixels);
430         }
431
432         size_t num_pixels = ((size_t)width) * height * depth;
433         if(cmyk) {
434                 /* CMYK */
435                 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
436                         pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
437                         pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
438                         pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255;
439                         pixels[i*4+3] = 255;
440                 }
441         }
442         else if(components == 2) {
443                 /* grayscale + alpha */
444                 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
445                         pixels[i*4+3] = pixels[i*2+1];
446                         pixels[i*4+2] = pixels[i*2+0];
447                         pixels[i*4+1] = pixels[i*2+0];
448                         pixels[i*4+0] = pixels[i*2+0];
449                 }
450         }
451         else if(components == 3) {
452                 /* RGB */
453                 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
454                         pixels[i*4+3] = 255;
455                         pixels[i*4+2] = pixels[i*3+2];
456                         pixels[i*4+1] = pixels[i*3+1];
457                         pixels[i*4+0] = pixels[i*3+0];
458                 }
459         }
460         else if(components == 1) {
461                 /* grayscale */
462                 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
463                         pixels[i*4+3] = 255;
464                         pixels[i*4+2] = pixels[i];
465                         pixels[i*4+1] = pixels[i];
466                         pixels[i*4+0] = pixels[i];
467                 }
468         }
469
470         if(img->use_alpha == false) {
471                 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
472                         pixels[i*4+3] = 255;
473                 }
474         }
475
476         return true;
477 }
478
479 bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_img)
480 {
481         if(img->filename == "")
482                 return false;
483
484         ImageInput *in = NULL;
485         int width, height, depth, components;
486
487         if(!img->builtin_data) {
488                 /* load image from file through OIIO */
489                 in = ImageInput::create(img->filename);
490
491                 if(!in)
492                         return false;
493
494                 ImageSpec spec = ImageSpec();
495                 ImageSpec config = ImageSpec();
496
497                 if(img->use_alpha == false)
498                         config.attribute("oiio:UnassociatedAlpha",1);
499
500                 if(!in->open(img->filename, spec, config)) {
501                         delete in;
502                         return false;
503                 }
504
505                 /* we only handle certain number of components */
506                 width = spec.width;
507                 height = spec.height;
508                 depth = spec.depth;
509                 components = spec.nchannels;
510         }
511         else {
512                 /* load image using builtin images callbacks */
513                 if(!builtin_image_info_cb || !builtin_image_float_pixels_cb)
514                         return false;
515
516                 bool is_float;
517                 builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components);
518         }
519
520         if(components < 1 || width == 0 || height == 0) {
521                 if(in) {
522                         in->close();
523                         delete in;
524                 }
525                 return false;
526         }
527
528         /* read RGBA pixels */
529         float *pixels = (float*)tex_img.resize(width, height, depth);
530         if(pixels == NULL) {
531                 return false;
532         }
533         bool cmyk = false;
534
535         if(in) {
536                 float *readpixels = pixels;
537                 vector<float> tmppixels;
538
539                 if(components > 4) {
540                         tmppixels.resize(((size_t)width)*height*components);
541                         readpixels = &tmppixels[0];
542                 }
543
544                 if(depth <= 1) {
545                         int scanlinesize = width*components*sizeof(float);
546
547                         in->read_image(TypeDesc::FLOAT,
548                                 (uchar*)readpixels + (height-1)*scanlinesize,
549                                 AutoStride,
550                                 -scanlinesize,
551                                 AutoStride);
552                 }
553                 else {
554                         in->read_image(TypeDesc::FLOAT, (uchar*)readpixels);
555                 }
556
557                 if(components > 4) {
558                         size_t dimensions = ((size_t)width)*height;
559                         for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) {
560                                 pixels[i*4+3] = tmppixels[i*components+3];
561                                 pixels[i*4+2] = tmppixels[i*components+2];
562                                 pixels[i*4+1] = tmppixels[i*components+1];
563                                 pixels[i*4+0] = tmppixels[i*components+0];
564                         }
565
566                         tmppixels.clear();
567                 }
568
569                 cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;
570
571                 in->close();
572                 delete in;
573         }
574         else {
575                 builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels);
576         }
577
578         size_t num_pixels = ((size_t)width) * height * depth;
579         if(cmyk) {
580                 /* CMYK */
581                 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
582                         pixels[i*4+3] = 255;
583                         pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
584                         pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
585                         pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255;
586                 }
587         }
588         else if(components == 2) {
589                 /* grayscale + alpha */
590                 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
591                         pixels[i*4+3] = pixels[i*2+1];
592                         pixels[i*4+2] = pixels[i*2+0];
593                         pixels[i*4+1] = pixels[i*2+0];
594                         pixels[i*4+0] = pixels[i*2+0];
595                 }
596         }
597         else if(components == 3) {
598                 /* RGB */
599                 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
600                         pixels[i*4+3] = 1.0f;
601                         pixels[i*4+2] = pixels[i*3+2];
602                         pixels[i*4+1] = pixels[i*3+1];
603                         pixels[i*4+0] = pixels[i*3+0];
604                 }
605         }
606         else if(components == 1) {
607                 /* grayscale */
608                 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
609                         pixels[i*4+3] = 1.0f;
610                         pixels[i*4+2] = pixels[i];
611                         pixels[i*4+1] = pixels[i];
612                         pixels[i*4+0] = pixels[i];
613                 }
614         }
615
616         if(img->use_alpha == false) {
617                 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
618                         pixels[i*4+3] = 1.0f;
619                 }
620         }
621
622         return true;
623 }
624
625 void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot, Progress *progress)
626 {
627         if(progress->get_cancel())
628                 return;
629         
630         Image *img = images[type][slot];
631
632         if(osl_texture_system && !img->builtin_data)
633                 return;
634
635         string filename = path_filename(images[type][slot]->filename);
636         progress->set_status("Updating Images", "Loading " + filename);
637
638         if(type == IMAGE_DATA_TYPE_FLOAT4) {
639                 device_vector<float4>& tex_img = dscene->tex_float4_image[slot];
640
641                 if(tex_img.device_pointer) {
642                         thread_scoped_lock device_lock(device_mutex);
643                         device->tex_free(tex_img);
644                 }
645
646                 if(!file_load_float_image(img, tex_img)) {
647                         /* on failure to load, we set a 1x1 pixels pink image */
648                         float *pixels = (float*)tex_img.resize(1, 1);
649
650                         pixels[0] = TEX_IMAGE_MISSING_R;
651                         pixels[1] = TEX_IMAGE_MISSING_G;
652                         pixels[2] = TEX_IMAGE_MISSING_B;
653                         pixels[3] = TEX_IMAGE_MISSING_A;
654                 }
655
656                 string name;
657
658                 if(slot >= 100) name = string_printf("__tex_image_float4_%d", slot);
659                 else if(slot >= 10) name = string_printf("__tex_image_float4_0%d", slot);
660                 else name = string_printf("__tex_image_float4_00%d", slot);
661
662                 if(!pack_images) {
663                         thread_scoped_lock device_lock(device_mutex);
664                         device->tex_alloc(name.c_str(),
665                                           tex_img,
666                                           img->interpolation,
667                                           img->extension);
668                 }
669         }
670         else {
671                 device_vector<uchar4>& tex_img = dscene->tex_byte_image[slot];
672
673                 if(tex_img.device_pointer) {
674                         thread_scoped_lock device_lock(device_mutex);
675                         device->tex_free(tex_img);
676                 }
677
678                 if(!file_load_image(img, tex_img)) {
679                         /* on failure to load, we set a 1x1 pixels pink image */
680                         uchar *pixels = (uchar*)tex_img.resize(1, 1);
681
682                         pixels[0] = (TEX_IMAGE_MISSING_R * 255);
683                         pixels[1] = (TEX_IMAGE_MISSING_G * 255);
684                         pixels[2] = (TEX_IMAGE_MISSING_B * 255);
685                         pixels[3] = (TEX_IMAGE_MISSING_A * 255);
686                 }
687
688                 string name;
689
690                 if(slot >= 100) name = string_printf("__tex_image_byte_%d", slot);
691                 else if(slot >= 10) name = string_printf("__tex_image_byte_0%d", slot);
692                 else name = string_printf("__tex_image_byte_00%d", slot);
693
694                 if(!pack_images) {
695                         thread_scoped_lock device_lock(device_mutex);
696                         device->tex_alloc(name.c_str(),
697                                           tex_img,
698                                           img->interpolation,
699                                           img->extension);
700                 }
701         }
702
703         img->need_load = false;
704 }
705
706 void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot)
707 {
708         Image *img = images[type][slot];
709
710         if(img) {
711                 if(osl_texture_system && !img->builtin_data) {
712 #ifdef WITH_OSL
713                         ustring filename(images[type][slot]->filename);
714                         ((OSL::TextureSystem*)osl_texture_system)->invalidate(filename);
715 #endif
716                 }
717                 else if(type == IMAGE_DATA_TYPE_FLOAT4) {
718                         device_vector<float4>& tex_img = dscene->tex_float4_image[slot];
719
720                         if(tex_img.device_pointer) {
721                                 thread_scoped_lock device_lock(device_mutex);
722                                 device->tex_free(tex_img);
723                         }
724
725                         tex_img.clear();
726
727                         delete images[type][slot];
728                         images[type][slot] = NULL;
729                 }
730                 else {
731                         device_vector<uchar4>& tex_img = dscene->tex_byte_image[slot];
732
733                         if(tex_img.device_pointer) {
734                                 thread_scoped_lock device_lock(device_mutex);
735                                 device->tex_free(tex_img);
736                         }
737
738                         tex_img.clear();
739
740                         delete images[type][slot];
741                         images[type][slot] = NULL;
742                 }
743         }
744 }
745
746 void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& progress)
747 {
748         if(!need_update)
749                 return;
750
751         TaskPool pool;
752
753         for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
754                 for(size_t slot = 0; slot < images[type].size(); slot++) {
755                         if(!images[type][slot])
756                                 continue;
757
758                         if(images[type][slot]->users == 0) {
759                                 device_free_image(device, dscene, (ImageDataType)type, slot);
760                         }
761                         else if(images[type][slot]->need_load) {
762                                 if(!osl_texture_system || images[type][slot]->builtin_data)
763                                         pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, (ImageDataType)type, slot, &progress));
764                         }
765                 }
766         }
767
768         pool.wait_work();
769
770         if(pack_images)
771                 device_pack_images(device, dscene, progress);
772
773         need_update = false;
774 }
775
776 void ImageManager::device_update_slot(Device *device,
777                                       DeviceScene *dscene,
778                                       int slot,
779                                       Progress *progress)
780 {
781         ImageDataType type;
782         slot = flattened_slot_to_type_index(slot, &type);
783
784         Image *image = images[type][slot];
785         assert(image != NULL);
786
787         if(image->users == 0) {
788                 device_free_image(device, dscene, type, slot);
789         }
790         else if(image->need_load) {
791                 if(!osl_texture_system || image->builtin_data)
792                         device_load_image(device,
793                                           dscene,
794                                           type,
795                                           slot,
796                                           progress);
797         }
798 }
799
800 void ImageManager::device_pack_images(Device *device,
801                                       DeviceScene *dscene,
802                                       Progress& /*progess*/)
803 {
804         /* for OpenCL, we pack all image textures inside a single big texture, and
805          * will do our own interpolation in the kernel */
806         size_t size = 0;
807
808         /* Only byte textures are supported atm */
809         ImageDataType type = IMAGE_DATA_TYPE_BYTE4;
810
811         for(size_t slot = 0; slot < images[type].size(); slot++) {
812                 if(!images[type][slot])
813                         continue;
814
815                 device_vector<uchar4>& tex_img = dscene->tex_byte_image[slot];
816                 size += tex_img.size();
817         }
818
819         uint4 *info = dscene->tex_image_packed_info.resize(images[type].size());
820         uchar4 *pixels = dscene->tex_image_packed.resize(size);
821
822         size_t offset = 0;
823
824         for(size_t slot = 0; slot < images[type].size(); slot++) {
825                 if(!images[type][slot])
826                         continue;
827
828                 device_vector<uchar4>& tex_img = dscene->tex_byte_image[slot];
829
830                 /* todo: support 3D textures, only CPU for now */
831
832                 /* The image options are packed
833                    bit 0 -> periodic
834                    bit 1 + 2 -> interpolation type */
835                 uint8_t interpolation = (images[type][slot]->interpolation << 1) + 1;
836                 info[slot] = make_uint4(tex_img.data_width, tex_img.data_height, offset, interpolation);
837
838                 memcpy(pixels+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
839                 offset += tex_img.size();
840         }
841
842         if(dscene->tex_image_packed.size()) {
843                 if(dscene->tex_image_packed.device_pointer) {
844                         thread_scoped_lock device_lock(device_mutex);
845                         device->tex_free(dscene->tex_image_packed);
846                 }
847                 device->tex_alloc("__tex_image_packed", dscene->tex_image_packed);
848         }
849         if(dscene->tex_image_packed_info.size()) {
850                 if(dscene->tex_image_packed_info.device_pointer) {
851                         thread_scoped_lock device_lock(device_mutex);
852                         device->tex_free(dscene->tex_image_packed_info);
853                 }
854                 device->tex_alloc("__tex_image_packed_info", dscene->tex_image_packed_info);
855         }
856 }
857
858 void ImageManager::device_free_builtin(Device *device, DeviceScene *dscene)
859 {
860         for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
861                 for(size_t slot = 0; slot < images[type].size(); slot++) {
862                         if(images[type][slot] && images[type][slot]->builtin_data)
863                                 device_free_image(device, dscene, (ImageDataType)type, slot);
864                 }
865         }
866 }
867
868 void ImageManager::device_free(Device *device, DeviceScene *dscene)
869 {
870         for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
871                 for(size_t slot = 0; slot < images[type].size(); slot++) {
872                         device_free_image(device, dscene, (ImageDataType)type, slot);
873                 }
874                 images[type].clear();
875         }
876
877         device->tex_free(dscene->tex_image_packed);
878         device->tex_free(dscene->tex_image_packed_info);
879
880         dscene->tex_image_packed.clear();
881         dscene->tex_image_packed_info.clear();
882 }
883
884 CCL_NAMESPACE_END
885