95090ae835668f6bff2dd7df47a654056d03b551
[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_BYTE] = 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_BYTE] = 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_BYTE] = 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_BYTE] = 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_BYTE] = 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_BYTE)
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_BYTE;
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_BYTE;
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         assert(images[type][slot] != NULL);
294
295         /* decrement user count */
296         images[type][slot]->users--;
297         assert(images[type][slot]->users >= 0);
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(images[type][slot]->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, int slot, Progress *progress)
626 {
627         if(progress->get_cancel())
628                 return;
629         
630         Image *img;
631         ImageDataType type;
632         int slot_offset;
633
634         slot_offset = flattened_slot_to_type_index(slot, &type);
635
636         img = images[type][slot_offset];
637
638         if(osl_texture_system && !img->builtin_data)
639                 return;
640
641         string filename = path_filename(images[type][slot_offset]->filename);
642         progress->set_status("Updating Images", "Loading " + filename);
643
644         if(type == IMAGE_DATA_TYPE_FLOAT4) {
645                 device_vector<float4>& tex_img = dscene->tex_float4_image[slot_offset];
646
647                 if(tex_img.device_pointer) {
648                         thread_scoped_lock device_lock(device_mutex);
649                         device->tex_free(tex_img);
650                 }
651
652                 if(!file_load_float_image(img, tex_img)) {
653                         /* on failure to load, we set a 1x1 pixels pink image */
654                         float *pixels = (float*)tex_img.resize(1, 1);
655
656                         pixels[0] = TEX_IMAGE_MISSING_R;
657                         pixels[1] = TEX_IMAGE_MISSING_G;
658                         pixels[2] = TEX_IMAGE_MISSING_B;
659                         pixels[3] = TEX_IMAGE_MISSING_A;
660                 }
661
662                 string name;
663
664                 if(slot >= 100) name = string_printf("__tex_image_float4_%d", slot);
665                 else if(slot >= 10) name = string_printf("__tex_image_float4_0%d", slot);
666                 else name = string_printf("__tex_image_float4_00%d", slot);
667
668                 if(!pack_images) {
669                         thread_scoped_lock device_lock(device_mutex);
670                         device->tex_alloc(name.c_str(),
671                                           tex_img,
672                                           img->interpolation,
673                                           img->extension);
674                 }
675         }
676         else {
677                 device_vector<uchar4>& tex_img = dscene->tex_byte_image[slot_offset];
678
679                 if(tex_img.device_pointer) {
680                         thread_scoped_lock device_lock(device_mutex);
681                         device->tex_free(tex_img);
682                 }
683
684                 if(!file_load_image(img, tex_img)) {
685                         /* on failure to load, we set a 1x1 pixels pink image */
686                         uchar *pixels = (uchar*)tex_img.resize(1, 1);
687
688                         pixels[0] = (TEX_IMAGE_MISSING_R * 255);
689                         pixels[1] = (TEX_IMAGE_MISSING_G * 255);
690                         pixels[2] = (TEX_IMAGE_MISSING_B * 255);
691                         pixels[3] = (TEX_IMAGE_MISSING_A * 255);
692                 }
693
694                 string name;
695
696                 if(slot >= 100) name = string_printf("__tex_image_byte_%d", slot);
697                 else if(slot >= 10) name = string_printf("__tex_image_byte_0%d", slot);
698                 else name = string_printf("__tex_image_byte_00%d", slot);
699
700                 if(!pack_images) {
701                         thread_scoped_lock device_lock(device_mutex);
702                         device->tex_alloc(name.c_str(),
703                                           tex_img,
704                                           img->interpolation,
705                                           img->extension);
706                 }
707         }
708
709         img->need_load = false;
710 }
711
712 void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int slot)
713 {
714         Image *img;
715         ImageDataType type;
716
717         int slot_offset = flattened_slot_to_type_index(slot, &type);
718
719         img = images[type][slot_offset];
720
721         if(img) {
722                 if(osl_texture_system && !img->builtin_data) {
723 #ifdef WITH_OSL
724                         ustring filename(images[type][slot]->filename);
725                         ((OSL::TextureSystem*)osl_texture_system)->invalidate(filename);
726 #endif
727                 }
728                 else if(type == IMAGE_DATA_TYPE_FLOAT4) {
729                         device_vector<float4>& tex_img = dscene->tex_float4_image[slot_offset];
730
731                         if(tex_img.device_pointer) {
732                                 thread_scoped_lock device_lock(device_mutex);
733                                 device->tex_free(tex_img);
734                         }
735
736                         tex_img.clear();
737
738                         delete images[type][slot_offset];
739                         images[type][slot_offset] = NULL;
740                 }
741                 else {
742                         device_vector<uchar4>& tex_img = dscene->tex_byte_image[slot_offset];
743
744                         if(tex_img.device_pointer) {
745                                 thread_scoped_lock device_lock(device_mutex);
746                                 device->tex_free(tex_img);
747                         }
748
749                         tex_img.clear();
750
751                         delete images[type][slot_offset];
752                         images[type][slot_offset] = NULL;
753                 }
754         }
755 }
756
757 void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& progress)
758 {
759         if(!need_update)
760                 return;
761
762         TaskPool pool;
763
764         for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
765                 for(size_t slot = 0; slot < images[type].size(); slot++) {
766                         if(!images[type][slot])
767                                 continue;
768
769                         if(images[type][slot]->users == 0) {
770                                 device_free_image(device, dscene, type_index_to_flattened_slot(slot, (ImageDataType)type));
771                         }
772                         else if(images[type][slot]->need_load) {
773                                 if(!osl_texture_system || images[type][slot]->builtin_data)
774                                         pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, type_index_to_flattened_slot(slot, (ImageDataType)type), &progress));
775                         }
776                 }
777         }
778
779         pool.wait_work();
780
781         if(pack_images)
782                 device_pack_images(device, dscene, progress);
783
784         need_update = false;
785 }
786
787 void ImageManager::device_update_slot(Device *device,
788                                       DeviceScene *dscene,
789                                       int slot,
790                                       Progress *progress)
791 {
792         Image *image;
793         ImageDataType type;
794
795         slot = flattened_slot_to_type_index(slot, &type);
796
797         assert(images[type][slot] != NULL);
798         image = images[type][slot];
799
800         if(image->users == 0) {
801                 device_free_image(device, dscene, slot);
802         }
803         else if(image->need_load) {
804                 if(!osl_texture_system || image->builtin_data)
805                         device_load_image(device,
806                                           dscene,
807                                           slot,
808                                           progress);
809         }
810 }
811
812 void ImageManager::device_pack_images(Device *device,
813                                       DeviceScene *dscene,
814                                       Progress& /*progess*/)
815 {
816         /* for OpenCL, we pack all image textures inside a single big texture, and
817          * will do our own interpolation in the kernel */
818         size_t size = 0;
819
820         /* Only byte textures are supported atm */
821         ImageDataType type = IMAGE_DATA_TYPE_BYTE;
822
823         for(size_t slot = 0; slot < images[type].size(); slot++) {
824                 if(!images[type][slot])
825                         continue;
826
827                 device_vector<uchar4>& tex_img = dscene->tex_byte_image[slot];
828                 size += tex_img.size();
829         }
830
831         uint4 *info = dscene->tex_image_packed_info.resize(images[type].size());
832         uchar4 *pixels = dscene->tex_image_packed.resize(size);
833
834         size_t offset = 0;
835
836         for(size_t slot = 0; slot < images[type].size(); slot++) {
837                 if(!images[type][slot])
838                         continue;
839
840                 device_vector<uchar4>& tex_img = dscene->tex_byte_image[slot];
841
842                 /* todo: support 3D textures, only CPU for now */
843
844                 /* The image options are packed
845                    bit 0 -> periodic
846                    bit 1 + 2 -> interpolation type */
847                 uint8_t interpolation = (images[type][slot]->interpolation << 1) + 1;
848                 info[slot] = make_uint4(tex_img.data_width, tex_img.data_height, offset, interpolation);
849
850                 memcpy(pixels+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
851                 offset += tex_img.size();
852         }
853
854         if(dscene->tex_image_packed.size()) {
855                 if(dscene->tex_image_packed.device_pointer) {
856                         thread_scoped_lock device_lock(device_mutex);
857                         device->tex_free(dscene->tex_image_packed);
858                 }
859                 device->tex_alloc("__tex_image_packed", dscene->tex_image_packed);
860         }
861         if(dscene->tex_image_packed_info.size()) {
862                 if(dscene->tex_image_packed_info.device_pointer) {
863                         thread_scoped_lock device_lock(device_mutex);
864                         device->tex_free(dscene->tex_image_packed_info);
865                 }
866                 device->tex_alloc("__tex_image_packed_info", dscene->tex_image_packed_info);
867         }
868 }
869
870 void ImageManager::device_free_builtin(Device *device, DeviceScene *dscene)
871 {
872         for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
873                 for(size_t slot = 0; slot < images[type].size(); slot++) {
874                         if(images[type][slot] && images[type][slot]->builtin_data)
875                                 device_free_image(device, dscene, type_index_to_flattened_slot(slot, (ImageDataType)type));
876                 }
877         }
878 }
879
880 void ImageManager::device_free(Device *device, DeviceScene *dscene)
881 {
882         for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
883                 for(size_t slot = 0; slot < images[type].size(); slot++) {
884                         device_free_image(device, dscene, type_index_to_flattened_slot(slot, (ImageDataType)type));
885                 }
886                 images[type].clear();
887         }
888
889         device->tex_free(dscene->tex_image_packed);
890         device->tex_free(dscene->tex_image_packed_info);
891
892         dscene->tex_image_packed.clear();
893         dscene->tex_image_packed_info.clear();
894 }
895
896 CCL_NAMESPACE_END
897