diff options
Diffstat (limited to 'drivers/gles3/storage')
-rw-r--r-- | drivers/gles3/storage/config.cpp | 68 | ||||
-rw-r--r-- | drivers/gles3/storage/config.h | 25 | ||||
-rw-r--r-- | drivers/gles3/storage/material_storage.cpp | 22 | ||||
-rw-r--r-- | drivers/gles3/storage/material_storage.h | 28 | ||||
-rw-r--r-- | drivers/gles3/storage/texture_storage.cpp | 450 | ||||
-rw-r--r-- | drivers/gles3/storage/texture_storage.h | 93 |
6 files changed, 209 insertions, 477 deletions
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp index 49a2a79cb2..f2809734a9 100644 --- a/drivers/gles3/storage/config.cpp +++ b/drivers/gles3/storage/config.cpp @@ -55,82 +55,34 @@ Config::Config() { } } - keep_original_textures = true; // false - depth_internalformat = GL_DEPTH_COMPONENT; - depth_type = GL_UNSIGNED_INT; - - srgb_decode_supported = extensions.has("GL_EXT_texture_sRGB_decode"); - etc2_supported = true; + bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc"); #ifdef GLES_OVER_GL float_texture_supported = true; + etc2_supported = false; s3tc_supported = true; - etc_supported = false; // extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); - bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc"); - rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc"); - support_npot_repeat_mipmap = true; - depth_buffer_internalformat = GL_DEPTH_COMPONENT24; + rgtc_supported = true; //RGTC - core since OpenGL version 3.0 #else float_texture_supported = extensions.has("GL_ARB_texture_float") || extensions.has("GL_OES_texture_float"); - s3tc_supported = extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc"); - etc_supported = extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || extensions.has("WEBGL_compressed_texture_etc1"); - bptc_supported = false; - rgtc_supported = false; - support_npot_repeat_mipmap = extensions.has("GL_OES_texture_npot"); - -#ifdef JAVASCRIPT_ENABLED - // RenderBuffer internal format must be 16 bits in WebGL, - // but depth_texture should default to 32 always - // if the implementation doesn't support 32, it should just quietly use 16 instead - // https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/ - depth_buffer_internalformat = GL_DEPTH_COMPONENT16; - depth_type = GL_UNSIGNED_INT; -#else - // on mobile check for 24 bit depth support for RenderBufferStorage - if (extensions.has("GL_OES_depth24")) { - depth_buffer_internalformat = _DEPTH_COMPONENT24_OES; - depth_type = GL_UNSIGNED_INT; - } else { - depth_buffer_internalformat = GL_DEPTH_COMPONENT16; - depth_type = GL_UNSIGNED_SHORT; - } -#endif + etc2_supported = true; + s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc"); + rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc"); #endif #ifdef GLES_OVER_GL use_rgba_2d_shadows = false; - use_rgba_3d_shadows = false; - support_depth_cubemaps = true; #else use_rgba_2d_shadows = !(float_texture_supported && extensions.has("GL_EXT_texture_rg")); - use_rgba_3d_shadows = false; - support_depth_cubemaps = extensions.has("GL_OES_depth_texture_cube_map"); -#endif - -#ifdef GLES_OVER_GL - support_32_bits_indices = true; -#else - support_32_bits_indices = extensions.has("GL_OES_element_index_uint"); #endif -#ifdef GLES_OVER_GL - support_write_depth = true; -#elif defined(JAVASCRIPT_ENABLED) - support_write_depth = false; -#else - support_write_depth = extensions.has("GL_EXT_frag_depth"); -#endif + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units); + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_image_units); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size); - //picky requirements for these - support_shadow_cubemaps = support_write_depth && support_depth_cubemaps; // the use skeleton software path should be used if either float texture is not supported, // OR max_vertex_texture_image_units is zero use_skeleton_software = (float_texture_supported == false) || (max_vertex_texture_image_units == 0); - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units); - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_image_units); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); - glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size); - support_anisotropic_filter = extensions.has("GL_EXT_texture_filter_anisotropic"); if (support_anisotropic_filter) { glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropic_level); diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h index c93c030498..db76aa79fb 100644 --- a/drivers/gles3/storage/config.h +++ b/drivers/gles3/storage/config.h @@ -53,6 +53,8 @@ private: public: bool use_nearest_mip_filter = false; bool use_skeleton_software = false; + bool use_depth_prepass = true; + bool use_rgba_2d_shadows = false; int max_vertex_texture_image_units = 0; int max_texture_image_units = 0; @@ -69,38 +71,15 @@ public: bool float_texture_supported = false; bool s3tc_supported = false; - bool latc_supported = false; bool rgtc_supported = false; bool bptc_supported = false; - bool etc_supported = false; bool etc2_supported = false; - bool srgb_decode_supported = false; - - bool keep_original_textures = false; bool force_vertex_shading = false; - bool use_rgba_2d_shadows = false; - bool use_rgba_3d_shadows = false; - - bool support_32_bits_indices = false; - bool support_write_depth = false; - bool support_npot_repeat_mipmap = false; - bool support_depth_cubemaps = false; - bool support_shadow_cubemaps = false; bool support_anisotropic_filter = false; float anisotropic_level = 0.0f; - GLuint depth_internalformat = 0; - GLuint depth_type = 0; - GLuint depth_buffer_internalformat = 0; - - // in some cases the legacy render didn't orphan. We will mark these - // so the user can switch orphaning off for them. - bool should_orphan = true; - - bool use_depth_prepass = true; - static Config *get_singleton() { return singleton; }; Config(); diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index a57c899133..698bcf3ec2 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1184,8 +1184,6 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet p_textures[k++] = gl_texture; } } else { - //bool srgb = p_use_linear_color && p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR; - for (int j = 0; j < textures.size(); j++) { Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]); @@ -1671,10 +1669,6 @@ ShaderCompiler::DefaultIdentifierActions actions; shaders.compiler_sky.initialize(actions); } - - //shaders.copy.initialize(); - //shaders.copy_version = shaders.copy.version_create(); //TODO - //shaders.copy.version_bind_shader(shaders.copy_version, CopyShaderGLES3::MODE_COPY_SECTION); } MaterialStorage::~MaterialStorage() { @@ -2748,7 +2742,7 @@ void CanvasShaderData::set_code(const String &p_code) { ShaderCompiler::GeneratedCode gen_code; - int blend_mode = BLEND_MODE_MIX; + int blend_modei = BLEND_MODE_MIX; uses_screen_texture = false; ShaderCompiler::IdentifierActions actions; @@ -2756,12 +2750,12 @@ void CanvasShaderData::set_code(const String &p_code) { actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT; actions.entry_point_stages["light"] = ShaderCompiler::STAGE_FRAGMENT; - actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD); - actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX); - actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB); - actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL); - actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PMALPHA); - actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_mode, BLEND_MODE_DISABLED); + actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_modei, BLEND_MODE_ADD); + actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX); + actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB); + actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL); + actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_modei, BLEND_MODE_PMALPHA); + actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_modei, BLEND_MODE_DISABLED); actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; actions.usage_flag_pointers["texture_sdf"] = &uses_sdf; @@ -2775,6 +2769,8 @@ void CanvasShaderData::set_code(const String &p_code) { version = MaterialStorage::get_singleton()->shaders.canvas_shader.version_create(); } + blend_mode = BlendMode(blend_modei); + #if 0 print_line("**compiling shader:"); print_line("**defines:\n"); diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index 053dbacc05..09f6680bec 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -42,8 +42,6 @@ #include "servers/rendering/shader_language.h" #include "servers/rendering/storage/material_storage.h" -#include "drivers/gles3/shaders/copy.glsl.gen.h" - #include "../shaders/canvas.glsl.gen.h" #include "../shaders/cubemap_filter.glsl.gen.h" #include "../shaders/scene.glsl.gen.h" @@ -53,18 +51,6 @@ namespace GLES3 { /* Shader Structs */ -struct Shaders { - CanvasShaderGLES3 canvas_shader; - SkyShaderGLES3 sky_shader; - SceneShaderGLES3 scene_shader; - CubemapFilterShaderGLES3 cubemap_filter_shader; - - ShaderCompiler compiler_canvas; - ShaderCompiler compiler_scene; - ShaderCompiler compiler_particles; - ShaderCompiler compiler_sky; -}; - struct ShaderData { virtual void set_code(const String &p_Code) = 0; virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; @@ -159,8 +145,8 @@ struct CanvasShaderData : public ShaderData { bool valid; RID version; - //PipelineVariants pipeline_variants; String path; + BlendMode blend_mode = BLEND_MODE_MIX; HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; @@ -467,7 +453,17 @@ public: MaterialStorage(); virtual ~MaterialStorage(); - Shaders shaders; + struct Shaders { + CanvasShaderGLES3 canvas_shader; + SkyShaderGLES3 sky_shader; + SceneShaderGLES3 scene_shader; + CubemapFilterShaderGLES3 cubemap_filter_shader; + + ShaderCompiler compiler_canvas; + ShaderCompiler compiler_scene; + ShaderCompiler compiler_particles; + ShaderCompiler compiler_sky; + } shaders; /* GLOBAL VARIABLE API */ diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index f932fa8bad..42c80da39a 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -32,6 +32,7 @@ #include "texture_storage.h" #include "config.h" +#include "drivers/gles3/effects/copy_effects.h" using namespace GLES3; @@ -55,8 +56,6 @@ TextureStorage::TextureStorage() { system_fbo = 0; - frame.current_rt = nullptr; - { //create default textures { // White Textures @@ -247,7 +246,7 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS: /* Texture API */ -Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const { +Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const { Config *config = Config::get_singleton(); r_gl_format = 0; Ref<Image> image = p_image; @@ -295,14 +294,12 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_internal_format = GL_RGB8; r_gl_format = GL_RGB; r_gl_type = GL_UNSIGNED_BYTE; - //r_srgb = true; } break; case Image::FORMAT_RGBA8: { r_gl_format = GL_RGBA; r_gl_internal_format = GL_RGBA8; r_gl_type = GL_UNSIGNED_BYTE; - //r_srgb = true; } break; case Image::FORMAT_RGBA4444: { @@ -311,12 +308,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4; } break; - //case Image::FORMAT_RGBA5551: { - // r_gl_internal_format = GL_RGB5_A1; - // r_gl_format = GL_RGBA; - // r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1; - // - //} break; case Image::FORMAT_RF: { r_gl_internal_format = GL_R32F; r_gl_format = GL_RED; @@ -376,8 +367,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; - } else { need_decompress = true; } @@ -388,8 +377,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; - } else { need_decompress = true; } @@ -400,8 +387,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; - } else { need_decompress = true; } @@ -412,7 +397,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - } else { need_decompress = true; } @@ -433,8 +417,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; - } else { need_decompress = true; } @@ -459,19 +441,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I need_decompress = true; } } break; - case Image::FORMAT_ETC: { - if (config->etc_supported) { - r_gl_internal_format = _EXT_ETC1_RGB8_OES; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - - } break; - /* case Image::FORMAT_ETC2_R11: { if (config->etc2_supported) { r_gl_internal_format = _EXT_COMPRESSED_R11_EAC; @@ -516,13 +485,13 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I need_decompress = true; } } break; + case Image::FORMAT_ETC: case Image::FORMAT_ETC2_RGB8: { if (config->etc2_supported) { r_gl_internal_format = _EXT_COMPRESSED_RGB8_ETC2; r_gl_format = GL_RGB; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; } else { need_decompress = true; @@ -534,7 +503,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; } else { need_decompress = true; @@ -546,13 +514,11 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - //r_srgb = true; } else { need_decompress = true; } } break; - */ default: { ERR_FAIL_V_MSG(Ref<Image>(), "Image Format: " + itos(p_format) + " is not supported by the OpenGL3 Renderer"); } @@ -643,7 +609,7 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im texture.format = p_image->get_format(); texture.type = Texture::TYPE_2D; texture.target = GL_TEXTURE_2D; - _get_gl_image_and_format(Ref<Image>(), texture.format, 0, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false); + _get_gl_image_and_format(Ref<Image>(), texture.format, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false); //texture.total_data_size = p_image->get_image_data_size(); // verify that this returns size in bytes texture.active = true; glGenTextures(1, &texture.tex_id); @@ -880,11 +846,6 @@ void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDe } void TextureStorage::texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - texture->detect_srgb = p_callback; - texture->detect_srgb_ud = p_userdata; } void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { @@ -967,7 +928,7 @@ void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image, // print_line("texture_set_data width " + itos (p_image->get_width()) + " height " + itos(p_image->get_height())); Image::Format real_format; - Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), 0, real_format, format, internal_format, type, compressed, texture->resize_to_po2); + Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), real_format, format, internal_format, type, compressed, texture->resize_to_po2); ERR_FAIL_COND(img.is_null()); if (texture->resize_to_po2) { if (p_image->is_compressed()) { @@ -1054,11 +1015,6 @@ void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image, texture->stored_cube_sides |= (1 << p_layer); - //if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != RenderingDevice::TEXTURE_TYPE_CUBE || texture->stored_cube_sides == (1 << 6) - 1)) { - //generate mipmaps if they were requested and the image does not contain them - // glGenerateMipmap(texture->target); - //} - texture->mipmaps = mipmaps; } @@ -1066,128 +1022,6 @@ void TextureStorage::texture_set_data_partial(RID p_texture, const Ref<Image> &p ERR_PRINT("Not implemented yet, sorry :("); } -/* -Ref<Image> TextureStorage::texture_get_data(RID p_texture, int p_layer) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, Ref<Image>()); - ERR_FAIL_COND_V(!texture->active, Ref<Image>()); - ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>()); - - -#ifdef GLES_OVER_GL - - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - bool compressed; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, false); - - PoolVector<uint8_t> data; - - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1); - - data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers - PoolVector<uint8_t>::Write wb = data.write(); - - glActiveTexture(GL_TEXTURE0); - - glBindTexture(texture->target, texture->tex_id); - - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - - for (int i = 0; i < texture->mipmaps; i++) { - int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, real_format, i); - - if (texture->compressed) { - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glGetCompressedTexImage(texture->target, i, &wb[ofs]); - } else { - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]); - } - } - - wb.release(); - - data.resize(data_size); - - Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, real_format, data)); - - return Ref<Image>(img); -#else - - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - bool compressed; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, texture->resize_to_po2); - - PoolVector<uint8_t> data; - - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); - - data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers - PoolVector<uint8_t>::Write wb = data.write(); - - GLuint temp_framebuffer; - glGenFramebuffers(1, &temp_framebuffer); - - GLuint temp_color_texture; - glGenTextures(1, &temp_color_texture); - - glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); - - glBindTexture(GL_TEXTURE_2D, temp_color_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); - - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - - glViewport(0, 0, texture->alloc_width, texture->alloc_height); - - shaders.copy.bind(); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - bind_quad_array(); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); - - glDeleteTextures(1, &temp_color_texture); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &temp_framebuffer); - - wb.release(); - - data.resize(data_size); - - Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); - if (!texture->compressed) { - img->convert(real_format); - } - - return Ref<Image>(img); - -#endif -} -*/ - Image::Format TextureStorage::texture_get_format(RID p_texture) const { Texture *texture = texture_owner.get_or_null(p_texture); @@ -1285,32 +1119,6 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const { GLuint TextureStorage::system_fbo = 0; -void TextureStorage::_set_current_render_target(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - - if (rt) { - if (rt->allocate_is_dirty) { - rt->allocate_is_dirty = false; - //_clear_render_target(rt); - //_update_render_target(rt); - } - - frame.current_rt = rt; - ERR_FAIL_COND(!rt); - - glViewport(rt->position.x, rt->position.y, rt->size.x, rt->size.y); - - _dims.rt_width = rt->size.x; - _dims.rt_height = rt->size.y; - _dims.win_width = rt->size.x; - _dims.win_height = rt->size.y; - - } else { - frame.current_rt = nullptr; - glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); - } -} - void TextureStorage::_update_render_target(RenderTarget *rt) { // do not allocate a render target with no size if (rt->size.x <= 0 || rt->size.y <= 0) { @@ -1318,14 +1126,14 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { } // do not allocate a render target that is attached to the screen - if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) { + if (rt->direct_to_screen) { rt->fbo = system_fbo; return; } - rt->color_internal_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_RGBA8 : GL_RGB10_A2; + rt->color_internal_format = rt->is_transparent ? GL_RGBA8 : GL_RGB10_A2; rt->color_format = GL_RGBA; - rt->color_type = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV; + rt->color_type = rt->is_transparent ? GL_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV; rt->image_format = Image::FORMAT_RGBA8; glDisable(GL_SCISSOR_TEST); @@ -1388,87 +1196,64 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); + glBindFramebuffer(GL_FRAMEBUFFER, system_fbo); +} +void TextureStorage::_create_render_target_backbuffer(RenderTarget *rt) { + ERR_FAIL_COND_MSG(rt->backbuffer_fbo != 0, "Cannot allocate RenderTarget backbuffer: already initialized."); + ERR_FAIL_COND(rt->direct_to_screen); // Allocate mipmap chains for full screen blur - if (rt->size.x >= 2 && rt->size.y >= 2) { - for (int i = 0; i < 2; i++) { - ERR_FAIL_COND(rt->mip_maps[i].sizes.size()); - int w = rt->size.x; - int h = rt->size.y; - - if (i > 0) { - w >>= 1; - h >>= 1; - } - - int level = 0; - GLsizei width = w; - GLsizei height = h; + // Limit mipmaps so smallest is 32x32 to avoid unnecessary framebuffer switches + int count = MAX(1, Image::get_image_required_mipmaps(rt->size.x, rt->size.y, Image::FORMAT_RGBA8) - 4); + if (rt->size.x > 40 && rt->size.y > 40) { + GLsizei width = rt->size.x; + GLsizei height = rt->size.y; - while (true) { - RenderTarget::MipMaps::Size mm; - mm.width = w; - mm.height = h; - rt->mip_maps[i].sizes.push_back(mm); + rt->mipmap_count = count; - w >>= 1; - h >>= 1; + glGenTextures(1, &rt->backbuffer); + glBindTexture(GL_TEXTURE_2D, rt->backbuffer); - if (w < 2 || h < 2) { - break; - } - - level++; - } - - glGenTextures(1, &rt->mip_maps[i].color); - glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].color); - - for (int l = 0; l < level + 1; l++) { - glTexImage2D(GL_TEXTURE_2D, l, rt->color_internal_format, width, height, 0, rt->color_format, rt->color_type, nullptr); - width = MAX(1, (width / 2)); - height = MAX(1, (height / 2)); - } -#ifdef GLES_OVER_GL - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level); -#endif + for (int l = 0; l < count; l++) { + glTexImage2D(GL_TEXTURE_2D, l, rt->color_internal_format, width, height, 0, rt->color_format, rt->color_type, nullptr); + width = MAX(1, (width / 2)); + height = MAX(1, (height / 2)); + } - for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) { - RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j]; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, count - 1); - glGenFramebuffers(1, &mm.fbo); - bind_framebuffer(mm.fbo); + glGenFramebuffers(1, &rt->backbuffer_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->backbuffer, 0); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - WARN_PRINT_ONCE("Cannot allocate mipmaps for canvas screen blur. Status: " + get_framebuffer_error(status)); - bind_framebuffer_system(); - return; - } + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + WARN_PRINT_ONCE("Cannot allocate mipmaps for canvas screen blur. Status: " + get_framebuffer_error(status)); + glBindFramebuffer(GL_FRAMEBUFFER, system_fbo); + return; + } - glClearColor(1.0, 0.0, 1.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - } + // Initialize all levels to opaque Magenta. + for (int j = 0; j < count; j++) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->backbuffer, j); + glClearColor(1.0, 0.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + } - rt->mip_maps[i].levels = level; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->backbuffer, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - rt->mip_maps_allocated = true; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - - bind_framebuffer_system(); } void TextureStorage::_clear_render_target(RenderTarget *rt) { // there is nothing to clear when DIRECT_TO_SCREEN is used - if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) { + if (rt->direct_to_screen) { return; } @@ -1504,17 +1289,11 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { tex->height = 0; tex->active = false; - for (int i = 0; i < 2; i++) { - if (rt->mip_maps[i].sizes.size()) { - for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) { - glDeleteFramebuffers(1, &rt->mip_maps[i].sizes[j].fbo); - } - - glDeleteTextures(1, &rt->mip_maps[i].color); - rt->mip_maps[i].sizes.clear(); - rt->mip_maps[i].levels = 0; - rt->mip_maps[i].color = 0; - } + if (rt->backbuffer_fbo != 0) { + glDeleteFramebuffers(1, &rt->backbuffer_fbo); + glDeleteTextures(1, &rt->backbuffer); + rt->backbuffer = 0; + rt->backbuffer_fbo = 0; } } @@ -1523,9 +1302,6 @@ RID TextureStorage::render_target_create() { //render_target.was_used = false; render_target.clear_requested = false; - for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) { - render_target.flags[i] = false; - } Texture t; t.active = true; t.render_target = &render_target; @@ -1568,9 +1344,6 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in rt->size = Size2i(p_width, p_height); - // print_line("render_target_set_size " + itos(p_render_target.get_id()) + ", w " + itos(p_width) + " h " + itos(p_height)); - - rt->allocate_is_dirty = true; _update_render_target(rt); } @@ -1642,7 +1415,6 @@ void TextureStorage::render_target_set_external_texture(RID p_render_target, uns t->gl_format_cache = 0; t->gl_internal_format_cache = 0; t->gl_type_cache = 0; - t->srgb = false; t->total_data_size = 0; t->mipmaps = 1; t->active = true; @@ -1688,29 +1460,28 @@ void TextureStorage::render_target_set_external_texture(RID p_render_target, uns } } -void TextureStorage::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { +void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_transparent) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); - // When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as - // those functions change how they operate depending on the value of DIRECT_TO_SCREEN - if (p_flag == RENDER_TARGET_DIRECT_TO_SCREEN && p_value != rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) { - _clear_render_target(rt); - rt->flags[p_flag] = p_value; - _update_render_target(rt); - } + rt->is_transparent = p_transparent; - rt->flags[p_flag] = p_value; + _clear_render_target(rt); + _update_render_target(rt); +} - switch (p_flag) { - case RENDER_TARGET_TRANSPARENT: { - //must reset for these formats - _clear_render_target(rt); - _update_render_target(rt); - } break; - default: { - } +void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + if (p_direct_to_screen == rt->direct_to_screen) { + return; } + // When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as + // those functions change how they operate depending on the value of DIRECT_TO_SCREEN + _clear_render_target(rt); + rt->direct_to_screen = p_direct_to_screen; + _update_render_target(rt); } bool TextureStorage::render_target_was_used(RID p_render_target) { @@ -1772,4 +1543,85 @@ Rect2i TextureStorage::render_target_get_sdf_rect(RID p_render_target) const { void TextureStorage::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) { } +void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + ERR_FAIL_COND(rt->direct_to_screen); + + if (rt->backbuffer_fbo == 0) { + _create_render_target_backbuffer(rt); + } + + Rect2i region; + if (p_region == Rect2i()) { + region.size = rt->size; + } else { + region = Rect2i(Size2i(), rt->size).intersection(p_region); + if (region.size == Size2i()) { + return; //nothing to do + } + } + + glDisable(GL_BLEND); + //single texture copy for backbuffer + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, rt->color); + GLES3::CopyEffects::get_singleton()->copy_screen(); + + if (p_gen_mipmaps) { + GLES3::CopyEffects::get_singleton()->bilinear_blur(rt->backbuffer, rt->mipmap_count, region); + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); + } + + glEnable(GL_BLEND); // 2D almost always uses blend. +} + +void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + ERR_FAIL_COND(rt->direct_to_screen); + + if (rt->backbuffer_fbo == 0) { + _create_render_target_backbuffer(rt); + } + + Rect2i region; + if (p_region == Rect2i()) { + // Just do a full screen clear; + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); + glClearColor(p_color.r, p_color.g, p_color.b, p_color.a); + glClear(GL_COLOR_BUFFER_BIT); + } else { + region = Rect2i(Size2i(), rt->size).intersection(p_region); + if (region.size == Size2i()) { + return; //nothing to do + } + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); + GLES3::CopyEffects::get_singleton()->set_color(p_color, region); + } +} + +void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + if (rt->backbuffer_fbo == 0) { + _create_render_target_backbuffer(rt); + } + + Rect2i region; + if (p_region == Rect2i()) { + region.size = rt->size; + } else { + region = Rect2i(Size2i(), rt->size).intersection(p_region); + if (region.size == Size2i()) { + return; //nothing to do + } + } + + GLES3::CopyEffects::get_singleton()->bilinear_blur(rt->backbuffer, rt->mipmap_count, region); + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); +} + #endif // GLES3_ENABLED diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index b092a009c1..d6d04e45a1 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -71,6 +71,17 @@ namespace GLES3 { #define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E #define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#define _EXT_COMPRESSED_R11_EAC 0x9270 +#define _EXT_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define _EXT_COMPRESSED_RG11_EAC 0x9272 +#define _EXT_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define _EXT_COMPRESSED_RGB8_ETC2 0x9274 +#define _EXT_COMPRESSED_SRGB8_ETC2 0x9275 +#define _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define _EXT_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define _EXT_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 + #define _GL_TEXTURE_EXTERNAL_OES 0x8D65 #ifdef GLES_OVER_GL @@ -161,8 +172,6 @@ struct Texture { bool compressed = false; - bool srgb = false; - bool resize_to_po2 = false; bool active = false; @@ -179,9 +188,6 @@ struct Texture { RS::TextureDetectCallback detect_3d_callback = nullptr; void *detect_3d_callback_ud = nullptr; - RS::TextureDetectCallback detect_srgb = nullptr; - void *detect_srgb_ud = nullptr; - RS::TextureDetectCallback detect_normal_callback = nullptr; void *detect_normal_callback_ud = nullptr; @@ -213,8 +219,6 @@ struct Texture { redraw_if_visible = o.redraw_if_visible; detect_3d_callback = o.detect_3d_callback; detect_3d_callback_ud = o.detect_3d_callback_ud; - detect_srgb = o.detect_srgb; - detect_srgb_ud = o.detect_srgb_ud; detect_normal_callback = o.detect_normal_callback; detect_normal_callback_ud = o.detect_normal_callback_ud; detect_roughness_callback = o.detect_roughness_callback; @@ -311,21 +315,6 @@ private: }; struct RenderTarget { - struct MipMaps { - struct Size { - GLuint fbo; - int width; - int height; - }; - - Vector<Size> sizes; - GLuint color = 0; - int levels = 0; - - MipMaps() { - } - }; - struct External { GLuint fbo = 0; GLuint color = 0; @@ -338,23 +327,21 @@ struct RenderTarget { Point2i position = Point2i(0, 0); Size2i size = Size2i(0, 0); + int mipmap_count = 1; RID self; GLuint fbo = 0; GLuint color = 0; + GLuint backbuffer_fbo = 0; + GLuint backbuffer = 0; GLuint color_internal_format = GL_RGBA8; GLuint color_format = GL_RGBA; GLuint color_type = GL_UNSIGNED_BYTE; Image::Format image_format = Image::FORMAT_RGBA8; - MipMaps mip_maps[2]; - bool mip_maps_allocated = false; - - bool flags[RendererTextureStorage::RENDER_TARGET_FLAG_MAX]; + bool is_transparent = false; + bool direct_to_screen = false; - // instead of allocating sized render targets immediately, - // defer this for faster startup - bool allocate_is_dirty = false; bool used_in_frame = false; RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; @@ -364,9 +351,6 @@ struct RenderTarget { bool clear_requested = false; RenderTarget() { - for (int i = 0; i < RendererTextureStorage::RENDER_TARGET_FLAG_MAX; ++i) { - flags[i] = false; - } } }; @@ -384,28 +368,15 @@ private: mutable RID_Owner<Texture> texture_owner; - Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const; + Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const; /* Render Target API */ mutable RID_Owner<RenderTarget> render_target_owner; - // make access easier to these - struct Dimensions { - // render target - int rt_width; - int rt_height; - - // window - int win_width; - int win_height; - Dimensions() { - rt_width = 0; - rt_height = 0; - win_width = 0; - win_height = 0; - } - } _dims; + void _clear_render_target(RenderTarget *rt); + void _update_render_target(RenderTarget *rt); + void _create_render_target_backbuffer(RenderTarget *rt); public: static TextureStorage *get_singleton(); @@ -522,20 +493,9 @@ public: static GLuint system_fbo; - // TODO this should be moved back to storage or removed - struct Frame { - GLES3::RenderTarget *current_rt; - } frame; - RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); }; bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); }; - // TODO these internals should be private - void _clear_render_target(RenderTarget *rt); - void _update_render_target(RenderTarget *rt); - void _create_render_target_backbuffer(RenderTarget *rt); - void _set_current_render_target(RID p_render_target); - virtual RID render_target_create() override; virtual void render_target_free(RID p_rid) override; virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override; @@ -544,7 +504,8 @@ public: virtual RID render_target_get_texture(RID p_render_target) override; virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override; - virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override; + virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override; + virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override; virtual bool render_target_was_used(RID p_render_target) override; void render_target_clear_used(RID p_render_target); @@ -563,13 +524,9 @@ public: Rect2i render_target_get_sdf_rect(RID p_render_target) const override; void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override; - void bind_framebuffer(GLuint framebuffer) { - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - } - - void bind_framebuffer_system() { - glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); - } + void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps); + void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color); + void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region); String get_framebuffer_error(GLenum p_status); }; |