Exemple #1
0
/** Run a couple of tests with the given base texture size */
static int test_size(GLuint basew, GLuint baseh)
{
	int lvls, lvl;
	GLuint w = basew;
	GLuint h = baseh;

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	teximage2d(0, w, h, testnr);
	if (!cell(testnr, 0, basew, baseh, testnr,
	          "Nearest filtering, base size %ix%i", basew, baseh))
		return 0;
	testnr++;

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
	for(lvls = 0; w >= 1 || h >= 1; lvls++, w >>= 1, h >>= 1) {
		if (!w)
			w = 1;
		if (!h)
			h = 1;

		teximage2d(lvls, w, h, testnr+lvls);
	}

	for(lvl = 0; lvl < lvls; ++lvl) {
		if (!cell(testnr+lvl, lvl, basew, baseh, testnr+lvl,
		          "Mip filtering, base size %ix%i, level %i",
		          basew, baseh, lvl))
			return 0;
	}
	testnr += lvls;

	return 1;
}
//this function currently assumes that the new texture has the same size as the old
int r1_opengl_texture_manager_class::set_texture_image(r1_texture_handle handle, i4_image_class * im)
{
	w32 tid=registered_tnames[handle].id;
	i4_image_class * memim;

	for (int i=0; i<memory_images.size(); i++)
	{
		if (memory_images[i].id==tid)
		{
			delete memory_images[i].image;
			memory_images[i].image=im->copy(); //replace saved memory image with new copy

			sw32 act_w=0,act_h=0;
			r1_miplevel_t * mip=get_texture(handle,0,max_texture_dimention,act_w,act_h);
			used_node * u=(used_node *) mip->vram_handle;
			float b1,b2;
			select_texture(u,b1,b2);
			u->data=im->data;
			teximage2d(u);
			u->data=0;
			return i4_T;
		}
	}
	return i4_F;
}
// bind all textures respresented in finished_array
void r1_opengl_texture_manager_class::next_frame()
{
	r1_texture_manager_class::next_frame();

	if (!finished_array.size())
	{
		return;
	}

	array_lock.lock();
	i4_image_class * im=NULL;

	// get texture names
	GLuint * texnames = (GLuint *)I4_MALLOC(finished_array.size() * sizeof(GLuint),"failure calling i4_malloc");
	glGenTextures(finished_array.size(), texnames);

	for (sw32 i=0; i<finished_array.size(); i++)
	{
		used_node * u = finished_array[i];

		// put it in vram
		u->mip->vram_handle = u;
		u->mip->flags &= (~R1_MIPLEVEL_IS_LOADING);

		if (u->mip->last_frame_used != -1)
		{
			u->mip->last_frame_used = frame_count;
		}

		tex_no_heap->update_usage((r1_tex_no_heap_used_node *)u);

		if (u->mip->flags & R1_MIPLEVEL_JPG_ALREADY_LOADED)
		{
			//Case 2: The file was already in mem, just copy data
			for(int x=0; x<image_list.size(); x++)
			{
				if (image_list[x].id==u->mip->entry->id)
				{
					im=image_list[x].image;
					image_list[x].usage=30;
					image_list[x].unlock();
				}
				//image_list[x].usage--;
				//if (image_list[x].usage==0) image_list[x].usage=1;
			}
			I4_ASSERT(im,"Internal error in texture loader: Image deleted during access.");
			if (u->data)
			{
				delete u->data;
			}
			u->data=0;
			u->data=new w8[u->mip->width*u->mip->height*2];
			size_image_to_texture(u->data,im,
								  u->mip->width,u->mip->height,2,
								  u->mip->entry->is_transparent(),
								  u->mip->entry->is_alphatexture());
			u->mip->flags &=~R1_MIPLEVEL_JPG_ALREADY_LOADED;
		}


		// assign the texture handle, bind it
		u->gltexname = texnames[i];
		glBindTexture(GL_TEXTURE_2D, u->gltexname);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		teximage2d(u);

		delete u->data;
		u->data = 0;
		no_of_textures_loaded--;

	}

	i4_free(texnames);

	finished_array.clear();

	array_lock.unlock();

	if (tex_no_heap->needs_cleanup)
	{
		tex_no_heap->free_really_old();
	}

	bytes_loaded = 0;
	//no_of_textures_loaded = 0;
}
i4_bool r1_opengl_texture_manager_class::immediate_mip_load(r1_mip_load_info * load_info)
{
	if (no_of_textures_loaded > 0)
	{
		if (load_info->dest_mip->last_frame_used != -1)
		{
			load_info->error = R1_MIP_LOAD_BUSY;
			return i4_F;
		}
	}

	r1_miplevel_t * mip = load_info->dest_mip;

	used_node * new_used = make_new_used_node(load_info);
	if (!new_used)
	{
		return i4_F;
	}
	new_used->async_fp=0;
	new_used->mip=0;
	new_used->data = (w8 *) new w8[(mip->width*mip->height*2) ]; //(w8 *)i4_malloc(mip->width * mip->height * 2,"failure calling i4_malloc");

	if (load_info->src_file)
	{
		//for opengl, we currently use only this case, since we support only 16 bit color depth
		//This is for loading data from the tex_cache only, where the data format
		//is always known.
		//Unfortunatelly, the above statement is just plain wrong... This
		//code is also used to load up the lowest miplevel (distant terrain)
		//texture. Therefore, we convert here

		if (load_info->flags & R1_MIPFLAGS_SRC32)
		{
			w32 co=0,r=0,g=0,b=0;
			w16 * tex=(w16 *)(new_used->data);
			const i4_pal * p=i4_pal_man.default_no_alpha_32();
			for (int i=0; i<mip->width*mip->height; i++)
			{
				//The order here is a bit strange (argb backwards).
				//I don't know why it should be like this (testing shows it's right on my system,
				//but it might as well be hardware dependent)
				b=load_info->src_file->read_8();
				g=load_info->src_file->read_8();
				r=load_info->src_file->read_8();
				load_info->src_file->read_8();
				co=p->convert(r<<16|g<<8|b,&regular_format);
				tex[i]=(w16)co;
			}
		}
		else
		{
			load_info->src_file->read(new_used->data,mip->width * mip->height * 2);
		}
	}
	else
	{
		load_texture_from_file(load_info->texture_name,
							   mip->entry->id,new_used->data,
							   mip->width, mip->height,
							   mip->width*2, 2, mip->entry->is_transparent(),
							   mip->entry->is_alphatexture());
	}

	mip->vram_handle = new_used;

	if (mip->last_frame_used != -1)
	{
		mip->last_frame_used = frame_count;
	}

	new_used->mip = mip;
	new_used->async_fp = 0;

	glGenTextures(1,&new_used->gltexname);
	glBindTexture(GL_TEXTURE_2D, new_used->gltexname);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	teximage2d(new_used);

	//i4_free(new_used->data);
	delete [] new_used->data;
	new_used->data = 0;

	//bytes_loaded += mip->width * mip->height * 2;
	//no_of_textures_loaded++;

	return i4_T;
}