45
51
assert(!float_images[slot]);
54
void ImageManager::set_pack_images(bool pack_images_)
56
pack_images = pack_images_;
48
59
void ImageManager::set_osl_texture_system(void *texture_system)
50
61
osl_texture_system = texture_system;
53
static bool is_float_image(const string& filename)
64
void ImageManager::set_extended_image_limits(void)
66
tex_num_images = TEX_EXTENDED_NUM_IMAGES;
67
tex_num_float_images = TEX_EXTENDED_NUM_FLOAT_IMAGES;
68
tex_image_byte_start = TEX_EXTENDED_IMAGE_BYTE_START;
71
bool ImageManager::set_animation_frame_update(int frame)
73
if(frame != animation_frame) {
74
animation_frame = frame;
76
for(size_t slot = 0; slot < images.size(); slot++)
77
if(images[slot] && images[slot]->animated)
80
for(size_t slot = 0; slot < float_images.size(); slot++)
81
if(float_images[slot] && float_images[slot]->animated)
88
bool ImageManager::is_float_image(const string& filename, void *builtin_data, bool& is_linear)
90
bool is_float = false;
94
if(builtin_image_info_cb) {
95
int width, height, channels;
96
builtin_image_info_cb(filename, builtin_data, is_float, width, height, channels);
55
105
ImageInput *in = ImageInput::create(filename);
56
bool is_float = false;
61
110
if(in->open(filename, spec)) {
62
111
/* check the main format, and channel formats;
63
if any are non-integer, we'll need a float texture slot */
64
if(spec.format == TypeDesc::HALF ||
65
spec.format == TypeDesc::FLOAT ||
66
spec.format == TypeDesc::DOUBLE) {
112
* if any take up more than one byte, we'll need a float texture slot */
113
if(spec.format.basesize() > 1) {
70
118
for(size_t channel = 0; channel < spec.channelformats.size(); channel++) {
71
if(spec.channelformats[channel] == TypeDesc::HALF ||
72
spec.channelformats[channel] == TypeDesc::FLOAT ||
73
spec.channelformats[channel] == TypeDesc::DOUBLE) {
119
if(spec.channelformats[channel].basesize() > 1) {
125
/* basic color space detection, not great but better than nothing
126
* before we do OpenColorIO integration */
128
string colorspace = spec.get_string_attribute("oiio:ColorSpace");
130
is_linear = !(colorspace == "sRGB" ||
131
colorspace == "GammaCorrected" ||
132
strcmp(in->format_name(), "png") == 0);
87
int ImageManager::add_image(const string& filename, bool& is_float)
146
int ImageManager::add_image(const string& filename, void *builtin_data, bool animated, bool& is_float, bool& is_linear)
92
151
/* load image info and find out if we need a float texture */
93
is_float = is_float_image(filename);
152
is_float = (pack_images)? false: is_float_image(filename, builtin_data, is_linear);
96
155
/* find existing image */
97
156
for(slot = 0; slot < float_images.size(); slot++) {
98
157
if(float_images[slot] && float_images[slot]->filename == filename) {
99
158
float_images[slot]->users++;
100
return slot+TEX_IMAGE_FLOAT_START;
150
215
/* add new image */
151
216
img = new Image();
152
217
img->filename = filename;
218
img->builtin_data = builtin_data;
153
219
img->need_load = true;
220
img->animated = animated;
156
223
images[slot] = img;
225
slot += tex_image_byte_start;
158
227
need_update = true;
163
void ImageManager::remove_image(const string& filename)
232
void ImageManager::remove_image(const string& filename, void *builtin_data)
167
236
for(slot = 0; slot < images.size(); slot++) {
168
if(images[slot] && images[slot]->filename == filename) {
237
if(images[slot] && images[slot]->filename == filename && images[slot]->builtin_data == builtin_data) {
169
238
/* decrement user count */
170
239
images[slot]->users--;
171
240
assert(images[slot]->users >= 0);
173
242
/* don't remove immediately, rather do it all together later on. one of
174
the reasons for this is that on shader changes we add and remove nodes
175
that use them, but we do not want to reload the image all the time. */
243
* the reasons for this is that on shader changes we add and remove nodes
244
* that use them, but we do not want to reload the image all the time. */
176
245
if(images[slot]->users == 0)
177
246
need_update = true;
183
252
if(slot == images.size()) {
184
253
/* see if it's in a float texture slot */
185
254
for(slot = 0; slot < float_images.size(); slot++) {
186
if(float_images[slot] && float_images[slot]->filename == filename) {
255
if(float_images[slot] && float_images[slot]->filename == filename && float_images[slot]->builtin_data == builtin_data) {
187
256
/* decrement user count */
188
257
float_images[slot]->users--;
189
258
assert(float_images[slot]->users >= 0);
191
260
/* don't remove immediately, rather do it all together later on. one of
192
the reasons for this is that on shader changes we add and remove nodes
193
that use them, but we do not want to reload the image all the time. */
261
* the reasons for this is that on shader changes we add and remove nodes
262
* that use them, but we do not want to reload the image all the time. */
194
263
if(float_images[slot]->users == 0)
195
264
need_update = true;
205
274
if(img->filename == "")
208
/* load image from file through OIIO */
209
ImageInput *in = ImageInput::create(img->filename);
216
if(!in->open(img->filename, spec)) {
277
ImageInput *in = NULL;
278
int width, height, components;
280
if(!img->builtin_data) {
281
/* load image from file through OIIO */
282
in = ImageInput::create(img->filename);
289
if(!in->open(img->filename, spec)) {
295
height = spec.height;
296
components = spec.nchannels;
299
/* load image using builtin images callbacks */
300
if(!builtin_image_info_cb || !builtin_image_pixels_cb)
304
builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, components);
221
307
/* we only handle certain number of components */
222
int width = spec.width;
223
int height = spec.height;
224
int components = spec.nchannels;
226
308
if(!(components == 1 || components == 3 || components == 4)) {
267
357
if(img->filename == "")
270
/* load image from file through OIIO */
271
ImageInput *in = ImageInput::create(img->filename);
278
if(!in->open(img->filename, spec)) {
283
/* we only handle certain number of components */
284
int width = spec.width;
285
int height = spec.height;
286
int components = spec.nchannels;
360
ImageInput *in = NULL;
361
int width, height, components;
363
if(!img->builtin_data) {
364
/* load image from file through OIIO */
365
in = ImageInput::create(img->filename);
372
if(!in->open(img->filename, spec)) {
377
/* we only handle certain number of components */
379
height = spec.height;
380
components = spec.nchannels;
383
/* load image using builtin images callbacks */
384
if(!builtin_image_info_cb || !builtin_image_float_pixels_cb)
388
builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, components);
288
391
if(!(components == 1 || components == 3 || components == 4)) {
327
void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int slot)
437
void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int slot, Progress *progress)
439
if(progress->get_cancel())
329
441
if(osl_texture_system)
335
if(slot < TEX_IMAGE_FLOAT_START) {
447
if(slot >= tex_image_byte_start) {
448
img = images[slot - tex_image_byte_start];
337
449
is_float = false;
340
img = float_images[slot - TEX_IMAGE_FLOAT_START];
452
img = float_images[slot];
345
device_vector<float4>& tex_img = dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START];
347
if(tex_img.device_pointer)
457
string filename = path_filename(float_images[slot]->filename);
458
progress->set_status("Updating Images", "Loading " + filename);
460
device_vector<float4>& tex_img = dscene->tex_float_image[slot];
462
if(tex_img.device_pointer) {
463
thread_scoped_lock device_lock(device_mutex);
348
464
device->tex_free(tex_img);
350
467
if(!file_load_float_image(img, tex_img)) {
351
/* on failure to load, we set a 1x1 pixels black image */
468
/* on failure to load, we set a 1x1 pixels pink image */
352
469
float *pixels = (float*)tex_img.resize(1, 1);
471
pixels[0] = TEX_IMAGE_MISSING_R;
472
pixels[1] = TEX_IMAGE_MISSING_G;
473
pixels[2] = TEX_IMAGE_MISSING_B;
474
pixels[3] = TEX_IMAGE_MISSING_A;
362
479
if(slot >= 10) name = string_printf("__tex_image_float_0%d", slot);
363
480
else name = string_printf("__tex_image_float_00%d", slot);
365
device->tex_alloc(name.c_str(), tex_img, true, true);
483
thread_scoped_lock device_lock(device_mutex);
484
device->tex_alloc(name.c_str(), tex_img, true, true);
368
device_vector<uchar4>& tex_img = dscene->tex_image[slot];
370
if(tex_img.device_pointer)
488
string filename = path_filename(images[slot - tex_image_byte_start]->filename);
489
progress->set_status("Updating Images", "Loading " + filename);
491
device_vector<uchar4>& tex_img = dscene->tex_image[slot - tex_image_byte_start];
493
if(tex_img.device_pointer) {
494
thread_scoped_lock device_lock(device_mutex);
371
495
device->tex_free(tex_img);
373
498
if(!file_load_image(img, tex_img)) {
374
/* on failure to load, we set a 1x1 pixels black image */
499
/* on failure to load, we set a 1x1 pixels pink image */
375
500
uchar *pixels = (uchar*)tex_img.resize(1, 1);
502
pixels[0] = (TEX_IMAGE_MISSING_R * 255);
503
pixels[1] = (TEX_IMAGE_MISSING_G * 255);
504
pixels[2] = (TEX_IMAGE_MISSING_B * 255);
505
pixels[3] = (TEX_IMAGE_MISSING_A * 255);
413
543
else if(is_float) {
414
device->tex_free(dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START]);
415
dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START].clear();
417
delete float_images[slot - TEX_IMAGE_FLOAT_START];
418
float_images[slot - TEX_IMAGE_FLOAT_START] = NULL;
544
device_vector<float4>& tex_img = dscene->tex_float_image[slot];
546
if(tex_img.device_pointer) {
547
thread_scoped_lock device_lock(device_mutex);
548
device->tex_free(tex_img);
553
delete float_images[slot];
554
float_images[slot] = NULL;
421
device->tex_free(dscene->tex_image[slot]);
422
dscene->tex_image[slot].clear();
557
device_vector<uchar4>& tex_img = dscene->tex_image[slot - tex_image_byte_start];
559
if(tex_img.device_pointer) {
560
thread_scoped_lock device_lock(device_mutex);
561
device->tex_free(tex_img);
566
delete images[slot - tex_image_byte_start];
567
images[slot - tex_image_byte_start] = NULL;
435
579
for(size_t slot = 0; slot < images.size(); slot++) {
437
if(images[slot]->users == 0) {
438
device_free_image(device, dscene, slot);
440
else if(images[slot]->need_load) {
441
string name = path_filename(images[slot]->filename);
442
progress.set_status("Updating Images", "Loading " + name);
443
device_load_image(device, dscene, slot);
444
images[slot]->need_load = false;
447
if(progress.get_cancel()) return;
583
if(images[slot]->users == 0) {
584
device_free_image(device, dscene, slot + tex_image_byte_start);
586
else if(images[slot]->need_load) {
587
if(!osl_texture_system)
588
pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot + tex_image_byte_start, &progress));
451
592
for(size_t slot = 0; slot < float_images.size(); slot++) {
452
if(float_images[slot]) {
453
if(float_images[slot]->users == 0) {
454
device_free_image(device, dscene, slot + TEX_IMAGE_FLOAT_START);
456
else if(float_images[slot]->need_load) {
457
string name = path_filename(float_images[slot]->filename);
458
progress.set_status("Updating Images", "Loading " + name);
459
device_load_image(device, dscene, slot + TEX_IMAGE_FLOAT_START);
460
float_images[slot]->need_load = false;
593
if(!float_images[slot])
463
if(progress.get_cancel()) return;
596
if(float_images[slot]->users == 0) {
597
device_free_image(device, dscene, slot);
599
else if(float_images[slot]->need_load) {
600
if(!osl_texture_system)
601
pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot, &progress));
608
device_pack_images(device, dscene, progress);
467
610
need_update = false;
613
void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progress& progess)
615
/* for OpenCL, we pack all image textures inside a single big texture, and
616
* will do our own interpolation in the kernel */
619
for(size_t slot = 0; slot < images.size(); slot++) {
623
device_vector<uchar4>& tex_img = dscene->tex_image[slot];
624
size += tex_img.size();
627
uint4 *info = dscene->tex_image_packed_info.resize(images.size());
628
uchar4 *pixels = dscene->tex_image_packed.resize(size);
632
for(size_t slot = 0; slot < images.size(); slot++) {
636
device_vector<uchar4>& tex_img = dscene->tex_image[slot];
638
info[slot] = make_uint4(tex_img.data_width, tex_img.data_height, offset, 1);
640
memcpy(pixels+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
641
offset += tex_img.size();
644
if(dscene->tex_image_packed.size())
645
device->tex_alloc("__tex_image_packed", dscene->tex_image_packed);
646
if(dscene->tex_image_packed_info.size())
647
device->tex_alloc("__tex_image_packed_info", dscene->tex_image_packed_info);
470
650
void ImageManager::device_free(Device *device, DeviceScene *dscene)
472
652
for(size_t slot = 0; slot < images.size(); slot++)
653
device_free_image(device, dscene, slot + tex_image_byte_start);
654
for(size_t slot = 0; slot < float_images.size(); slot++)
473
655
device_free_image(device, dscene, slot);
474
for(size_t slot = 0; slot < float_images.size(); slot++)
475
device_free_image(device, dscene, slot + TEX_IMAGE_FLOAT_START);
657
device->tex_free(dscene->tex_image_packed);
658
device->tex_free(dscene->tex_image_packed_info);
660
dscene->tex_image_packed.clear();
661
dscene->tex_image_packed_info.clear();
478
664
float_images.clear();