소스 검색

ability to shrink all images x2 on load

this is for extreme cases when running on devices with very low video
memory, so you can still retain compatibility.
Juan Linietsky 9 년 전
부모
커밋
89d87294db

+ 60 - 0
core/image.cpp

@@ -901,6 +901,66 @@ static void _generate_po2_mipmap(const uint8_t* p_src, uint8_t* p_dst, uint32_t
 }
 
 
+void Image::shrink_x2() {
+
+	ERR_FAIL_COND(format==FORMAT_INDEXED || format==FORMAT_INDEXED_ALPHA);
+	ERR_FAIL_COND( data.size()==0 );
+
+
+
+	if (mipmaps) {
+
+		//just use the lower mipmap as base and copy all
+		DVector<uint8_t> new_img;
+
+		int ofs = get_mipmap_offset(1);
+
+		int new_size = data.size()-ofs;
+		new_img.resize(new_size);
+
+
+		{
+			DVector<uint8_t>::Write w=new_img.write();
+			DVector<uint8_t>::Read r=data.read();
+
+			copymem(w.ptr(),&r[ofs],new_size);
+		}
+
+		mipmaps--;
+		width/=2;
+		height/=2;
+		data=new_img;
+
+	} else {
+
+		DVector<uint8_t> new_img;
+
+		ERR_FAIL_COND( format>=FORMAT_INDEXED );
+		int ps = get_format_pixel_size(format);
+		new_img.resize((width/2)*(height/2)*ps);
+
+		{
+			DVector<uint8_t>::Write w=new_img.write();
+			DVector<uint8_t>::Read r=data.read();
+
+			switch(format) {
+
+				case FORMAT_GRAYSCALE:
+				case FORMAT_INTENSITY: _generate_po2_mipmap<1>(r.ptr(), w.ptr(), width,height); break;
+				case FORMAT_GRAYSCALE_ALPHA: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width,height); break;
+				case FORMAT_RGB: _generate_po2_mipmap<3>(r.ptr(), w.ptr(), width,height); break;
+				case FORMAT_RGBA: _generate_po2_mipmap<4>(r.ptr(), w.ptr(), width,height); break;
+				default: {}
+			}
+		}
+
+		width/=2;
+		height/=2;
+		data=new_img;
+
+	}
+}
+
 Error Image::generate_mipmaps(int p_mipmaps,bool p_keep_existing)  {
 
 	if (!_can_modify(format)) {

+ 1 - 0
core/image.h

@@ -249,6 +249,7 @@ public:
 	void resize_to_po2(bool p_square=false);
 	void resize( int p_width, int p_height, Interpolation p_interpolation=INTERPOLATE_BILINEAR );
 	Image resized( int p_width, int p_height, int p_interpolation=INTERPOLATE_BILINEAR );
+	void shrink_x2();
 	/**
 	 * Crop the image to a specific size, if larger, then the image is filled by black
 	 */

+ 18 - 1
drivers/gles2/rasterizer_gles2.cpp

@@ -921,6 +921,11 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I
 		texture->alloc_height = texture->height;
 	};
 
+	if (shrink_textures_x2) {
+		texture->alloc_height = MAX(1,texture->alloc_height/2);
+		texture->alloc_width = MAX(1,texture->alloc_width/2);
+	}
+
 
 	texture->gl_components_cache=components;
 	texture->gl_format_cache=format;
@@ -970,8 +975,15 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
 
 	if (texture->alloc_width != img.get_width() || texture->alloc_height != img.get_height()) {
 
-		if (img.get_format() <= Image::FORMAT_INDEXED_ALPHA)
+
+		if (texture->alloc_width == img.get_width()/2 && texture->alloc_height == img.get_height()/2) {
+
+			img.shrink_x2();
+		} else if (img.get_format() <= Image::FORMAT_INDEXED_ALPHA) {
+
 			img.resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR);
+
+		}
 	};
 
 
@@ -1452,6 +1464,11 @@ void RasterizerGLES2::texture_debug_usage(List<VS::TextureInfo> *r_info){
 
 }
 
+void RasterizerGLES2::texture_set_shrink_all_x2_on_set_data(bool p_enable) {
+
+	shrink_textures_x2=p_enable;
+}
+
 /* SHADER API */
 
 RID RasterizerGLES2::shader_create(VS::ShaderMode p_mode) {

+ 4 - 0
drivers/gles2/rasterizer_gles2.h

@@ -108,6 +108,8 @@ class RasterizerGLES2 : public Rasterizer {
 	bool use_half_float;
 	bool low_memory_2d;
 
+	bool shrink_textures_x2;
+
 	Vector<float> skel_default;
 
 	Image _get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,GLenum& r_gl_internal_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed);
@@ -1336,6 +1338,8 @@ public:
 	virtual String texture_get_path(RID p_texture) const;
 	virtual void texture_debug_usage(List<VS::TextureInfo> *r_info);
 
+	virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable);
+
 	GLuint _texture_get_name(RID p_tex);
 
 	/* SHADER API */

