Пример #1
0
int ImageManager::max_flattened_slot(ImageDataType type)
{
	if(tex_num_images[type] == 0) {
		/* No textures for the type, no slots needs allocation. */
		return 0;
	}
	return type_index_to_flattened_slot(tex_num_images[type], type);
}
Пример #2
0
void ImageManager::remove_image(const string& filename,
                                void *builtin_data,
                                InterpolationType interpolation,
                                ExtensionType extension)
{
	size_t slot;

	for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
		for(slot = 0; slot < images[type].size(); slot++) {
			if(images[type][slot] && image_equals(images[type][slot],
			                                      filename,
			                                      builtin_data,
			                                      interpolation,
			                                      extension))
			{
				remove_image(type_index_to_flattened_slot(slot, (ImageDataType)type));
				return;
			}
		}
	}
}
Пример #3
0
void ImageManager::device_load_image(Device *device,
                                     Scene *scene,
                                     ImageDataType type,
                                     int slot,
                                     Progress *progress)
{
	if(progress->get_cancel())
		return;

	Image *img = images[type][slot];

	if(osl_texture_system && !img->builtin_data)
		return;

	string filename = path_filename(images[type][slot]->filename);
	progress->set_status("Updating Images", "Loading " + filename);

	const int texture_limit = scene->params.texture_limit;

	/* Slot assignment */
	int flat_slot = type_index_to_flattened_slot(slot, type);
	img->mem_name = string_printf("__tex_image_%s_%03d", name_from_type(type).c_str(), flat_slot);

	/* Free previous texture in slot. */
	if(img->mem) {
		thread_scoped_lock device_lock(device_mutex);
		delete img->mem;
		img->mem = NULL;
	}

	/* Create new texture. */
	if(type == IMAGE_DATA_TYPE_FLOAT4) {
		device_vector<float4> *tex_img
			= new device_vector<float4>(device, img->mem_name.c_str(), MEM_TEXTURE);

		if(!file_load_image<TypeDesc::FLOAT, float>(img,
		                                            type,
		                                            texture_limit,
		                                            *tex_img))
		{
			/* on failure to load, we set a 1x1 pixels pink image */
			thread_scoped_lock device_lock(device_mutex);
			float *pixels = (float*)tex_img->alloc(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;
		}

		img->mem = tex_img;
		img->mem->interpolation = img->interpolation;
		img->mem->extension = img->extension;

		thread_scoped_lock device_lock(device_mutex);
		tex_img->copy_to_device();
	}
	else if(type == IMAGE_DATA_TYPE_FLOAT) {
		device_vector<float> *tex_img
			= new device_vector<float>(device, img->mem_name.c_str(), MEM_TEXTURE);

		if(!file_load_image<TypeDesc::FLOAT, float>(img,
		                                            type,
		                                            texture_limit,
		                                            *tex_img))
		{
			/* on failure to load, we set a 1x1 pixels pink image */
			thread_scoped_lock device_lock(device_mutex);
			float *pixels = (float*)tex_img->alloc(1, 1);

			pixels[0] = TEX_IMAGE_MISSING_R;
		}

		img->mem = tex_img;
		img->mem->interpolation = img->interpolation;
		img->mem->extension = img->extension;

		thread_scoped_lock device_lock(device_mutex);
		tex_img->copy_to_device();
	}
	else if(type == IMAGE_DATA_TYPE_BYTE4) {
		device_vector<uchar4> *tex_img
			= new device_vector<uchar4>(device, img->mem_name.c_str(), MEM_TEXTURE);

		if(!file_load_image<TypeDesc::UINT8, uchar>(img,
		                                            type,
		                                            texture_limit,
		                                            *tex_img))
		{
			/* on failure to load, we set a 1x1 pixels pink image */
			thread_scoped_lock device_lock(device_mutex);
			uchar *pixels = (uchar*)tex_img->alloc(1, 1);

			pixels[0] = (TEX_IMAGE_MISSING_R * 255);
			pixels[1] = (TEX_IMAGE_MISSING_G * 255);
			pixels[2] = (TEX_IMAGE_MISSING_B * 255);
			pixels[3] = (TEX_IMAGE_MISSING_A * 255);
		}

		img->mem = tex_img;
		img->mem->interpolation = img->interpolation;
		img->mem->extension = img->extension;

		thread_scoped_lock device_lock(device_mutex);
		tex_img->copy_to_device();
	}
	else if(type == IMAGE_DATA_TYPE_BYTE) {
		device_vector<uchar> *tex_img
			= new device_vector<uchar>(device, img->mem_name.c_str(), MEM_TEXTURE);

		if(!file_load_image<TypeDesc::UINT8, uchar>(img,
		                                            type,
		                                            texture_limit,
		                                            *tex_img)) {
			/* on failure to load, we set a 1x1 pixels pink image */
			thread_scoped_lock device_lock(device_mutex);
			uchar *pixels = (uchar*)tex_img->alloc(1, 1);

			pixels[0] = (TEX_IMAGE_MISSING_R * 255);
		}

		img->mem = tex_img;
		img->mem->interpolation = img->interpolation;
		img->mem->extension = img->extension;

		thread_scoped_lock device_lock(device_mutex);
		tex_img->copy_to_device();
	}
	else if(type == IMAGE_DATA_TYPE_HALF4) {
		device_vector<half4> *tex_img
			= new device_vector<half4>(device, img->mem_name.c_str(), MEM_TEXTURE);

		if(!file_load_image<TypeDesc::HALF, half>(img,
		                                          type,
		                                          texture_limit,
		                                          *tex_img)) {
			/* on failure to load, we set a 1x1 pixels pink image */
			thread_scoped_lock device_lock(device_mutex);
			half *pixels = (half*)tex_img->alloc(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;
		}

		img->mem = tex_img;
		img->mem->interpolation = img->interpolation;
		img->mem->extension = img->extension;

		thread_scoped_lock device_lock(device_mutex);
		tex_img->copy_to_device();
	}
	else if(type == IMAGE_DATA_TYPE_HALF) {
		device_vector<half> *tex_img
			= new device_vector<half>(device, img->mem_name.c_str(), MEM_TEXTURE);

		if(!file_load_image<TypeDesc::HALF, half>(img,
		                                          type,
		                                          texture_limit,
		                                          *tex_img)) {
			/* on failure to load, we set a 1x1 pixels pink image */
			thread_scoped_lock device_lock(device_mutex);
			half *pixels = (half*)tex_img->alloc(1, 1);

			pixels[0] = TEX_IMAGE_MISSING_R;
		}

		img->mem = tex_img;
		img->mem->interpolation = img->interpolation;
		img->mem->extension = img->extension;

		thread_scoped_lock device_lock(device_mutex);
		tex_img->copy_to_device();
	}

	img->need_load = false;
}
Пример #4
0
int ImageManager::add_image(const string& filename,
                            void *builtin_data,
                            bool animated,
                            float frame,
                            InterpolationType interpolation,
                            ExtensionType extension,
                            bool use_alpha,
                            ImageMetaData& metadata)
{
	Image *img;
	size_t slot;

	get_image_metadata(filename, builtin_data, metadata);
	ImageDataType type = metadata.type;

	thread_scoped_lock device_lock(device_mutex);

	/* No half textures on OpenCL, use full float instead. */
	if(!has_half_images) {
		if(type == IMAGE_DATA_TYPE_HALF4) {
			type = IMAGE_DATA_TYPE_FLOAT4;
		}
		else if(type == IMAGE_DATA_TYPE_HALF) {
			type = IMAGE_DATA_TYPE_FLOAT;
		}
	}

	/* Fnd existing image. */
	for(slot = 0; slot < images[type].size(); slot++) {
		img = images[type][slot];
		if(img && image_equals(img,
		                       filename,
		                       builtin_data,
		                       interpolation,
		                       extension,
		                       use_alpha))
		{
			if(img->frame != frame) {
				img->frame = frame;
				img->need_load = true;
			}
			if(img->use_alpha != use_alpha) {
				img->use_alpha = use_alpha;
				img->need_load = true;
			}
			img->users++;
			return type_index_to_flattened_slot(slot, type);
		}
	}

	/* Find free slot. */
	for(slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			break;
	}

	/* Count if we're over the limit.
	 * Very unlikely, since max_num_images is insanely big. But better safe than sorry. */
	int tex_count = 0;
	for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
		tex_count += tex_num_images[type];
	}
	if(tex_count > max_num_images) {
		printf("ImageManager::add_image: Reached image limit (%d), skipping '%s'\n",
			max_num_images, filename.c_str());
		return -1;
	}

	if(slot == images[type].size()) {
		images[type].resize(images[type].size() + 1);
	}

	/* Add new image. */
	img = new Image();
	img->filename = filename;
	img->builtin_data = builtin_data;
	img->builtin_free_cache = metadata.builtin_free_cache;
	img->need_load = true;
	img->animated = animated;
	img->frame = frame;
	img->interpolation = interpolation;
	img->extension = extension;
	img->users = 1;
	img->use_alpha = use_alpha;
	img->mem = NULL;

	images[type][slot] = img;

	++tex_num_images[type];

	need_update = true;

	return type_index_to_flattened_slot(slot, type);
}
Пример #5
0
void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot, Progress *progress)
{
	if(progress->get_cancel())
		return;
	
	Image *img = images[type][slot];

	if(osl_texture_system && !img->builtin_data)
		return;

	string filename = path_filename(images[type][slot]->filename);
	progress->set_status("Updating Images", "Loading " + filename);

	/* Slot assignment */
	int flat_slot = type_index_to_flattened_slot(slot, type);

	string name;
	if(flat_slot >= 100)
		name = string_printf("__tex_image_%s_%d", name_from_type(type).c_str(), flat_slot);
	else if(flat_slot >= 10)
		name = string_printf("__tex_image_%s_0%d", name_from_type(type).c_str(), flat_slot);
	else
		name = string_printf("__tex_image_%s_00%d", name_from_type(type).c_str(), flat_slot);

	if(type == IMAGE_DATA_TYPE_FLOAT4) {
		device_vector<float4>& tex_img = dscene->tex_float4_image[slot];

		if(tex_img.device_pointer) {
			thread_scoped_lock device_lock(device_mutex);
			device->tex_free(tex_img);
		}

		if(!file_load_float_image(img, type, tex_img)) {
			/* on failure to load, we set a 1x1 pixels pink image */
			float *pixels = (float*)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_FLOAT) {
		device_vector<float>& tex_img = dscene->tex_float_image[slot];

		if(tex_img.device_pointer) {
			thread_scoped_lock device_lock(device_mutex);
			device->tex_free(tex_img);
		}

		if(!file_load_float_image(img, type, tex_img)) {
			/* on failure to load, we set a 1x1 pixels pink image */
			float *pixels = (float*)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);
		}
	}
	else if(type == IMAGE_DATA_TYPE_BYTE4) {
		device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot];

		if(tex_img.device_pointer) {
			thread_scoped_lock device_lock(device_mutex);
			device->tex_free(tex_img);
		}

		if(!file_load_byte_image(img, type, tex_img)) {
			/* on failure to load, we set a 1x1 pixels pink image */
			uchar *pixels = (uchar*)tex_img.resize(1, 1);

			pixels[0] = (TEX_IMAGE_MISSING_R * 255);
			pixels[1] = (TEX_IMAGE_MISSING_G * 255);
			pixels[2] = (TEX_IMAGE_MISSING_B * 255);
			pixels[3] = (TEX_IMAGE_MISSING_A * 255);
		}

		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_BYTE){
		device_vector<uchar>& tex_img = dscene->tex_byte_image[slot];

		if(tex_img.device_pointer) {
			thread_scoped_lock device_lock(device_mutex);
			device->tex_free(tex_img);
		}

		if(!file_load_byte_image(img, type, tex_img)) {
			/* on failure to load, we set a 1x1 pixels pink image */
			uchar *pixels = (uchar*)tex_img.resize(1, 1);

			pixels[0] = (TEX_IMAGE_MISSING_R * 255);
		}

		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_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;
}
Пример #6
0
int ImageManager::add_image(const string& filename,
                            void *builtin_data,
                            bool animated,
                            float frame,
                            bool& is_float,
                            bool& is_linear,
                            InterpolationType interpolation,
                            ExtensionType extension,
                            bool use_alpha)
{
	Image *img;
	size_t slot;

	ImageDataType type = get_image_metadata(filename, builtin_data, is_linear);

	thread_scoped_lock device_lock(device_mutex);

	/* Do we have a float? */
	if(type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4)
		is_float = true;

	/* No single channel and half textures on CUDA (Fermi) and no half on 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) {
		type = IMAGE_DATA_TYPE_BYTE4;
	}

	/* Fnd existing image. */
	for(slot = 0; slot < images[type].size(); slot++) {
		img = images[type][slot];
		if(img && image_equals(img,
		                       filename,
		                       builtin_data,
		                       interpolation,
		                       extension))
		{
			if(img->frame != frame) {
				img->frame = frame;
				img->need_load = true;
			}
			if(img->use_alpha != use_alpha) {
				img->use_alpha = use_alpha;
				img->need_load = true;
			}
			img->users++;
			return type_index_to_flattened_slot(slot, type);
		}
	}

	/* Find free slot. */
	for(slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			break;
	}

	if(slot == images[type].size()) {
		/* Max images limit reached. */
		if(images[type].size() == tex_num_images[type]) {
			printf("ImageManager::add_image: Reached %s image limit (%d), skipping '%s'\n",
			       name_from_type(type).c_str(), tex_num_images[type], filename.c_str());
			return -1;
		}

		images[type].resize(images[type].size() + 1);
	}

	/* Add new image. */
	img = new Image();
	img->filename = filename;
	img->builtin_data = builtin_data;
	img->need_load = true;
	img->animated = animated;
	img->frame = frame;
	img->interpolation = interpolation;
	img->extension = extension;
	img->users = 1;
	img->use_alpha = use_alpha;

	images[type][slot] = img;

	need_update = true;

	return type_index_to_flattened_slot(slot, type);
}
Пример #7
0
void ImageManager::device_pack_images(Device *device,
                                      DeviceScene *dscene,
                                      Progress& /*progess*/)
{
	/* For OpenCL, we pack all image textures into a single large texture, and
	 * do our own interpolation in the kernel. */
	size_t size = 0, offset = 0;
	ImageDataType type;

	int info_size = tex_num_images[IMAGE_DATA_TYPE_FLOAT4] + tex_num_images[IMAGE_DATA_TYPE_BYTE4]
	                + tex_num_images[IMAGE_DATA_TYPE_FLOAT] + tex_num_images[IMAGE_DATA_TYPE_BYTE];
	uint4 *info = dscene->tex_image_packed_info.resize(info_size*2);

	/* Byte4 Textures*/
	type = IMAGE_DATA_TYPE_BYTE4;

	for(size_t slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			continue;

		device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot];
		size += tex_img.size();
	}

	uchar4 *pixels_byte4 = dscene->tex_image_byte4_packed.resize(size);

	for(size_t slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			continue;

		device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot];

		uint8_t options = pack_image_options(type, slot);

		int index = type_index_to_flattened_slot(slot, type) * 2;
		info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options);
		info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0);

		memcpy(pixels_byte4+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
		offset += tex_img.size();
	}

	/* Float4 Textures*/
	type = IMAGE_DATA_TYPE_FLOAT4;
	size = 0, offset = 0;

	for(size_t slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			continue;

		device_vector<float4>& tex_img = dscene->tex_float4_image[slot];
		size += tex_img.size();
	}

	float4 *pixels_float4 = dscene->tex_image_float4_packed.resize(size);

	for(size_t slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			continue;

		device_vector<float4>& tex_img = dscene->tex_float4_image[slot];

		/* todo: support 3D textures, only CPU for now */

		uint8_t options = pack_image_options(type, slot);

		int index = type_index_to_flattened_slot(slot, type) * 2;
		info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options);
		info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0);

		memcpy(pixels_float4+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
		offset += tex_img.size();
	}

	/* Byte Textures*/
	type = IMAGE_DATA_TYPE_BYTE;
	size = 0, offset = 0;

	for(size_t slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			continue;

		device_vector<uchar>& tex_img = dscene->tex_byte_image[slot];
		size += tex_img.size();
	}

	uchar *pixels_byte = dscene->tex_image_byte_packed.resize(size);

	for(size_t slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			continue;

		device_vector<uchar>& tex_img = dscene->tex_byte_image[slot];

		uint8_t options = pack_image_options(type, slot);

		int index = type_index_to_flattened_slot(slot, type) * 2;
		info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options);
		info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0);

		memcpy(pixels_byte+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
		offset += tex_img.size();
	}

	/* Float Textures*/
	type = IMAGE_DATA_TYPE_FLOAT;
	size = 0, offset = 0;

	for(size_t slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			continue;

		device_vector<float>& tex_img = dscene->tex_float_image[slot];
		size += tex_img.size();
	}

	float *pixels_float = dscene->tex_image_float_packed.resize(size);

	for(size_t slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			continue;

		device_vector<float>& tex_img = dscene->tex_float_image[slot];

		/* todo: support 3D textures, only CPU for now */

		uint8_t options = pack_image_options(type, slot);

		int index = type_index_to_flattened_slot(slot, type) * 2;
		info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options);
		info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0);

		memcpy(pixels_float+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
		offset += tex_img.size();
	}

	if(dscene->tex_image_byte4_packed.size()) {
		if(dscene->tex_image_byte4_packed.device_pointer) {
			thread_scoped_lock device_lock(device_mutex);
			device->tex_free(dscene->tex_image_byte4_packed);
		}
		device->tex_alloc("__tex_image_byte4_packed", dscene->tex_image_byte4_packed);
	}
	if(dscene->tex_image_float4_packed.size()) {
		if(dscene->tex_image_float4_packed.device_pointer) {
			thread_scoped_lock device_lock(device_mutex);
			device->tex_free(dscene->tex_image_float4_packed);
		}
		device->tex_alloc("__tex_image_float4_packed", dscene->tex_image_float4_packed);
	}
	if(dscene->tex_image_byte_packed.size()) {
		if(dscene->tex_image_byte_packed.device_pointer) {
			thread_scoped_lock device_lock(device_mutex);
			device->tex_free(dscene->tex_image_byte_packed);
		}
		device->tex_alloc("__tex_image_byte_packed", dscene->tex_image_byte_packed);
	}
	if(dscene->tex_image_float_packed.size()) {
		if(dscene->tex_image_float_packed.device_pointer) {
			thread_scoped_lock device_lock(device_mutex);
			device->tex_free(dscene->tex_image_float_packed);
		}
		device->tex_alloc("__tex_image_float_packed", dscene->tex_image_float_packed);
	}
	if(dscene->tex_image_packed_info.size()) {
		if(dscene->tex_image_packed_info.device_pointer) {
			thread_scoped_lock device_lock(device_mutex);
			device->tex_free(dscene->tex_image_packed_info);
		}
		device->tex_alloc("__tex_image_packed_info", dscene->tex_image_packed_info);
	}
}
Пример #8
0
int ImageManager::add_image(const string& filename,
                            void *builtin_data,
                            bool animated,
                            float frame,
                            bool& is_float,
                            bool& is_linear,
                            InterpolationType interpolation,
                            ExtensionType extension,
                            bool use_alpha)
{
	Image *img;
	size_t slot;
	bool builtin_free_cache;

	ImageDataType type = get_image_metadata(filename, builtin_data, is_linear, builtin_free_cache);

	thread_scoped_lock device_lock(device_mutex);

	/* Check whether it's a float texture. */
	is_float = (type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4);

	/* No single channel and half textures on CUDA (Fermi) and no half on OpenCL, use available slots */
	if(!has_half_images) {
		if(type == IMAGE_DATA_TYPE_HALF4) {
			type = IMAGE_DATA_TYPE_FLOAT4;
		}
		else if(type == IMAGE_DATA_TYPE_HALF) {
			type = IMAGE_DATA_TYPE_FLOAT;
		}
	}

	if(cuda_fermi_limits) {
		if(type == IMAGE_DATA_TYPE_FLOAT) {
			type = IMAGE_DATA_TYPE_FLOAT4;
		}
		else if(type == IMAGE_DATA_TYPE_BYTE) {
			type = IMAGE_DATA_TYPE_BYTE4;
		}
	}

	/* Fnd existing image. */
	for(slot = 0; slot < images[type].size(); slot++) {
		img = images[type][slot];
		if(img && image_equals(img,
		                       filename,
		                       builtin_data,
		                       interpolation,
		                       extension,
		                       use_alpha))
		{
			if(img->frame != frame) {
				img->frame = frame;
				img->need_load = true;
			}
			if(img->use_alpha != use_alpha) {
				img->use_alpha = use_alpha;
				img->need_load = true;
			}
			img->users++;
			return type_index_to_flattened_slot(slot, type);
		}
	}

	/* Find free slot. */
	for(slot = 0; slot < images[type].size(); slot++) {
		if(!images[type][slot])
			break;
	}

	/* Count if we're over the limit */
	if(cuda_fermi_limits) {
		if(tex_num_images[IMAGE_DATA_TYPE_BYTE4] == TEX_NUM_BYTE4_CUDA
			|| tex_num_images[IMAGE_DATA_TYPE_FLOAT4] == TEX_NUM_FLOAT4_CUDA)
		{
			printf("ImageManager::add_image: Reached %s image limit (%d), skipping '%s'\n",
				name_from_type(type).c_str(), tex_num_images[type], filename.c_str());
			return -1;
		}
	}
	else {
		/* Very unlikely, since max_num_images is insanely big. But better safe than sorry. */
		int tex_count = 0;
		for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
			tex_count += tex_num_images[type];
		}
		if(tex_count > max_num_images) {
			printf("ImageManager::add_image: Reached image limit (%d), skipping '%s'\n",
				max_num_images, filename.c_str());
			return -1;
		}
	}

	if(slot == images[type].size()) {
		images[type].resize(images[type].size() + 1);
	}

	/* Add new image. */
	img = new Image();
	img->filename = filename;
	img->builtin_data = builtin_data;
	img->builtin_free_cache = builtin_free_cache;
	img->need_load = true;
	img->animated = animated;
	img->frame = frame;
	img->interpolation = interpolation;
	img->extension = extension;
	img->users = 1;
	img->use_alpha = use_alpha;

	images[type][slot] = img;

	++tex_num_images[type];

	need_update = true;

	return type_index_to_flattened_slot(slot, type);
}