From d6e30256ad7e2660db796b41cf8a7bf073aa6d09 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 4 May 2016 12:36:51 -0300 Subject: [PATCH] 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. --- core/image.cpp | 60 +++++++++++++++++++++++++ core/image.h | 1 + drivers/gles2/rasterizer_gles2.cpp | 19 +++++++- drivers/gles2/rasterizer_gles2.h | 4 ++ servers/visual/rasterizer.h | 2 + servers/visual/rasterizer_dummy.h | 2 + servers/visual/visual_server_raster.cpp | 5 +++ servers/visual/visual_server_raster.h | 4 +- servers/visual/visual_server_wrap_mt.h | 2 + servers/visual_server.cpp | 4 ++ servers/visual_server.h | 2 + 11 files changed, 103 insertions(+), 2 deletions(-) diff --git a/core/image.cpp b/core/image.cpp index 184ab70dc48..cb667c9b9fe 100644 --- a/core/image.cpp +++ b/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 new_img; + + int ofs = get_mipmap_offset(1); + + int new_size = data.size()-ofs; + new_img.resize(new_size); + + + { + DVector::Write w=new_img.write(); + DVector::Read r=data.read(); + + copymem(w.ptr(),&r[ofs],new_size); + } + + mipmaps--; + width/=2; + height/=2; + data=new_img; + + } else { + + DVector new_img; + + ERR_FAIL_COND( format>=FORMAT_INDEXED ); + int ps = get_format_pixel_size(format); + new_img.resize((width/2)*(height/2)*ps); + + { + DVector::Write w=new_img.write(); + DVector::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)) { diff --git a/core/image.h b/core/image.h index 8f8fff755e3..393b110a163 100644 --- a/core/image.h +++ b/core/image.h @@ -248,6 +248,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 */ diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 4b976c5b068..2d1bda0050b 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/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 *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) { diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index 0f70ceaa976..d74daf37d52 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/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 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); @@ -1334,6 +1336,8 @@ public: virtual String texture_get_path(RID p_texture) const; virtual void texture_debug_usage(List *r_info); + virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable); + GLuint _texture_get_name(RID p_tex); /* SHADER API */ diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 687a11f9476..3d4d026185c 100644 --- a/servers/visual/rasterizer.h +++ b/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 *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; diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h index efa843839aa..674c1659661 100644 --- a/servers/visual/rasterizer_dummy.h +++ b/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 *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); diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index ed7f8bea093..169659bac56 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -127,6 +127,11 @@ void VisualServerRaster::texture_debug_usage(List *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) { diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 4461bd899b1..b0a51bbd102 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -659,7 +659,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; @@ -675,6 +675,8 @@ public: virtual void texture_debug_usage(List *r_info); + virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable); + /* SHADER API */ diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index de8726179f6..6e9f27101e3 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/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 *r_info) { //pass directly, should lock the server anyway visual_server->texture_debug_usage(r_info); diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 17d5b16b9f8..5ac0e5b5d5d 100644 --- a/servers/visual_server.cpp +++ b/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); diff --git a/servers/visual_server.h b/servers/visual_server.h index 0d064e717db..e907239c2fd 100644 --- a/servers/visual_server.h +++ b/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;