From 6eb742d49f5d60fe8b61d5ac4ae72703764c6f67 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 10 Jan 2016 21:45:11 -0300 Subject: [PATCH] -Make a rare corner case where disabling/reenabling mipmaps causes invalid texture state. Fixes #3102 --- drivers/gles2/rasterizer_gles2.cpp | 13 ++++- drivers/gles2/rasterizer_gles2.h | 3 ++ scene/gui/tabs.cpp | 84 ++++++++++++++++++++++++++++++ scene/gui/tabs.h | 6 +++ tools/editor/editor_node.cpp | 2 + 5 files changed, 106 insertions(+), 2 deletions(-) diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 1f3b3433f98..58d5c307f06 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -929,6 +929,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I texture->compressed=compressed; texture->has_alpha=false; //by default it doesn't have alpha unless something with alpha is blitteds texture->data_size=0; + texture->mipmaps=0; glActiveTexture(GL_TEXTURE0); @@ -1086,6 +1087,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu glGenerateMipmap(texture->target); } + texture->mipmaps=mipmaps; @@ -1269,11 +1271,14 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { p_flags&=VS::TEXTURE_FLAG_FILTER;//can change only filter } + bool had_mipmaps = texture->flags&VS::TEXTURE_FLAG_MIPMAPS; + glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; texture->flags=p_flags|cube; // can't remove a cube from being a cube + bool force_clamp_to_edge = !(p_flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); if (!force_clamp_to_edge && (texture->flags&VS::TEXTURE_FLAG_REPEAT || texture->flags&VS::TEXTURE_FLAG_MIRRORED_REPEAT) && texture->target != GL_TEXTURE_CUBE_MAP) { @@ -1304,9 +1309,13 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { } } - if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) + if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) { + if (!had_mipmaps && texture->mipmaps==1) { + glGenerateMipmap(texture->target); + } glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR); - else{ + + } else{ if (texture->flags&VS::TEXTURE_FLAG_FILTER) { glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); } else { diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index f3edc288617..0f70ceaa976 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -138,6 +138,8 @@ class RasterizerGLES2 : public Rasterizer { StringName reloader_func; Image image[6]; + int mipmaps; + bool active; GLuint tex_id; @@ -159,6 +161,7 @@ class RasterizerGLES2 : public Rasterizer { compressed=false; total_data_size=0; target=GL_TEXTURE_2D; + mipmaps=0; reloader=0; } diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index 14cd0bee8e5..bb64a572128 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -266,6 +266,7 @@ void Tabs::_notification(int p_what) { int label_valign_fg = get_constant("label_valign_fg"); int label_valign_bg = get_constant("label_valign_bg"); + int w=0; int mw = 0; @@ -277,12 +278,16 @@ void Tabs::_notification(int p_what) { for(int i=0;i tex = tabs[i].icon; if (tex.is_valid()) { if (tabs[i].text!="") mw+=get_constant("hseparation"); } + + tabs[i].ofs_cache=mw; + mw+=font->get_string_size(tabs[i].text).width; if (current==i) mw+=tab_fg->get_minimum_size().width; @@ -303,6 +308,9 @@ void Tabs::_notification(int p_what) { bms.width+=get_constant("hseparation"); mw+=bms.width; } + + + } } @@ -758,6 +766,79 @@ Tabs::TabAlign Tabs::get_tab_align() const { } +void Tabs::ensure_tab_visible(int p_idx) { + + if (!is_inside_tree()) + return; + + ERR_FAIL_INDEX(p_idx,tabs.size()); + + if (p_idx tab_bg = get_stylebox("tab_bg"); + Ref tab_fg = get_stylebox("tab_fg"); + Ref font = get_font("font"); + + Ref incr = get_icon("increment"); + Ref decr = get_icon("decrement"); + + int limit=get_size().width-incr->get_width()-decr->get_width(); + + + + int x=0; + for(int i=0;i tex = tabs[i].icon; + if (tex.is_valid()) { + if (tabs[i].text!="") + x+=get_constant("hseparation"); + + } + + tabs[i].x_cache=x; + + x+=font->get_string_size(tabs[i].text).width; + if (current==i) + x+=tab_fg->get_minimum_size().width; + else + x+=tab_bg->get_minimum_size().width; + + if (tabs[i].right_button.is_valid()) { + Ref rb=tabs[i].right_button; + Size2 bms = rb->get_size();//+get_stylebox("button")->get_minimum_size(); + bms.width+=get_constant("hseparation"); + + x+=bms.width; + } + + if (tabs[i].close_button.is_valid()) { + Ref cb=tabs[i].close_button; + Size2 bms = cb->get_size();//+get_stylebox("button")->get_minimum_size(); + bms.width+=get_constant("hseparation"); + x+=bms.width; + } + + tabs[i].x_size_cache=x-tabs[i].x_cache; + + + + } + + while(offset icon; int ofs_cache; int size_cache; + int x_cache; + int x_size_cache; + Ref right_button; Rect2 rb_rect; Ref close_button; Rect2 cb_rect; + }; @@ -119,6 +123,8 @@ public: void clear_tabs(); + void ensure_tab_visible(int p_idx); + Size2 get_minimum_size() const; Tabs(); diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 462153a1834..d7708fcefda 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -4723,11 +4723,13 @@ void EditorNode::_scene_tab_changed(int p_tab) { editor_data.get_undo_redo().add_do_method(this,"set_current_version",unsaved?saved_version:0); editor_data.get_undo_redo().add_do_method(this,"set_current_scene",p_tab); editor_data.get_undo_redo().add_do_method(scene_tabs,"set_current_tab",p_tab); + editor_data.get_undo_redo().add_do_method(scene_tabs,"ensure_tab_visible",p_tab); editor_data.get_undo_redo().add_do_method(this,"set_current_version",next_scene_version==0?editor_data.get_undo_redo().get_version()+1:next_scene_version); editor_data.get_undo_redo().add_undo_method(this,"set_current_version",next_scene_version); editor_data.get_undo_redo().add_undo_method(this,"set_current_scene",editor_data.get_edited_scene()); editor_data.get_undo_redo().add_undo_method(scene_tabs,"set_current_tab",editor_data.get_edited_scene()); + editor_data.get_undo_redo().add_undo_method(scene_tabs,"ensure_tab_visible",p_tab,editor_data.get_edited_scene()); editor_data.get_undo_redo().add_undo_method(this,"set_current_version",saved_version); editor_data.get_undo_redo().commit_action();