Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render/image.cpp')
-rw-r--r--intern/cycles/render/image.cpp208
1 files changed, 201 insertions, 7 deletions
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 71dc85f5f03..c5e819520ea 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -54,10 +54,14 @@ ImageManager::ImageManager(const DeviceInfo& info)
tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_ ## ARCH; \
tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_ ## ARCH; \
tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_ ## ARCH; \
+ tex_num_images[IMAGE_DATA_TYPE_HALF4] = TEX_NUM_HALF4_ ## ARCH; \
+ tex_num_images[IMAGE_DATA_TYPE_HALF] = TEX_NUM_HALF_ ## ARCH; \
tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_START_FLOAT4_ ## ARCH; \
tex_start_images[IMAGE_DATA_TYPE_BYTE4] = TEX_START_BYTE4_ ## ARCH; \
tex_start_images[IMAGE_DATA_TYPE_FLOAT] = TEX_START_FLOAT_ ## ARCH; \
tex_start_images[IMAGE_DATA_TYPE_BYTE] = TEX_START_BYTE_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_HALF4] = TEX_START_HALF4_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_HALF] = TEX_START_HALF_ ## ARCH; \
}
if(device_type == DEVICE_CPU) {
@@ -80,10 +84,14 @@ ImageManager::ImageManager(const DeviceInfo& info)
tex_num_images[IMAGE_DATA_TYPE_BYTE4] = 0;
tex_num_images[IMAGE_DATA_TYPE_FLOAT] = 0;
tex_num_images[IMAGE_DATA_TYPE_BYTE] = 0;
+ tex_num_images[IMAGE_DATA_TYPE_HALF4] = 0;
+ tex_num_images[IMAGE_DATA_TYPE_HALF] = 0;
tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = 0;
tex_start_images[IMAGE_DATA_TYPE_BYTE4] = 0;
tex_start_images[IMAGE_DATA_TYPE_FLOAT] = 0;
tex_start_images[IMAGE_DATA_TYPE_BYTE] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_HALF4] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_HALF] = 0;
assert(0);
}
@@ -128,7 +136,7 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
void *builtin_data,
bool& is_linear)
{
- bool is_float = false;
+ bool is_float = false, is_half = false;
is_linear = false;
int channels = 4;
@@ -167,6 +175,10 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
}
}
+ /* check if it's half float */
+ if(spec.format == TypeDesc::HALF)
+ is_half = true;
+
channels = spec.nchannels;
/* basic color space detection, not great but better than nothing
@@ -192,7 +204,10 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
delete in;
}
- if(is_float) {
+ if(is_half) {
+ return IMAGE_DATA_TYPE_HALF4;
+ }
+ else if(is_float) {
return (channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
}
else {
@@ -230,6 +245,10 @@ string ImageManager::name_from_type(int type)
return "float";
else if(type == IMAGE_DATA_TYPE_BYTE)
return "byte";
+ else if(type == IMAGE_DATA_TYPE_HALF4)
+ return "half4";
+ else if(type == IMAGE_DATA_TYPE_HALF)
+ return "half";
else
return "byte4";
}
@@ -265,11 +284,16 @@ int ImageManager::add_image(const string& filename,
if(type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4)
is_float = true;
- /* No single channel textures on CUDA (Fermi) and OpenCL, use available slots */
- if(type == IMAGE_DATA_TYPE_FLOAT && tex_num_images[type] == 0)
+ /* No single channel and half textures on CUDA (Fermi) and OpenCL, use available slots */
+ if((type == IMAGE_DATA_TYPE_FLOAT ||
+ type == IMAGE_DATA_TYPE_HALF4 ||
+ type == IMAGE_DATA_TYPE_HALF) &&
+ tex_num_images[type] == 0) {
type = IMAGE_DATA_TYPE_FLOAT4;
- if(type == IMAGE_DATA_TYPE_BYTE && tex_num_images[type] == 0)
+ }
+ if(type == IMAGE_DATA_TYPE_BYTE && tex_num_images[type] == 0) {
type = IMAGE_DATA_TYPE_BYTE4;
+ }
/* Fnd existing image. */
for(slot = 0; slot < images[type].size(); slot++) {
@@ -645,6 +669,107 @@ bool ImageManager::file_load_float_image(Image *img, ImageDataType type, device_
return true;
}
+template<typename T>
+bool ImageManager::file_load_half_image(Image *img, ImageDataType type, device_vector<T>& tex_img)
+{
+ ImageInput *in = NULL;
+ int width, height, depth, components;
+
+ if(!file_load_image_generic(img, &in, width, height, depth, components))
+ return false;
+
+ /* read RGBA pixels */
+ half *pixels = (half*)tex_img.resize(width, height, depth);
+ if(pixels == NULL) {
+ return false;
+ }
+
+ if(in) {
+ half *readpixels = pixels;
+ vector<half> tmppixels;
+
+ if(components > 4) {
+ tmppixels.resize(((size_t)width)*height*components);
+ readpixels = &tmppixels[0];
+ }
+
+ if(depth <= 1) {
+ int scanlinesize = width*components*sizeof(half);
+
+ in->read_image(TypeDesc::HALF,
+ (uchar*)readpixels + (height-1)*scanlinesize, /*TODO(dingto): why uchar cast? */
+ AutoStride,
+ -scanlinesize,
+ AutoStride);
+ }
+ else {
+ in->read_image(TypeDesc::HALF, (uchar*)readpixels);
+ }
+
+ if(components > 4) {
+ size_t dimensions = ((size_t)width)*height;
+ for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) {
+ pixels[i*4+3] = tmppixels[i*components+3];
+ pixels[i*4+2] = tmppixels[i*components+2];
+ pixels[i*4+1] = tmppixels[i*components+1];
+ pixels[i*4+0] = tmppixels[i*components+0];
+ }
+
+ tmppixels.clear();
+ }
+
+ in->close();
+ delete in;
+ }
+#if 0
+ /* TODO(dingto): Support half for ImBuf. */
+ else {
+ builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels);
+ }
+#endif
+
+ /* Check if we actually have a half4 slot, in case components == 1, but device
+ * doesn't support single channel textures. */
+ if(type == IMAGE_DATA_TYPE_HALF4) {
+ size_t num_pixels = ((size_t)width) * height * depth;
+ if(components == 2) {
+ /* grayscale + alpha */
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i*4+3] = pixels[i*2+1];
+ pixels[i*4+2] = pixels[i*2+0];
+ pixels[i*4+1] = pixels[i*2+0];
+ pixels[i*4+0] = pixels[i*2+0];
+ }
+ }
+ else if(components == 3) {
+ /* RGB */
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i*4+3] = 1.0f;
+ pixels[i*4+2] = pixels[i*3+2];
+ pixels[i*4+1] = pixels[i*3+1];
+ pixels[i*4+0] = pixels[i*3+0];
+ }
+ }
+ else if(components == 1) {
+ /* grayscale */
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i*4+3] = 1.0f;
+ pixels[i*4+2] = pixels[i];
+ pixels[i*4+1] = pixels[i];
+ pixels[i*4+0] = pixels[i];
+ }
+ }
+
+ if(img->use_alpha == false) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i*4+3] = 1.0f;
+ }
+ }
+ }
+
+ return true;
+}
+
void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot, Progress *progress)
{
if(progress->get_cancel())
@@ -744,7 +869,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
img->extension);
}
}
- else {
+ else if(type == IMAGE_DATA_TYPE_BYTE){
device_vector<uchar>& tex_img = dscene->tex_byte_image[slot];
if(tex_img.device_pointer) {
@@ -767,6 +892,55 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
img->extension);
}
}
+ else if(type == IMAGE_DATA_TYPE_HALF4){
+ device_vector<half4>& tex_img = dscene->tex_half4_image[slot];
+
+ if(tex_img.device_pointer) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_free(tex_img);
+ }
+
+ if(!file_load_half_image(img, type, tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ half *pixels = (half*)tex_img.resize(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ pixels[1] = TEX_IMAGE_MISSING_G;
+ pixels[2] = TEX_IMAGE_MISSING_B;
+ pixels[3] = TEX_IMAGE_MISSING_A;
+ }
+
+ if(!pack_images) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_alloc(name.c_str(),
+ tex_img,
+ img->interpolation,
+ img->extension);
+ }
+ }
+ else if(type == IMAGE_DATA_TYPE_HALF){
+ device_vector<half>& tex_img = dscene->tex_half_image[slot];
+
+ if(tex_img.device_pointer) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_free(tex_img);
+ }
+
+ if(!file_load_half_image(img, type, tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ half *pixels = (half*)tex_img.resize(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ }
+
+ if(!pack_images) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_alloc(name.c_str(),
+ tex_img,
+ img->interpolation,
+ img->extension);
+ }
+ }
img->need_load = false;
}
@@ -812,7 +986,7 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageD
tex_img.clear();
}
- else {
+ else if(type == IMAGE_DATA_TYPE_BYTE){
device_vector<uchar>& tex_img = dscene->tex_byte_image[slot];
if(tex_img.device_pointer) {
@@ -822,6 +996,26 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageD
tex_img.clear();
}
+ else if(type == IMAGE_DATA_TYPE_HALF4){
+ device_vector<half4>& tex_img = dscene->tex_half4_image[slot];
+
+ if(tex_img.device_pointer) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_free(tex_img);
+ }
+
+ tex_img.clear();
+ }
+ else if(type == IMAGE_DATA_TYPE_HALF){
+ device_vector<half>& tex_img = dscene->tex_half_image[slot];
+
+ if(tex_img.device_pointer) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_free(tex_img);
+ }
+
+ tex_img.clear();
+ }
delete images[type][slot];
images[type][slot] = NULL;