+ 2 - 0
servers/visual/rasterizer.h

@@ -196,6 +196,8 @@ public:
 	virtual String texture_get_path(RID p_texture) const=0;
 	virtual void texture_debug_usage(List<VS::TextureInfo> *r_info)=0;
 
+	virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable)=0;
+
 	/* SHADER API */
 
 	virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_MATERIAL)=0;

+ 2 - 0
servers/visual/rasterizer_dummy.h

@@ -415,6 +415,8 @@ public:
 	virtual String texture_get_path(RID p_texture) const { return String(); }
 	virtual void texture_debug_usage(List<VS::TextureInfo> *r_info) {}
 
+	virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable) {}
+
 	/* SHADER API */
 
 	virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_MATERIAL);

+ 5 - 0
servers/visual/visual_server_raster.cpp

@@ -127,6 +127,11 @@ void VisualServerRaster::texture_debug_usage(List<TextureInfo> *r_info){
 	rasterizer->texture_debug_usage(r_info);
 }
 
+void VisualServerRaster::texture_set_shrink_all_x2_on_set_data(bool p_enable) {
+
+	rasterizer->texture_set_shrink_all_x2_on_set_data(p_enable);
+}
+
 /* SHADER API */
 
 RID VisualServerRaster::shader_create(ShaderMode p_mode) {

+ 3 - 1
servers/visual/visual_server_raster.h

@@ -657,7 +657,7 @@ public:
 
 	virtual RID texture_create();
 	virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=TEXTURE_FLAGS_DEFAULT);
-	virtual void texture_set_data(RID p_texture,const Image& p_image,CubeMapSide p_cube_side=CUBEMAP_LEFT);
+	virtual void texture_set_data(RID p_texture,const Image& p_image,CubeMapSide p_cube_side=CUBEMAP_LEFT);	
 	virtual Image texture_get_data(RID p_texture,CubeMapSide p_cube_side=CUBEMAP_LEFT) const;
 	virtual void texture_set_flags(RID p_texture,uint32_t p_flags) ;
 	virtual uint32_t texture_get_flags(RID p_texture) const;
@@ -673,6 +673,8 @@ public:
 
 	virtual void texture_debug_usage(List<TextureInfo> *r_info);
 
+	virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable);
+
 
 	/* SHADER API */
 

+ 2 - 0
servers/visual/visual_server_wrap_mt.h

@@ -101,6 +101,8 @@ public:
 	FUNC2(texture_set_path,RID,const String&);
 	FUNC1RC(String,texture_get_path,RID);
 
+	FUNC1(texture_set_shrink_all_x2_on_set_data,bool);
+
 	virtual void texture_debug_usage(List<TextureInfo> *r_info) {
 		//pass directly, should lock the server anyway
 		visual_server->texture_debug_usage(r_info);

+ 4 - 0
servers/visual_server.cpp

@@ -355,8 +355,12 @@ void VisualServer::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("texture_get_flags"),&VisualServer::texture_get_flags );
 	ObjectTypeDB::bind_method(_MD("texture_get_width"),&VisualServer::texture_get_width );
 	ObjectTypeDB::bind_method(_MD("texture_get_height"),&VisualServer::texture_get_height );
+
+	ObjectTypeDB::bind_method(_MD("texture_set_shrink_all_x2_on_set_data","shrink"),&VisualServer::texture_set_shrink_all_x2_on_set_data );
+
 #ifndef _3D_DISABLED
 
+
 	ObjectTypeDB::bind_method(_MD("shader_create","mode"),&VisualServer::shader_create,DEFVAL(SHADER_MATERIAL));
 	ObjectTypeDB::bind_method(_MD("shader_set_mode","shader","mode"),&VisualServer::shader_set_mode);
 

+ 2 - 0
servers/visual_server.h

@@ -138,6 +138,8 @@ public:
 	virtual void texture_set_path(RID p_texture,const String& p_path)=0;
 	virtual String texture_get_path(RID p_texture) const=0;
 
+	virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable)=0;
+
 	struct TextureInfo {
 		RID texture;
 		Size2 size;