/* * Copyright 2011-2013 Blender Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __IMAGE_H__ #define __IMAGE_H__ #include "device/device_memory.h" #include "render/colorspace.h" #include "util/util_string.h" #include "util/util_thread.h" #include "util/util_transform.h" #include "util/util_unique_ptr.h" #include "util/util_vector.h" CCL_NAMESPACE_BEGIN class Device; class DeviceInfo; class ImageHandle; class ImageKey; class ImageMetaData; class ImageManager; class Progress; class RenderStats; class Scene; class ColorSpaceProcessor; class VDBImageLoader; /* Image Parameters */ class ImageParams { public: bool animated; InterpolationType interpolation; ExtensionType extension; ImageAlphaType alpha_type; ustring colorspace; float frame; ImageParams() : animated(false), interpolation(INTERPOLATION_LINEAR), extension(EXTENSION_CLIP), alpha_type(IMAGE_ALPHA_AUTO), colorspace(u_colorspace_raw), frame(0.0f) { } bool operator==(const ImageParams &other) const { return (animated == other.animated && interpolation == other.interpolation && extension == other.extension && alpha_type == other.alpha_type && colorspace == other.colorspace && frame == other.frame); } }; /* Image MetaData * * Information about the image that is available before the image pixels are loaded. */ class ImageMetaData { public: /* Set by ImageLoader.load_metadata(). */ int channels; size_t width, height, depth; size_t byte_size; ImageDataType type; /* Optional color space, defaults to raw. */ ustring colorspace; const char *colorspace_file_format; /* Optional transform for 3D images. */ bool use_transform_3d; Transform transform_3d; /* Automatically set. */ bool compress_as_srgb; ImageMetaData(); bool operator==(const ImageMetaData &other) const; bool is_float() const; void detect_colorspace(); }; /* Information about supported features that Image loaders can use. */ class ImageDeviceFeatures { public: bool has_half_float; bool has_nanovdb; }; /* Image loader base class, that can be subclassed to load image data * from custom sources (file, memory, procedurally generated, etc). */ class ImageLoader { public: ImageLoader(); virtual ~ImageLoader(){}; /* Load metadata without actual image yet, should be fast. */ virtual bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) = 0; /* Load actual image contents. */ virtual bool load_pixels(const ImageMetaData &metadata, void *pixels, const size_t pixels_size, const bool associate_alpha) = 0; /* Name for logs and stats. */ virtual string name() const = 0; /* Optional for OSL texture cache. */ virtual ustring osl_filepath() const; /* Free any memory used for loading metadata and pixels. */ virtual void cleanup(){}; /* Compare avoid loading the same image multiple times. */ virtual bool equals(const ImageLoader &other) const = 0; static bool equals(const ImageLoader *a, const ImageLoader *b); virtual bool is_vdb_loader() const; /* Work around for no RTTI. */ }; /* Image Handle * * Access handle for image in the image manager. Multiple shader nodes may * share the same image, and this class handles reference counting for that. */ class ImageHandle { public: ImageHandle(); ImageHandle(const ImageHandle &other); ImageHandle &operator=(const ImageHandle &other); ~ImageHandle(); bool operator==(const ImageHandle &other) const; void clear(); bool empty(); int num_tiles(); ImageMetaData metadata(); int svm_slot(const int tile_index = 0) const; device_texture *image_memory(const int tile_index = 0) const; VDBImageLoader *vdb_loader(const int tile_index = 0) const; protected: vector tile_slots; ImageManager *manager; friend class ImageManager; }; /* Image Manager * * Handles loading and storage of all images in the scene. This includes 2D * texture images and 3D volume images. */ class ImageManager { public: explicit ImageManager(const DeviceInfo &info); ~ImageManager(); ImageHandle add_image(const string &filename, const ImageParams ¶ms); ImageHandle add_image(const string &filename, const ImageParams ¶ms, const array &tiles); ImageHandle add_image(ImageLoader *loader, const ImageParams ¶ms, const bool builtin = true); void device_update(Device *device, Scene *scene, Progress &progress); void device_update_slot(Device *device, Scene *scene, int slot, Progress *progress); void device_free(Device *device); void device_load_builtin(Device *device, Scene *scene, Progress &progress); void device_free_builtin(Device *device); void set_osl_texture_system(void *texture_system); bool set_animation_frame_update(int frame); void collect_statistics(RenderStats *stats); void tag_update(); bool need_update() const; struct Image { ImageParams params; ImageMetaData metadata; ImageLoader *loader; float frame; bool need_metadata; bool need_load; bool builtin; string mem_name; device_texture *mem; int users; thread_mutex mutex; }; private: bool need_update_; ImageDeviceFeatures features; thread_mutex device_mutex; thread_mutex images_mutex; int animation_frame; vector images; void *osl_texture_system; int add_image_slot(ImageLoader *loader, const ImageParams ¶ms, const bool builtin); void add_image_user(int slot); void remove_image_user(int slot); void load_image_metadata(Image *img); template bool file_load_image(Image *img, int texture_limit); void device_load_image(Device *device, Scene *scene, int slot, Progress *progress); void device_free_image(Device *device, int slot); friend class ImageHandle; }; CCL_NAMESPACE_END #endif /* __IMAGE_H__ */