36 # include <OSL/oslexec.h>
77 return "nanovdb_float";
79 return "nanovdb_float3";
81 assert(!
"System enumerator type, should never be used");
84 assert(!
"Unhandled image data type");
97 : tile_slots(other.tile_slots), manager(other.manager)
126 manager->remove_image_user(slot);
150 manager->load_image_metadata(img);
160 if (
manager->osl_texture_system) {
194 if (loader ==
NULL) {
220 colorspace_file_format(
""),
221 use_transform_3d(false),
222 compress_as_srgb(false)
288 return (
a && b &&
typeid(*
a) ==
typeid(*b) &&
a->equals(*b));
302 osl_texture_system =
NULL;
312 for (
size_t slot = 0; slot < images.size(); slot++)
313 assert(!images[slot]);
318 osl_texture_system = texture_system;
323 if (frame != animation_frame) {
325 animation_frame = frame;
327 for (
size_t slot = 0; slot < images.size(); slot++) {
328 if (images[slot] && images[slot]->
params.animated)
336 void ImageManager::load_image_metadata(
Image *img)
338 if (!img->need_metadata) {
343 if (!img->need_metadata) {
351 if (img->loader->load_metadata(features, metadata)) {
365 img->need_metadata =
false;
385 foreach (
int tile, tiles) {
386 string tile_filename = filename;
401 const int slot = add_image_slot(loader,
params, builtin);
409 int ImageManager::add_image_slot(
ImageLoader *loader,
419 for (slot = 0; slot < images.size(); slot++) {
429 for (slot = 0; slot < images.size(); slot++) {
434 if (slot == images.size()) {
435 images.resize(images.size() + 1);
441 img->loader = loader;
442 img->need_metadata =
true;
443 img->need_load = !(osl_texture_system && !img->loader->osl_filepath().empty());
444 img->builtin = builtin;
455 void ImageManager::add_image_user(
int slot)
458 Image *image = images[slot];
459 assert(image && image->users >= 1);
464 void ImageManager::remove_image_user(
int slot)
467 Image *image = images[slot];
468 assert(image && image->users >= 1);
476 if (image->users == 0)
489 template<TypeDesc::BASETYPE FileFormat,
typename StorageType>
490 bool ImageManager::file_load_image(
Image *img,
int texture_limit)
493 if (!(img->metadata.channels > 0)) {
500 int depth = img->metadata.depth;
501 int components = img->metadata.channels;
513 if (texture_limit > 0 && max_size > texture_limit) {
514 pixels_storage.resize(((
size_t)
width) *
height * depth * 4);
515 pixels = &pixels_storage[0];
519 pixels = (StorageType *)img->mem->alloc(
width,
height, depth);
522 if (pixels ==
NULL) {
527 const size_t num_pixels = ((size_t)
width) *
height * depth;
528 img->loader->load_pixels(
539 const StorageType one = util_image_cast_from_float<StorageType>(1.0f);
541 if (components == 2) {
543 for (
size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
544 pixels[i * 4 + 3] = pixels[i * 2 + 1];
545 pixels[i * 4 + 2] = pixels[i * 2 + 0];
546 pixels[i * 4 + 1] = pixels[i * 2 + 0];
547 pixels[i * 4 + 0] = pixels[i * 2 + 0];
550 else if (components == 3) {
552 for (
size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
553 pixels[i * 4 + 3] = one;
554 pixels[i * 4 + 2] = pixels[i * 3 + 2];
555 pixels[i * 4 + 1] = pixels[i * 3 + 1];
556 pixels[i * 4 + 0] = pixels[i * 3 + 0];
559 else if (components == 1) {
561 for (
size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
562 pixels[i * 4 + 3] = one;
563 pixels[i * 4 + 2] = pixels[i];
564 pixels[i * 4 + 1] = pixels[i];
565 pixels[i * 4 + 0] = pixels[i];
571 for (
size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
572 pixels[i * 4 + 3] = one;
580 img->metadata.colorspace, pixels, num_pixels, img->metadata.compress_as_srgb);
585 if (FileFormat == TypeDesc::FLOAT) {
590 for (
size_t i = 0; i < num_pixels; i += 4) {
591 StorageType *pixel = &pixels[i * 4];
602 for (
size_t i = 0; i < num_pixels; ++i) {
603 StorageType *pixel = &pixels[i];
612 if (pixels_storage.size() > 0) {
613 float scale_factor = 1.0f;
614 while (max_size * scale_factor > texture_limit) {
615 scale_factor *= 0.5f;
617 VLOG(1) <<
"Scaling image " << img->loader->name() <<
" by a factor of " << scale_factor
620 size_t scaled_width, scaled_height, scaled_depth;
632 StorageType *texture_pixels;
636 texture_pixels = (StorageType *)img->mem->alloc(scaled_width, scaled_height, scaled_depth);
639 memcpy(texture_pixels, &scaled_pixels[0], scaled_pixels.size() *
sizeof(StorageType));
651 Image *img = images[slot];
653 progress->
set_status(
"Updating Images",
"Loading " + img->loader->name());
657 load_image_metadata(img);
671 device, img->mem_name.c_str(), slot,
type, img->params.interpolation, img->params.extension);
672 img->mem->info.use_transform_3d = img->metadata.use_transform_3d;
673 img->mem->info.transform_3d = img->metadata.transform_3d;
677 if (!file_load_image<TypeDesc::FLOAT, float>(img, texture_limit)) {
680 float *pixels = (
float *)img->mem->alloc(1, 1);
689 if (!file_load_image<TypeDesc::FLOAT, float>(img, texture_limit)) {
692 float *pixels = (
float *)img->mem->alloc(1, 1);
698 if (!file_load_image<TypeDesc::UINT8, uchar>(img, texture_limit)) {
701 uchar *pixels = (
uchar *)img->mem->alloc(1, 1);
710 if (!file_load_image<TypeDesc::UINT8, uchar>(img, texture_limit)) {
713 uchar *pixels = (
uchar *)img->mem->alloc(1, 1);
719 if (!file_load_image<TypeDesc::HALF, half>(img, texture_limit)) {
722 half *pixels = (
half *)img->mem->alloc(1, 1);
731 if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, texture_limit)) {
740 if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, texture_limit)) {
752 if (!file_load_image<TypeDesc::HALF, half>(img, texture_limit)) {
755 half *pixels = (
half *)img->mem->alloc(1, 1);
763 void *pixels = img->mem->alloc(img->metadata.byte_size, 0);
765 if (pixels !=
NULL) {
766 img->loader->load_pixels(img->metadata, pixels, img->metadata.byte_size,
false);
773 img->mem->copy_to_device();
777 img->loader->cleanup();
778 img->need_load =
false;
781 void ImageManager::device_free_image(
Device *,
int slot)
783 Image *img = images[slot];
788 if (osl_texture_system) {
790 ustring filepath = img->loader->osl_filepath();
791 if (!filepath.empty()) {
792 ((OSL::TextureSystem *)osl_texture_system)->invalidate(filepath);
815 scene->update_stats->image.times.add_entry({
"device_update", time});
820 for (
size_t slot = 0; slot < images.size(); slot++) {
821 Image *img = images[slot];
822 if (img && img->users == 0) {
823 device_free_image(device, slot);
825 else if (img && img->need_load) {
827 function_bind(&ImageManager::device_load_image,
this, device,
scene, slot, &progress));
833 need_update_ =
false;
838 Image *img = images[slot];
841 if (img->
users == 0) {
842 device_free_image(device, slot);
845 device_load_image(device,
scene, slot, progress);
858 for (
size_t slot = 0; slot < images.size(); slot++) {
859 Image *img = images[slot];
862 function_bind(&ImageManager::device_load_image,
this, device,
scene, slot, &progress));
871 for (
size_t slot = 0; slot < images.size(); slot++) {
872 Image *img = images[slot];
874 device_free_image(device, slot);
881 for (
size_t slot = 0; slot < images.size(); slot++) {
882 device_free_image(device, slot);
889 foreach (
const Image *image, images) {
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
static bool colorspace_is_data(ustring colorspace)
static void to_scene_linear(ustring colorspace, T *pixels, size_t num_pixels, bool compress_as_srgb)
static ustring detect_known_colorspace(ustring colorspace, const char *file_format, bool is_float)
bool operator==(const ImageHandle &other) const
VDBImageLoader * vdb_loader(const int tile_index=0) const
device_texture * image_memory(const int tile_index=0) const
ImageHandle & operator=(const ImageHandle &other)
int svm_slot(const int tile_index=0) const
virtual bool equals(const ImageLoader &other) const =0
virtual ustring osl_filepath() const
virtual string name() const =0
virtual bool is_vdb_loader() const
bool set_animation_frame_update(int frame)
ImageManager(const DeviceInfo &info)
void device_update(Device *device, Scene *scene, Progress &progress)
void device_free(Device *device)
void device_load_builtin(Device *device, Scene *scene, Progress &progress)
void device_free_builtin(Device *device)
ImageHandle add_image(const string &filename, const ImageParams ¶ms)
void device_update_slot(Device *device, Scene *scene, int slot, Progress *progress)
void collect_statistics(RenderStats *stats)
void set_osl_texture_system(void *texture_system)
ImageAlphaType alpha_type
void add_entry(const NamedSizeEntry &entry)
void set_status(const string &status_, const string &substatus_="")
ustring u_colorspace_srgb
static bool image_associate_alpha(ImageManager::Image *img)
#define CCL_NAMESPACE_END
const char * name_from_type(ImageDataType type)
SceneUpdateStats * update_stats
void push(TaskRunFunction &&task)
void wait_work(Summary *stats=NULL)
CCL_NAMESPACE_BEGIN OIIO_NAMESPACE_USING void util_image_resize_pixels(const vector< T > &input_pixels, const size_t input_width, const size_t input_height, const size_t input_depth, const size_t components, vector< T > *output_pixels, size_t *output_width, size_t *output_height, size_t *output_depth)
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
void string_replace(string &haystack, const string &needle, const string &other)
@ IMAGE_DATA_TYPE_USHORT4
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT3
@ IMAGE_ALPHA_CHANNEL_PACKED
#define TEX_IMAGE_MISSING_R
#define TEX_IMAGE_MISSING_B
#define TEX_IMAGE_MISSING_A
#define TEX_IMAGE_MISSING_G
std::unique_lock< std::mutex > thread_scoped_lock