From fb142ed6f8e98756eb134a6bbbb631f30ec91cc3 Mon Sep 17 00:00:00 2001 From: Relintai Date: Sun, 27 Aug 2023 22:19:07 +0200 Subject: [PATCH] Ported: Unbind texture slots when changing framebuffer Prevent bugs whereby texture still in use. - lawnjelly https://github.com/godotengine/godot/commit/5e197fd21ea836a632d97e27a3dd5ecfaa8405f8 --- .../gles2/rasterizer_canvas_base_gles2.cpp | 28 +++---- drivers/gles2/rasterizer_canvas_gles2.cpp | 22 ++--- drivers/gles2/rasterizer_gles2.cpp | 11 ++- drivers/gles2/rasterizer_scene_gles2.cpp | 84 +++++++++---------- drivers/gles2/rasterizer_storage_gles2.cpp | 65 ++++++++------ drivers/gles2/rasterizer_storage_gles2.h | 23 +++++ 6 files changed, 137 insertions(+), 96 deletions(-) diff --git a/drivers/gles2/rasterizer_canvas_base_gles2.cpp b/drivers/gles2/rasterizer_canvas_base_gles2.cpp index d9b0b26ae..be3f93dce 100644 --- a/drivers/gles2/rasterizer_canvas_base_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_base_gles2.cpp @@ -99,7 +99,7 @@ void RasterizerCanvasBaseGLES2::canvas_begin() { reset_canvas(); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); @@ -191,7 +191,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture state.current_tex = RID(); state.current_tex_ptr = nullptr; - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); } else { @@ -205,7 +205,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture texture->render_target->used_in_frame = true; } - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); glBindTexture(GL_TEXTURE_2D, texture->tex_id); state.current_tex = p_texture; @@ -217,7 +217,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture state.current_tex = RID(); state.current_tex_ptr = nullptr; - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); } @@ -230,7 +230,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture if (!normal_map) { state.current_normal = RID(); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, false); @@ -241,7 +241,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture normal_map = normal_map->get_ptr(); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); glBindTexture(GL_TEXTURE_2D, normal_map->tex_id); state.current_normal = p_normal_map; state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, true); @@ -249,7 +249,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture } else { state.current_normal = RID(); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, false); } @@ -272,7 +272,7 @@ void RasterizerCanvasBaseGLES2::draw_window_margins(int *black_margin, RID *blac draw_generic_textured_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h), Rect2(0, 0, (float)black_margin[MARGIN_LEFT] / sz.x, (float)(window_h) / sz.y)); } else if (black_margin[MARGIN_LEFT]) { - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); draw_generic_textured_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h), Rect2(0, 0, 1, 1)); @@ -284,7 +284,7 @@ void RasterizerCanvasBaseGLES2::draw_window_margins(int *black_margin, RID *blac draw_generic_textured_rect(Rect2(window_w - black_margin[MARGIN_RIGHT], 0, black_margin[MARGIN_RIGHT], window_h), Rect2(0, 0, (float)black_margin[MARGIN_RIGHT] / sz.x, (float)window_h / sz.y)); } else if (black_margin[MARGIN_RIGHT]) { - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); draw_generic_textured_rect(Rect2(window_w - black_margin[MARGIN_RIGHT], 0, black_margin[MARGIN_RIGHT], window_h), Rect2(0, 0, 1, 1)); @@ -298,7 +298,7 @@ void RasterizerCanvasBaseGLES2::draw_window_margins(int *black_margin, RID *blac Rect2(0, 0, (float)window_w / sz.x, (float)black_margin[MARGIN_TOP] / sz.y)); } else if (black_margin[MARGIN_TOP]) { - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); draw_generic_textured_rect(Rect2(0, 0, window_w, black_margin[MARGIN_TOP]), Rect2(0, 0, 1, 1)); @@ -312,7 +312,7 @@ void RasterizerCanvasBaseGLES2::draw_window_margins(int *black_margin, RID *blac Rect2(0, 0, (float)window_w / sz.x, (float)black_margin[MARGIN_BOTTOM] / sz.y)); } else if (black_margin[MARGIN_BOTTOM]) { - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); draw_generic_textured_rect(Rect2(0, window_h - black_margin[MARGIN_BOTTOM], window_w, black_margin[MARGIN_BOTTOM]), Rect2(0, 0, 1, 1)); @@ -364,7 +364,7 @@ void RasterizerCanvasBaseGLES2::_set_uniforms() { if (state.using_shadow) { RasterizerStorageGLES2::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(light->shadow_buffer); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); glBindTexture(GL_TEXTURE_2D, cls->distance); state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX, light->shadow_matrix_cache); state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR, light->shadow_color); @@ -402,7 +402,7 @@ void RasterizerCanvasBaseGLES2::reset_canvas() { // keeping this for now as there's nothing else that uses texture unit 2 // TODO ^ if (storage->frame.current_rt) { - // glActiveTexture(GL_TEXTURE0 + 2); + // WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + 2); // glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); } @@ -723,7 +723,7 @@ void RasterizerCanvasBaseGLES2::_copy_screen(const Rect2 &p_rect) { storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, !state.using_transparent_rt); glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->copy_screen_effect.fbo); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); storage->shaders.copy.bind(); diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 05434c983..cb1eb2d55 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -1229,7 +1229,7 @@ void RasterizerCanvasGLES2::canvas_render_items_implementation(Item *p_item_list state.current_normal = RID(); state.canvas_texscreen_used = false; - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); if (bdata.settings_use_batching) { @@ -1617,7 +1617,7 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta } if (skeleton) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); glBindTexture(GL_TEXTURE_2D, skeleton->tex_id); state.using_skeleton = true; } else { @@ -1652,7 +1652,7 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta } if (storage->frame.current_rt->copy_screen_effect.color) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); } } @@ -1672,7 +1672,7 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw(); for (int i = 0; i < tc; i++) { - glActiveTexture(GL_TEXTURE0 + i); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + i); RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second); @@ -1852,7 +1852,7 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta _set_uniforms(); state.canvas_shader.use_material((void *)material_ptr); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(light->texture); if (!t) { glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); @@ -1862,7 +1862,7 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta glBindTexture(t->target, t->tex_id); } - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); _legacy_canvas_item_render_commands(p_ci, nullptr, reclip, material_ptr); //redraw using light state.using_light = nullptr; @@ -1981,7 +1981,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI } if (skeleton) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); glBindTexture(GL_TEXTURE_2D, skeleton->tex_id); state.using_skeleton = true; } else { @@ -2017,7 +2017,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI } if (storage->frame.current_rt->copy_screen_effect.color) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); } } @@ -2037,7 +2037,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw(); for (int i = 0; i < tc; i++) { - glActiveTexture(GL_TEXTURE0 + i); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + i); RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second); @@ -2235,7 +2235,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI _set_uniforms(); state.canvas_shader.use_material((void *)material_ptr); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(light->texture); if (!t) { glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); @@ -2245,7 +2245,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI glBindTexture(t->target, t->tex_id); } - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); // redraw using light. // if there is no clip item, we can consider scissoring to the intersection area between the light and the item diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index eebb68e35..bf449371a 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -30,8 +30,8 @@ #include "rasterizer_gles2.h" -#include "core/os/os.h" #include "core/config/project_settings.h" +#include "core/os/os.h" #define _EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 #define _EXT_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 @@ -317,6 +317,9 @@ void RasterizerGLES2::set_current_render_target(RID p_render_target) { glViewport(0, 0, OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); } + + // Unbind texture slots. + storage->gl_wrapper.reset(); } void RasterizerGLES2::restore_render_target(bool p_3d_was_drawn) { @@ -379,7 +382,7 @@ void RasterizerGLES2::set_boot_image(const Ref &p_image, const Color &p_c } RasterizerStorageGLES2::Texture *t = storage->texture_owner.get(texture); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); glBindTexture(GL_TEXTURE_2D, t->tex_id); canvas->draw_generic_textured_rect(screenrect, Rect2(0, 0, 1, 1)); glBindTexture(GL_TEXTURE_2D, 0); @@ -409,7 +412,7 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re canvas->canvas_begin(); glDisable(GL_BLEND); glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); if (rt->external.fbo != 0) { glBindTexture(GL_TEXTURE_2D, rt->external.color); } else { @@ -438,7 +441,7 @@ void RasterizerGLES2::output_lens_distorted_to_screen(RID p_render_target, const glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); // output our texture - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, rt->color); canvas->draw_lens_distortion_rect(p_screen_rect, p_k1, p_k2, p_eye_center, p_oversample); diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 3aed4b799..52a959e8c 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -188,7 +188,7 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) { } // create a depth texture - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); if (storage->config.use_rgba_3d_shadows) { //maximum compatibility, renderbuffer and RGBA shadow @@ -608,7 +608,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance GLenum format = GL_RGB; GLenum type = GL_UNSIGNED_BYTE; - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth); glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_buffer_internalformat, size, size); @@ -671,7 +671,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst } } - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap); glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //use linear, no mipmaps so it does not read from what is being written to @@ -683,7 +683,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst } //do filtering //vdc cache - glActiveTexture(GL_TEXTURE1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, storage->resources.radical_inverse_vdc_cache_tex); // now render to the framebuffer, mipmap level for mipmap level @@ -699,12 +699,12 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst //blur while (size >= 1) { - glActiveTexture(GL_TEXTURE3); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, storage->resources.mipmap_blur_color); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, storage->resources.mipmap_blur_color, 0); glViewport(0, 0, size, size); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); for (int i = 0; i < 6; i++) { storage->bind_quad_array(); @@ -723,12 +723,12 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst } // restore ranges - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE3); //back to panorama + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE3); //back to panorama glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); @@ -1229,7 +1229,7 @@ void RasterizerSceneGLES2::_copy_texture_to_buffer(GLuint p_texture, GLuint p_bu glDepthFunc(GL_LEQUAL); glColorMask(1, 1, 1, 1); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, p_texture); glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); @@ -1342,12 +1342,12 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m state.scene_shader.set_custom_shader(p_material->shader->custom_code_id); if (p_material->shader->spatial.uses_screen_texture && storage->frame.current_rt) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); } if (p_material->shader->spatial.uses_depth_texture && storage->frame.current_rt) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); } @@ -1382,7 +1382,7 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m state.current_main_tex = 0; for (int i = 0; i < tc; i++) { - glActiveTexture(GL_TEXTURE0 + i); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + i); RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second); @@ -1496,7 +1496,7 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste if (p_skeleton) { if (!storage->config.use_skeleton_software) { //use float texture workflow - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); glBindTexture(GL_TEXTURE_2D, p_skeleton->tex_id); } else { //use transform buffer workflow @@ -1804,11 +1804,11 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { t->render_target->used_in_frame = true; } - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(t->target, t->tex_id); restore_tex = true; } else if (restore_tex) { - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, state.current_main_tex); restore_tex = false; } @@ -1866,7 +1866,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { } if (restore_tex) { - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, state.current_main_tex); restore_tex = false; } @@ -1916,7 +1916,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, p_light->light_ptr->directional_blend_splits); if (!state.render_no_shadows && p_light->light_ptr->shadow) { state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); if (storage->config.use_rgba_3d_shadows) { glBindTexture(GL_TEXTURE_2D, directional_shadow.color); } else { @@ -1931,7 +1931,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, true); if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) { state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); if (storage->config.use_rgba_3d_shadows) { glBindTexture(GL_TEXTURE_2D, shadow_atlas->color); } else { @@ -1945,7 +1945,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, true); if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) { state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); if (storage->config.use_rgba_3d_shadows) { glBindTexture(GL_TEXTURE_2D, shadow_atlas->color); } else { @@ -2233,7 +2233,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, bool use_radiance_map = false; if (!p_shadow && p_base_env) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); glBindTexture(GL_TEXTURE_CUBE_MAP, p_base_env); use_radiance_map = true; state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, true); //since prev unshaded is false, this needs to be true if exists @@ -2413,11 +2413,11 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, refprobe_1 != nullptr); state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, refprobe_2 != nullptr); if (refprobe_1 != nullptr && refprobe_1 != prev_refprobe_1) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_1->cubemap); } if (refprobe_2 != nullptr && refprobe_2 != prev_refprobe_2) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_2->cubemap); } rebind = true; @@ -2611,7 +2611,7 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const P tex = tex->get_ptr(); //resolve for proxies - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(tex->target, tex->tex_id); glDepthMask(GL_TRUE); @@ -2810,10 +2810,10 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - glActiveTexture(GL_TEXTURE1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); if (storage->frame.current_rt->mip_maps[0].color) { glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); @@ -2830,7 +2830,7 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p storage->_copy_screen(); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_DIR, Vector2(0, 1)); glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->mip_maps[0].sizes[0].fbo); // copy to base level @@ -2846,7 +2846,7 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p if (env && env->dof_blur_near_enabled) { //convert texture to RGBA format if not already if (!storage->frame.current_rt->used_dof_blur_near) { - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } @@ -2875,10 +2875,10 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - glActiveTexture(GL_TEXTURE1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); if (storage->frame.current_rt->mip_maps[0].color) { glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); } else { @@ -2905,7 +2905,7 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->mip_maps[0].sizes[0].fbo); // copy to base level @@ -2929,7 +2929,7 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p if (env && (env->dof_blur_near_enabled || env->dof_blur_far_enabled)) { //these needed to disable filtering, reenamble - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); if (storage->frame.current_rt->mip_maps[0].color) { glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); @@ -2982,7 +2982,7 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::GLOW_STRENGTH, env->glow_strength); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::LUMINANCE_CAP, env->glow_hdr_luminance_cap); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); if (storage->frame.current_rt->mip_maps[0].color) { glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); @@ -3007,7 +3007,7 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::LOD, storage->frame.current_rt->mip_maps[0].color ? float(i) : 0.0); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::GLOW_STRENGTH, env->glow_strength); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); if (storage->frame.current_rt->mip_maps[0].color) { glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[1].color); @@ -3029,7 +3029,7 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); } - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); if (storage->frame.current_rt->mip_maps[0].color) { glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); } else { @@ -3068,7 +3068,7 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p } } } - glActiveTexture(GL_TEXTURE2); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); } else { state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_MULTI_TEXTURE_GLOW, true); @@ -3076,7 +3076,7 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p for (int i = 0; i < (max_glow_level + 1); i++) { if (glow_mask & (1 << i)) { active_glow_level++; - glActiveTexture(GL_TEXTURE1 + active_glow_level); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1 + active_glow_level); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[i + 1].color); if (active_glow_level == 1) { state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL1, true); @@ -3115,7 +3115,7 @@ void RasterizerSceneGLES2::_post_process(Environment3D *env, const Projection &p RasterizerStorageGLES2::Texture *tex = storage->texture_owner.getornull(env->color_correction); if (tex) { state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_COLOR_CORRECTION, true); - glActiveTexture(GL_TEXTURE1); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE1); glBindTexture(tex->target, tex->tex_id); } } @@ -3473,7 +3473,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const #ifdef GLES2_SHADOW_ATLAS_DEBUG_VIEW ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); if (shadow_atlas) { - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); glViewport(0, 0, storage->frame.current_rt->width / 4, storage->frame.current_rt->height / 4); @@ -3492,7 +3492,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const #ifdef GLES2_SHADOW_DIRECTIONAL_DEBUG_VIEW if (true) { - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); glViewport(0, 0, storage->frame.current_rt->width / 4, storage->frame.current_rt->height / 4); @@ -3740,7 +3740,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo); state.cube_to_dp_shader.bind(); - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, shadow_cubemaps[current_cubemap].cubemap); glDisable(GL_CULL_FACE); @@ -3923,7 +3923,7 @@ void RasterizerSceneGLES2::initialize() { int cube_size = max_shadow_cubemap_sampler_size; - glActiveTexture(GL_TEXTURE0); + WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0); while (cube_size >= 32) { ShadowCubeMap cube; diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 1993162bc..e6b40b732 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -120,6 +120,20 @@ PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT #define GL_MAX_SAMPLES 0x8D57 #endif //!GLES_OVER_GL +void RasterizerStorageGLES2::GLWrapper::initialize(int p_max_texture_image_units) { + texture_unit_table.create(p_max_texture_image_units); +} + +void RasterizerStorageGLES2::GLWrapper::reset() { + for (uint32_t i = 0; i < texture_units_bound.size(); i++) { + ::glActiveTexture(GL_TEXTURE0 + texture_units_bound[i]); + glBindTexture(GL_TEXTURE_2D, 0); + } + + texture_units_bound.clear(); + texture_unit_table.blank(); +} + void RasterizerStorageGLES2::bind_quad_array() const { glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, nullptr); @@ -599,7 +613,7 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_ texture->compressed = compressed; } - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); if (p_type == RS::TEXTURE_TYPE_EXTERNAL) { @@ -669,7 +683,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p PoolVector::Read read = img->get_data().read(); ERR_FAIL_COND(!read.ptr()); - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); texture->ignore_mipmaps = compressed && !img->has_mipmaps(); @@ -798,7 +812,7 @@ Ref RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer) data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers PoolVector::Write wb = data.write(); - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); @@ -860,7 +874,7 @@ Ref RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer) glDisable(GL_BLEND); glDepthFunc(GL_LEQUAL); glColorMask(1, 1, 1, 1); - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture->tex_id); glViewport(0, 0, texture->alloc_width, texture->alloc_height); @@ -902,7 +916,7 @@ void RasterizerStorageGLES2::texture_set_flags(RID p_texture, uint32_t p_flags) texture->flags = p_flags; - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); if (((texture->flags & RS::TEXTURE_FLAG_REPEAT) || (texture->flags & RS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) { @@ -990,7 +1004,7 @@ void RasterizerStorageGLES2::texture_bind(RID p_texture, uint32_t p_texture_no) ERR_FAIL_COND(!texture); - glActiveTexture(GL_TEXTURE0 + p_texture_no); + gl_wrapper.gl_active_texture(GL_TEXTURE0 + p_texture_no); glBindTexture(texture->target, texture->tex_id); } @@ -1180,7 +1194,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra } } - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -1188,7 +1202,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //need this for proper sampling - glActiveTexture(GL_TEXTURE1); + gl_wrapper.gl_active_texture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, resources.radical_inverse_vdc_cache_tex); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -1197,7 +1211,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // New cubemap that will hold the mipmaps with different roughness values - glActiveTexture(GL_TEXTURE2); + gl_wrapper.gl_active_texture(GL_TEXTURE2); glGenTextures(1, &sky->radiance); glBindTexture(GL_TEXTURE_CUBE_MAP, sky->radiance); @@ -1237,7 +1251,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra // third, render to the framebuffer using separate textures, then copy to mipmaps while (size >= 1) { //make framebuffer size the texture size, need to use a separate texture for compatibility - glActiveTexture(GL_TEXTURE3); + gl_wrapper.gl_active_texture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, resources.mipmap_blur_color); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resources.mipmap_blur_color, 0); @@ -1251,7 +1265,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glViewport(0, 0, size, size); bind_quad_array(); - glActiveTexture(GL_TEXTURE2); //back to panorama + gl_wrapper.gl_active_texture(GL_TEXTURE2); //back to panorama for (int i = 0; i < 6; i++) { shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i); @@ -1277,7 +1291,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, false); // restore ranges - glActiveTexture(GL_TEXTURE2); //back to panorama + gl_wrapper.gl_active_texture(GL_TEXTURE2); //back to panorama glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1285,18 +1299,18 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE3); //back to panorama + gl_wrapper.gl_active_texture(GL_TEXTURE3); //back to panorama glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE1); + gl_wrapper.gl_active_texture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); //reset flags on Sky Texture that may have changed texture_set_flags(sky->panorama, texture->flags); // Framebuffer did its job. thank mr framebuffer - glActiveTexture(GL_TEXTURE0); //back to panorama + gl_wrapper.gl_active_texture(GL_TEXTURE0); //back to panorama glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); } @@ -3653,7 +3667,7 @@ void RasterizerStorageGLES2::skeleton_allocate(RID p_skeleton, int p_bones, bool skeleton->use_2d = p_2d_skeleton; if (!config.use_skeleton_software) { - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, skeleton->tex_id); #ifdef GLES_OVER_GL @@ -4173,7 +4187,7 @@ void RasterizerStorageGLES2::update_dirty_skeletons() { return; } - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); while (skeleton_update_list.first()) { Skeleton *skeleton = skeleton_update_list.first()->self(); @@ -5444,7 +5458,7 @@ RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) { cls->size = p_width; cls->height = 16; - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glGenFramebuffers(1, &cls->fbo); glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); @@ -6134,6 +6148,7 @@ void RasterizerStorageGLES2::initialize() { glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &config.max_vertex_texture_image_units); glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units); + gl_wrapper.initialize(config.max_texture_image_units); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size); glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &config.max_cubemap_texture_size); glGetIntegerv(GL_MAX_VIEWPORT_DIMS, config.max_viewport_dimensions); @@ -6187,7 +6202,7 @@ void RasterizerStorageGLES2::initialize() { for (int i = 0; i < 8 * 8 * 3; i++) { whitetexdata[i] = 255; } - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, resources.white_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata); glGenerateMipmap(GL_TEXTURE_2D); @@ -6199,7 +6214,7 @@ void RasterizerStorageGLES2::initialize() { for (int i = 0; i < 8 * 8 * 3; i++) { blacktexdata[i] = 0; } - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, resources.black_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, blacktexdata); glGenerateMipmap(GL_TEXTURE_2D); @@ -6211,7 +6226,7 @@ void RasterizerStorageGLES2::initialize() { for (int i = 0; i < 8 * 8 * 4; i++) { transparenttexdata[i] = 0; } - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, resources.transparent_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, transparenttexdata); glGenerateMipmap(GL_TEXTURE_2D); @@ -6225,7 +6240,7 @@ void RasterizerStorageGLES2::initialize() { normaltexdata[i + 1] = 128; normaltexdata[i + 2] = 255; } - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, resources.normal_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, normaltexdata); glGenerateMipmap(GL_TEXTURE_2D); @@ -6239,7 +6254,7 @@ void RasterizerStorageGLES2::initialize() { anisotexdata[i + 1] = 128; anisotexdata[i + 2] = 0; } - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, resources.aniso_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata); glGenerateMipmap(GL_TEXTURE_2D); @@ -6262,7 +6277,7 @@ void RasterizerStorageGLES2::initialize() { if (true /*||config.float_texture_supported*/) { //uint8 is similar and works everywhere glGenTextures(1, &resources.radical_inverse_vdc_cache_tex); - glActiveTexture(GL_TEXTURE0); + gl_wrapper.gl_active_texture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, resources.radical_inverse_vdc_cache_tex); uint8_t radical_inverse[512]; diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index 42e2905fe..d5d073974 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -30,6 +30,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "core/containers/bitfield_dynamic.h" #include "core/containers/pool_vector.h" #include "core/containers/self_list.h" #include "drivers/gles_common/rasterizer_asserts.h" @@ -44,6 +45,7 @@ class RasterizerCanvasGLES2; class RasterizerSceneGLES2; +#define WRAPPED_GL_ACTIVE_TEXTURE storage->gl_wrapper.gl_active_texture class RasterizerStorageGLES2 : public RasterizerStorage { public: RasterizerCanvasGLES2 *canvas; @@ -1219,6 +1221,27 @@ public: } frame; + struct GLWrapper { + mutable BitFieldDynamic texture_unit_table; + mutable LocalVector texture_units_bound; + + void gl_active_texture(GLenum p_texture) const { + ::glActiveTexture(p_texture); + + p_texture -= GL_TEXTURE0; + + // Check for below zero and above max in one check. + ERR_FAIL_COND((unsigned int)p_texture >= texture_unit_table.get_num_bits()); + + // Set if the first occurrence in the table. + if (texture_unit_table.check_and_set(p_texture)) { + texture_units_bound.push_back(p_texture); + } + } + void initialize(int p_max_texture_image_units); + void reset(); + } gl_wrapper; + void initialize(); void finalize();