2 * Copyright 2011-2013 Blender Foundation
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include "util_foreach.h"
22 #include "util_path.h"
23 #include "util_progress.h"
24 #include "util_texture.h"
27 #include <OSL/oslexec.h>
32 ImageManager::ImageManager(const DeviceInfo& info)
36 osl_texture_system = NULL;
39 /* In case of multiple devices used we need to know type of an actual
42 * NOTE: We assume that all the devices are same type, otherwise we'll
43 * be screwed on so many levels..
45 DeviceType device_type = info.type;
46 if (device_type == DEVICE_MULTI) {
47 device_type = info.multi_devices[0].type;
50 /* Set image limits */
51 #define SET_TEX_IMAGES_LIMITS(ARCH) \
53 tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_ ## ARCH; \
54 tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_ ## ARCH; \
55 tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_ ## ARCH; \
56 tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_ ## ARCH; \
57 tex_num_images[IMAGE_DATA_TYPE_HALF4] = TEX_NUM_HALF4_ ## ARCH; \
58 tex_num_images[IMAGE_DATA_TYPE_HALF] = TEX_NUM_HALF_ ## ARCH; \
59 tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_START_FLOAT4_ ## ARCH; \
60 tex_start_images[IMAGE_DATA_TYPE_BYTE4] = TEX_START_BYTE4_ ## ARCH; \
61 tex_start_images[IMAGE_DATA_TYPE_FLOAT] = TEX_START_FLOAT_ ## ARCH; \
62 tex_start_images[IMAGE_DATA_TYPE_BYTE] = TEX_START_BYTE_ ## ARCH; \
63 tex_start_images[IMAGE_DATA_TYPE_HALF4] = TEX_START_HALF4_ ## ARCH; \
64 tex_start_images[IMAGE_DATA_TYPE_HALF] = TEX_START_HALF_ ## ARCH; \
67 if(device_type == DEVICE_CPU) {
68 SET_TEX_IMAGES_LIMITS(CPU);
70 else if(device_type == DEVICE_CUDA) {
71 if(info.has_bindless_textures) {
72 SET_TEX_IMAGES_LIMITS(CUDA_KEPLER);
75 SET_TEX_IMAGES_LIMITS(CUDA);
78 else if(device_type == DEVICE_OPENCL) {
79 SET_TEX_IMAGES_LIMITS(OPENCL);
82 /* Should not happen. */
83 tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = 0;
84 tex_num_images[IMAGE_DATA_TYPE_BYTE4] = 0;
85 tex_num_images[IMAGE_DATA_TYPE_FLOAT] = 0;
86 tex_num_images[IMAGE_DATA_TYPE_BYTE] = 0;
87 tex_num_images[IMAGE_DATA_TYPE_HALF4] = 0;
88 tex_num_images[IMAGE_DATA_TYPE_HALF] = 0;
89 tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = 0;
90 tex_start_images[IMAGE_DATA_TYPE_BYTE4] = 0;
91 tex_start_images[IMAGE_DATA_TYPE_FLOAT] = 0;
92 tex_start_images[IMAGE_DATA_TYPE_BYTE] = 0;
93 tex_start_images[IMAGE_DATA_TYPE_HALF4] = 0;
94 tex_start_images[IMAGE_DATA_TYPE_HALF] = 0;
98 #undef SET_TEX_IMAGES_LIMITS
101 ImageManager::~ImageManager()
103 for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
104 for(size_t slot = 0; slot < images[type].size(); slot++)
105 assert(!images[type][slot]);
109 void ImageManager::set_pack_images(bool pack_images_)
111 pack_images = pack_images_;
114 void ImageManager::set_osl_texture_system(void *texture_system)
116 osl_texture_system = texture_system;
119 bool ImageManager::set_animation_frame_update(int frame)
121 if(frame != animation_frame) {
122 animation_frame = frame;
124 for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
125 for(size_t slot = 0; slot < images[type].size(); slot++) {
126 if(images[type][slot] && images[type][slot]->animated)
135 ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filename,
139 bool is_float = false, is_half = false;
144 if(builtin_image_info_cb) {
145 int width, height, depth;
146 builtin_image_info_cb(filename, builtin_data, is_float, width, height, depth, channels);
151 return (channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
154 return (channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
158 ImageInput *in = ImageInput::create(filename);
163 if(in->open(filename, spec)) {
164 /* check the main format, and channel formats;
165 * if any take up more than one byte, we'll need a float texture slot */
166 if(spec.format.basesize() > 1) {
171 for(size_t channel = 0; channel < spec.channelformats.size(); channel++) {
172 if(spec.channelformats[channel].basesize() > 1) {
178 /* check if it's half float */
179 if(spec.format == TypeDesc::HALF)
182 channels = spec.nchannels;
184 /* basic color space detection, not great but better than nothing
185 * before we do OpenColorIO integration */
187 string colorspace = spec.get_string_attribute("oiio:ColorSpace");
189 is_linear = !(colorspace == "sRGB" ||
190 colorspace == "GammaCorrected" ||
192 (strcmp(in->format_name(), "png") == 0 ||
193 strcmp(in->format_name(), "tiff") == 0 ||
194 strcmp(in->format_name(), "dpx") == 0 ||
195 strcmp(in->format_name(), "jpeg2000") == 0)));
208 return (channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF;
211 return (channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
214 return (channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
218 /* We use a consecutive slot counting scheme on the devices, in order
219 * float4, byte4, float, byte.
220 * These functions convert the slot ids from ImageManager "images" ones
221 * to device ones and vice versa. */
222 int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type)
224 return slot + tex_start_images[type];
227 int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *type)
229 for(int i = IMAGE_DATA_NUM_TYPES - 1; i >= 0; i--) {
230 if(flat_slot >= tex_start_images[i]) {
231 *type = (ImageDataType)i;
232 return flat_slot - tex_start_images[i];
236 /* Should not happen. */
240 string ImageManager::name_from_type(int type)
242 if(type == IMAGE_DATA_TYPE_FLOAT4)
244 else if(type == IMAGE_DATA_TYPE_FLOAT)
246 else if(type == IMAGE_DATA_TYPE_BYTE)
248 else if(type == IMAGE_DATA_TYPE_HALF4)
250 else if(type == IMAGE_DATA_TYPE_HALF)
256 static bool image_equals(ImageManager::Image *image,
257 const string& filename,
259 InterpolationType interpolation,
260 ExtensionType extension)
262 return image->filename == filename &&
263 image->builtin_data == builtin_data &&
264 image->interpolation == interpolation &&
265 image->extension == extension;
268 int ImageManager::add_image(const string& filename,
274 InterpolationType interpolation,
275 ExtensionType extension,
281 ImageDataType type = get_image_metadata(filename, builtin_data, is_linear);
283 /* Do we have a float? */
284 if(type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4)
287 /* No single channel and half textures on CUDA (Fermi) and OpenCL, use available slots */
288 if((type == IMAGE_DATA_TYPE_FLOAT ||
289 type == IMAGE_DATA_TYPE_HALF4 ||
290 type == IMAGE_DATA_TYPE_HALF) &&
291 tex_num_images[type] == 0) {
292 type = IMAGE_DATA_TYPE_FLOAT4;
294 if(type == IMAGE_DATA_TYPE_BYTE && tex_num_images[type] == 0) {
295 type = IMAGE_DATA_TYPE_BYTE4;
298 /* Fnd existing image. */
299 for(slot = 0; slot < images[type].size(); slot++) {
300 img = images[type][slot];
301 if(img && image_equals(img,
307 if(img->frame != frame) {
309 img->need_load = true;
311 if(img->use_alpha != use_alpha) {
312 img->use_alpha = use_alpha;
313 img->need_load = true;
316 return type_index_to_flattened_slot(slot, type);
320 /* Find free slot. */
321 for(slot = 0; slot < images[type].size(); slot++) {
322 if(!images[type][slot])
326 if(slot == images[type].size()) {
327 /* Max images limit reached. */
328 if(images[type].size() == tex_num_images[type]) {
329 printf("ImageManager::add_image: Reached %s image limit (%d), skipping '%s'\n",
330 name_from_type(type).c_str(), tex_num_images[type], filename.c_str());
334 images[type].resize(images[type].size() + 1);
339 img->filename = filename;
340 img->builtin_data = builtin_data;
341 img->need_load = true;
342 img->animated = animated;
344 img->interpolation = interpolation;
345 img->extension = extension;
347 img->use_alpha = use_alpha;
349 images[type][slot] = img;
353 return type_index_to_flattened_slot(slot, type);
356 void ImageManager::remove_image(int flat_slot)
359 int slot = flattened_slot_to_type_index(flat_slot, &type);
361 Image *image = images[type][slot];
362 assert(image && image->users >= 1);
364 /* decrement user count */
367 /* don't remove immediately, rather do it all together later on. one of
368 * the reasons for this is that on shader changes we add and remove nodes
369 * that use them, but we do not want to reload the image all the time. */
370 if(image->users == 0)
374 void ImageManager::remove_image(const string& filename,
376 InterpolationType interpolation,
377 ExtensionType extension)
381 for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
382 for(slot = 0; slot < images[type].size(); slot++) {
383 if(images[type][slot] && image_equals(images[type][slot],
389 remove_image(type_index_to_flattened_slot(slot, (ImageDataType)type));
396 /* TODO(sergey): Deduplicate with the iteration above, but make it pretty,
397 * without bunch of arguments passing around making code readability even
400 void ImageManager::tag_reload_image(const string& filename,
402 InterpolationType interpolation,
403 ExtensionType extension)
405 for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
406 for(size_t slot = 0; slot < images[type].size(); slot++) {
407 if(images[type][slot] && image_equals(images[type][slot],
413 images[type][slot]->need_load = true;
420 bool ImageManager::file_load_image_generic(Image *img, ImageInput **in, int &width, int &height, int &depth, int &components)
422 if(img->filename == "")
425 if(!img->builtin_data) {
426 /* load image from file through OIIO */
427 *in = ImageInput::create(img->filename);
432 ImageSpec spec = ImageSpec();
433 ImageSpec config = ImageSpec();
435 if(img->use_alpha == false)
436 config.attribute("oiio:UnassociatedAlpha", 1);
438 if(!(*in)->open(img->filename, spec, config)) {
445 height = spec.height;
447 components = spec.nchannels;
450 /* load image using builtin images callbacks */
451 if(!builtin_image_info_cb || !builtin_image_pixels_cb)
455 builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components);
458 /* we only handle certain number of components */
459 if(!(components >= 1 && components <= 4)) {
473 bool ImageManager::file_load_byte_image(Image *img, ImageDataType type, device_vector<T>& tex_img)
475 ImageInput *in = NULL;
476 int width, height, depth, components;
478 if(!file_load_image_generic(img, &in, width, height, depth, components))
481 /* read RGBA pixels */
482 uchar *pixels = (uchar*)tex_img.resize(width, height, depth);
490 int scanlinesize = width*components*sizeof(uchar);
492 in->read_image(TypeDesc::UINT8,
493 (uchar*)pixels + (((size_t)height)-1)*scanlinesize,
499 in->read_image(TypeDesc::UINT8, (uchar*)pixels);
502 cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;
508 builtin_image_pixels_cb(img->filename, img->builtin_data, pixels);
511 /* Check if we actually have a byte4 slot, in case components == 1, but device
512 * doesn't support single channel textures. */
513 if(type == IMAGE_DATA_TYPE_BYTE4) {
514 size_t num_pixels = ((size_t)width) * height * depth;
517 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
518 pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
519 pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
520 pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255;
524 else if(components == 2) {
525 /* grayscale + alpha */
526 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
527 pixels[i*4+3] = pixels[i*2+1];
528 pixels[i*4+2] = pixels[i*2+0];
529 pixels[i*4+1] = pixels[i*2+0];
530 pixels[i*4+0] = pixels[i*2+0];
533 else if(components == 3) {
535 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
537 pixels[i*4+2] = pixels[i*3+2];
538 pixels[i*4+1] = pixels[i*3+1];
539 pixels[i*4+0] = pixels[i*3+0];
542 else if(components == 1) {
544 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
546 pixels[i*4+2] = pixels[i];
547 pixels[i*4+1] = pixels[i];
548 pixels[i*4+0] = pixels[i];
552 if(img->use_alpha == false) {
553 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
563 bool ImageManager::file_load_float_image(Image *img, ImageDataType type, device_vector<T>& tex_img)
565 ImageInput *in = NULL;
566 int width, height, depth, components;
568 if(!file_load_image_generic(img, &in, width, height, depth, components))
571 /* read RGBA pixels */
572 float *pixels = (float*)tex_img.resize(width, height, depth);
579 float *readpixels = pixels;
580 vector<float> tmppixels;
583 tmppixels.resize(((size_t)width)*height*components);
584 readpixels = &tmppixels[0];
588 int scanlinesize = width*components*sizeof(float);
590 in->read_image(TypeDesc::FLOAT,
591 (uchar*)readpixels + (height-1)*scanlinesize,
597 in->read_image(TypeDesc::FLOAT, (uchar*)readpixels);
601 size_t dimensions = ((size_t)width)*height;
602 for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) {
603 pixels[i*4+3] = tmppixels[i*components+3];
604 pixels[i*4+2] = tmppixels[i*components+2];
605 pixels[i*4+1] = tmppixels[i*components+1];
606 pixels[i*4+0] = tmppixels[i*components+0];
612 cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;
618 builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels);
621 /* Check if we actually have a float4 slot, in case components == 1, but device
622 * doesn't support single channel textures. */
623 if(type == IMAGE_DATA_TYPE_FLOAT4) {
624 size_t num_pixels = ((size_t)width) * height * depth;
627 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
629 pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
630 pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
631 pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255;
634 else if(components == 2) {
635 /* grayscale + alpha */
636 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
637 pixels[i*4+3] = pixels[i*2+1];
638 pixels[i*4+2] = pixels[i*2+0];
639 pixels[i*4+1] = pixels[i*2+0];
640 pixels[i*4+0] = pixels[i*2+0];
643 else if(components == 3) {
645 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
646 pixels[i*4+3] = 1.0f;
647 pixels[i*4+2] = pixels[i*3+2];
648 pixels[i*4+1] = pixels[i*3+1];
649 pixels[i*4+0] = pixels[i*3+0];
652 else if(components == 1) {
654 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
655 pixels[i*4+3] = 1.0f;
656 pixels[i*4+2] = pixels[i];
657 pixels[i*4+1] = pixels[i];
658 pixels[i*4+0] = pixels[i];
662 if(img->use_alpha == false) {
663 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
664 pixels[i*4+3] = 1.0f;
673 bool ImageManager::file_load_half_image(Image *img, ImageDataType type, device_vector<T>& tex_img)
675 ImageInput *in = NULL;
676 int width, height, depth, components;
678 if(!file_load_image_generic(img, &in, width, height, depth, components))
681 /* read RGBA pixels */
682 half *pixels = (half*)tex_img.resize(width, height, depth);
688 half *readpixels = pixels;
689 vector<half> tmppixels;
692 tmppixels.resize(((size_t)width)*height*components);
693 readpixels = &tmppixels[0];
697 int scanlinesize = width*components*sizeof(half);
699 in->read_image(TypeDesc::HALF,
700 (uchar*)readpixels + (height-1)*scanlinesize,
706 in->read_image(TypeDesc::HALF, (uchar*)readpixels);
710 size_t dimensions = ((size_t)width)*height;
711 for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) {
712 pixels[i*4+3] = tmppixels[i*components+3];
713 pixels[i*4+2] = tmppixels[i*components+2];
714 pixels[i*4+1] = tmppixels[i*components+1];
715 pixels[i*4+0] = tmppixels[i*components+0];
725 /* TODO(dingto): Support half for ImBuf. */
727 builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels);
731 /* Check if we actually have a half4 slot, in case components == 1, but device
732 * doesn't support single channel textures. */
733 if(type == IMAGE_DATA_TYPE_HALF4) {
734 size_t num_pixels = ((size_t)width) * height * depth;
735 if(components == 2) {
736 /* grayscale + alpha */
737 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
738 pixels[i*4+3] = pixels[i*2+1];
739 pixels[i*4+2] = pixels[i*2+0];
740 pixels[i*4+1] = pixels[i*2+0];
741 pixels[i*4+0] = pixels[i*2+0];
744 else if(components == 3) {
746 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
747 pixels[i*4+3] = 1.0f;
748 pixels[i*4+2] = pixels[i*3+2];
749 pixels[i*4+1] = pixels[i*3+1];
750 pixels[i*4+0] = pixels[i*3+0];
753 else if(components == 1) {
755 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
756 pixels[i*4+3] = 1.0f;
757 pixels[i*4+2] = pixels[i];
758 pixels[i*4+1] = pixels[i];
759 pixels[i*4+0] = pixels[i];
763 if(img->use_alpha == false) {
764 for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
765 pixels[i*4+3] = 1.0f;
773 void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot, Progress *progress)
775 if(progress->get_cancel())
778 Image *img = images[type][slot];
780 if(osl_texture_system && !img->builtin_data)
783 string filename = path_filename(images[type][slot]->filename);
784 progress->set_status("Updating Images", "Loading " + filename);
786 /* Slot assignment */
787 int flat_slot = type_index_to_flattened_slot(slot, type);
791 name = string_printf("__tex_image_%s_%d", name_from_type(type).c_str(), flat_slot);
792 else if(flat_slot >= 10)
793 name = string_printf("__tex_image_%s_0%d", name_from_type(type).c_str(), flat_slot);
795 name = string_printf("__tex_image_%s_00%d", name_from_type(type).c_str(), flat_slot);
797 if(type == IMAGE_DATA_TYPE_FLOAT4) {
798 device_vector<float4>& tex_img = dscene->tex_float4_image[slot];
800 if(tex_img.device_pointer) {
801 thread_scoped_lock device_lock(device_mutex);
802 device->tex_free(tex_img);
805 if(!file_load_float_image(img, type, tex_img)) {
806 /* on failure to load, we set a 1x1 pixels pink image */
807 float *pixels = (float*)tex_img.resize(1, 1);
809 pixels[0] = TEX_IMAGE_MISSING_R;
810 pixels[1] = TEX_IMAGE_MISSING_G;
811 pixels[2] = TEX_IMAGE_MISSING_B;
812 pixels[3] = TEX_IMAGE_MISSING_A;
816 thread_scoped_lock device_lock(device_mutex);
817 device->tex_alloc(name.c_str(),
823 else if(type == IMAGE_DATA_TYPE_FLOAT) {
824 device_vector<float>& tex_img = dscene->tex_float_image[slot];
826 if(tex_img.device_pointer) {
827 thread_scoped_lock device_lock(device_mutex);
828 device->tex_free(tex_img);
831 if(!file_load_float_image(img, type, tex_img)) {
832 /* on failure to load, we set a 1x1 pixels pink image */
833 float *pixels = (float*)tex_img.resize(1, 1);
835 pixels[0] = TEX_IMAGE_MISSING_R;
839 thread_scoped_lock device_lock(device_mutex);
840 device->tex_alloc(name.c_str(),
846 else if(type == IMAGE_DATA_TYPE_BYTE4) {
847 device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot];
849 if(tex_img.device_pointer) {
850 thread_scoped_lock device_lock(device_mutex);
851 device->tex_free(tex_img);
854 if(!file_load_byte_image(img, type, tex_img)) {
855 /* on failure to load, we set a 1x1 pixels pink image */
856 uchar *pixels = (uchar*)tex_img.resize(1, 1);
858 pixels[0] = (TEX_IMAGE_MISSING_R * 255);
859 pixels[1] = (TEX_IMAGE_MISSING_G * 255);
860 pixels[2] = (TEX_IMAGE_MISSING_B * 255);
861 pixels[3] = (TEX_IMAGE_MISSING_A * 255);
865 thread_scoped_lock device_lock(device_mutex);
866 device->tex_alloc(name.c_str(),
872 else if(type == IMAGE_DATA_TYPE_BYTE){
873 device_vector<uchar>& tex_img = dscene->tex_byte_image[slot];
875 if(tex_img.device_pointer) {
876 thread_scoped_lock device_lock(device_mutex);
877 device->tex_free(tex_img);
880 if(!file_load_byte_image(img, type, tex_img)) {
881 /* on failure to load, we set a 1x1 pixels pink image */
882 uchar *pixels = (uchar*)tex_img.resize(1, 1);
884 pixels[0] = (TEX_IMAGE_MISSING_R * 255);
888 thread_scoped_lock device_lock(device_mutex);
889 device->tex_alloc(name.c_str(),
895 else if(type == IMAGE_DATA_TYPE_HALF4){
896 device_vector<half4>& tex_img = dscene->tex_half4_image[slot];
898 if(tex_img.device_pointer) {
899 thread_scoped_lock device_lock(device_mutex);
900 device->tex_free(tex_img);
903 if(!file_load_half_image(img, type, tex_img)) {
904 /* on failure to load, we set a 1x1 pixels pink image */
905 half *pixels = (half*)tex_img.resize(1, 1);
907 pixels[0] = TEX_IMAGE_MISSING_R;
908 pixels[1] = TEX_IMAGE_MISSING_G;
909 pixels[2] = TEX_IMAGE_MISSING_B;
910 pixels[3] = TEX_IMAGE_MISSING_A;
914 thread_scoped_lock device_lock(device_mutex);
915 device->tex_alloc(name.c_str(),
921 else if(type == IMAGE_DATA_TYPE_HALF){
922 device_vector<half>& tex_img = dscene->tex_half_image[slot];
924 if(tex_img.device_pointer) {
925 thread_scoped_lock device_lock(device_mutex);
926 device->tex_free(tex_img);
929 if(!file_load_half_image(img, type, tex_img)) {
930 /* on failure to load, we set a 1x1 pixels pink image */
931 half *pixels = (half*)tex_img.resize(1, 1);
933 pixels[0] = TEX_IMAGE_MISSING_R;
937 thread_scoped_lock device_lock(device_mutex);
938 device->tex_alloc(name.c_str(),
945 img->need_load = false;
948 void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot)
950 Image *img = images[type][slot];
953 if(osl_texture_system && !img->builtin_data) {
955 ustring filename(images[type][slot]->filename);
956 ((OSL::TextureSystem*)osl_texture_system)->invalidate(filename);
959 else if(type == IMAGE_DATA_TYPE_FLOAT4) {
960 device_vector<float4>& tex_img = dscene->tex_float4_image[slot];
962 if(tex_img.device_pointer) {
963 thread_scoped_lock device_lock(device_mutex);
964 device->tex_free(tex_img);
969 else if(type == IMAGE_DATA_TYPE_FLOAT) {
970 device_vector<float>& tex_img = dscene->tex_float_image[slot];
972 if(tex_img.device_pointer) {
973 thread_scoped_lock device_lock(device_mutex);
974 device->tex_free(tex_img);
979 else if(type == IMAGE_DATA_TYPE_BYTE4) {
980 device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot];
982 if(tex_img.device_pointer) {
983 thread_scoped_lock device_lock(device_mutex);
984 device->tex_free(tex_img);
989 else if(type == IMAGE_DATA_TYPE_BYTE){
990 device_vector<uchar>& tex_img = dscene->tex_byte_image[slot];
992 if(tex_img.device_pointer) {
993 thread_scoped_lock device_lock(device_mutex);
994 device->tex_free(tex_img);
999 else if(type == IMAGE_DATA_TYPE_HALF4){
1000 device_vector<half4>& tex_img = dscene->tex_half4_image[slot];
1002 if(tex_img.device_pointer) {
1003 thread_scoped_lock device_lock(device_mutex);
1004 device->tex_free(tex_img);
1009 else if(type == IMAGE_DATA_TYPE_HALF){
1010 device_vector<half>& tex_img = dscene->tex_half_image[slot];
1012 if(tex_img.device_pointer) {
1013 thread_scoped_lock device_lock(device_mutex);
1014 device->tex_free(tex_img);
1020 delete images[type][slot];
1021 images[type][slot] = NULL;
1025 void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& progress)
1032 for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
1033 for(size_t slot = 0; slot < images[type].size(); slot++) {
1034 if(!images[type][slot])
1037 if(images[type][slot]->users == 0) {
1038 device_free_image(device, dscene, (ImageDataType)type, slot);
1040 else if(images[type][slot]->need_load) {
1041 if(!osl_texture_system || images[type][slot]->builtin_data)
1042 pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, (ImageDataType)type, slot, &progress));
1050 device_pack_images(device, dscene, progress);
1052 need_update = false;
1055 void ImageManager::device_update_slot(Device *device,
1056 DeviceScene *dscene,
1061 int slot = flattened_slot_to_type_index(flat_slot, &type);
1063 Image *image = images[type][slot];
1064 assert(image != NULL);
1066 if(image->users == 0) {
1067 device_free_image(device, dscene, type, slot);
1069 else if(image->need_load) {
1070 if(!osl_texture_system || image->builtin_data)
1071 device_load_image(device,
1079 uint8_t ImageManager::pack_image_options(ImageDataType type, size_t slot)
1082 /* Image Options are packed into one uint:
1083 * bit 0 -> Interpolation
1084 * bit 1 + 2 + 3-> Extension */
1085 if(images[type][slot]->interpolation == INTERPOLATION_CLOSEST)
1086 options |= (1 << 0);
1088 if(images[type][slot]->extension == EXTENSION_REPEAT)
1089 options |= (1 << 1);
1090 else if(images[type][slot]->extension == EXTENSION_EXTEND)
1091 options |= (1 << 2);
1092 else /* EXTENSION_CLIP */
1093 options |= (1 << 3);
1098 void ImageManager::device_pack_images(Device *device,
1099 DeviceScene *dscene,
1100 Progress& /*progess*/)
1102 /* For OpenCL, we pack all image textures into a single large texture, and
1103 * do our own interpolation in the kernel. */
1104 size_t size = 0, offset = 0;
1107 int info_size = tex_num_images[IMAGE_DATA_TYPE_FLOAT4] + tex_num_images[IMAGE_DATA_TYPE_BYTE4];
1108 uint4 *info = dscene->tex_image_packed_info.resize(info_size);
1111 type = IMAGE_DATA_TYPE_BYTE4;
1113 for(size_t slot = 0; slot < images[type].size(); slot++) {
1114 if(!images[type][slot])
1117 device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot];
1118 size += tex_img.size();
1121 uchar4 *pixels_byte = dscene->tex_image_byte4_packed.resize(size);
1123 for(size_t slot = 0; slot < images[type].size(); slot++) {
1124 if(!images[type][slot])
1127 device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot];
1129 uint8_t options = pack_image_options(type, slot);
1131 info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options);
1133 memcpy(pixels_byte+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
1134 offset += tex_img.size();
1138 type = IMAGE_DATA_TYPE_FLOAT4;
1139 size = 0, offset = 0;
1141 for(size_t slot = 0; slot < images[type].size(); slot++) {
1142 if(!images[type][slot])
1145 device_vector<float4>& tex_img = dscene->tex_float4_image[slot];
1146 size += tex_img.size();
1149 float4 *pixels_float = dscene->tex_image_float4_packed.resize(size);
1151 for(size_t slot = 0; slot < images[type].size(); slot++) {
1152 if(!images[type][slot])
1155 device_vector<float4>& tex_img = dscene->tex_float4_image[slot];
1157 /* todo: support 3D textures, only CPU for now */
1159 uint8_t options = pack_image_options(type, slot);
1160 info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options);
1162 memcpy(pixels_float+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
1163 offset += tex_img.size();
1166 if(dscene->tex_image_byte4_packed.size()) {
1167 if(dscene->tex_image_byte4_packed.device_pointer) {
1168 thread_scoped_lock device_lock(device_mutex);
1169 device->tex_free(dscene->tex_image_byte4_packed);
1171 device->tex_alloc("__tex_image_byte4_packed", dscene->tex_image_byte4_packed);
1173 if(dscene->tex_image_float4_packed.size()) {
1174 if(dscene->tex_image_float4_packed.device_pointer) {
1175 thread_scoped_lock device_lock(device_mutex);
1176 device->tex_free(dscene->tex_image_float4_packed);
1178 device->tex_alloc("__tex_image_float4_packed", dscene->tex_image_float4_packed);
1180 if(dscene->tex_image_packed_info.size()) {
1181 if(dscene->tex_image_packed_info.device_pointer) {
1182 thread_scoped_lock device_lock(device_mutex);
1183 device->tex_free(dscene->tex_image_packed_info);
1185 device->tex_alloc("__tex_image_packed_info", dscene->tex_image_packed_info);
1189 void ImageManager::device_free_builtin(Device *device, DeviceScene *dscene)
1191 for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
1192 for(size_t slot = 0; slot < images[type].size(); slot++) {
1193 if(images[type][slot] && images[type][slot]->builtin_data)
1194 device_free_image(device, dscene, (ImageDataType)type, slot);
1199 void ImageManager::device_free(Device *device, DeviceScene *dscene)
1201 for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
1202 for(size_t slot = 0; slot < images[type].size(); slot++) {
1203 device_free_image(device, dscene, (ImageDataType)type, slot);
1205 images[type].clear();
1208 device->tex_free(dscene->tex_image_byte4_packed);
1209 device->tex_free(dscene->tex_image_float4_packed);
1210 device->tex_free(dscene->tex_image_packed_info);
1212 dscene->tex_image_byte4_packed.clear();
1213 dscene->tex_image_float4_packed.clear();
1214 dscene->tex_image_packed_info.clear();