diff options
author | Bastiaan Olij <mux213@gmail.com> | 2022-03-12 22:19:59 +1100 |
---|---|---|
committer | Bastiaan Olij <mux213@gmail.com> | 2022-03-16 17:43:10 +1100 |
commit | 57e5a33623130ead5aeb5369c7a40410a1afc79b (patch) | |
tree | 8fce4bd039eb7dea19bc334e4cc0feb158a6a6ef | |
parent | cfd21adf64087c750dde89191bcfcf4d166adc85 (diff) |
Split dummy renderer classes into separate files
Split canvas_texture_storage and texture_storage from render_storage class
55 files changed, 5272 insertions, 4169 deletions
diff --git a/drivers/gles3/SCsub b/drivers/gles3/SCsub index 987ddcd16e..fcb05a988d 100644 --- a/drivers/gles3/SCsub +++ b/drivers/gles3/SCsub @@ -5,3 +5,4 @@ Import("env") env.add_source_files(env.drivers_sources, "*.cpp") SConscript("shaders/SCsub") +SConscript("storage/SCsub") diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index f25b7047d5..b47d2e08f1 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -38,6 +38,8 @@ #include "core/config/project_settings.h" #include "servers/rendering/rendering_server_default.h" +#include "storage/canvas_texture_storage.h" +#include "storage/config.h" #ifndef GLES_OVER_GL #define glClearDepth glClearDepthf @@ -260,7 +262,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou for (int ti = 0; ti < tc; i++) { glActiveTexture(GL_TEXTURE0 + ti); - RasterizerStorageGLES3::Texture *t = storage->texture_owner.get_or_null(textures[ti].second); + GLES3::Texture *t = texture_storage->get_texture(textures[ti].second); if (!t) { switch (texture_uniforms[i].hint) { @@ -915,20 +917,20 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe state.end_batch = true; _render_batch(r_index); - RasterizerStorageGLES3::CanvasTexture *ct = nullptr; + GLES3::CanvasTexture *ct = nullptr; - RasterizerStorageGLES3::Texture *t = storage->texture_owner.get_or_null(p_texture); + GLES3::Texture *t = texture_storage->get_texture(p_texture); if (t) { //regular texture if (!t->canvas_texture) { - t->canvas_texture = memnew(RasterizerStorageGLES3::CanvasTexture); + t->canvas_texture = memnew(GLES3::CanvasTexture); t->canvas_texture->diffuse = p_texture; } ct = t->canvas_texture; } else { - ct = storage->canvas_texture_owner.get_or_null(p_texture); + ct = GLES3::CanvasTextureStorage::get_singleton()->get_canvas_texture(p_texture); } if (!ct) { @@ -943,7 +945,7 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat; ERR_FAIL_COND(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - RasterizerStorageGLES3::Texture *texture = storage->texture_owner.get_or_null(ct->diffuse); + GLES3::Texture *texture = texture_storage->get_texture(ct->diffuse); if (!texture) { state.current_tex = RID(); @@ -967,18 +969,18 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe texture->GLSetRepeat(GL_TEXTURE_2D, repeat); } - RasterizerStorageGLES3::Texture *normal_map = storage->texture_owner.get_or_null(ct->normal_map); + GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map); if (!normal_map) { state.current_normal = RID(); ct->use_normal_cache = false; - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); + glActiveTexture(GL_TEXTURE0 + GLES3::Config::get_singleton()->max_texture_image_units - 6); glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); } else { normal_map = normal_map->get_ptr(); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); + glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 6); glBindTexture(GL_TEXTURE_2D, normal_map->tex_id); state.current_normal = ct->normal_map; ct->use_normal_cache = true; @@ -986,18 +988,18 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe texture->GLSetRepeat(GL_TEXTURE_2D, repeat); } - RasterizerStorageGLES3::Texture *specular_map = storage->texture_owner.get_or_null(ct->specular); + GLES3::Texture *specular_map = texture_storage->get_texture(ct->specular); if (!specular_map) { state.current_specular = RID(); ct->use_specular_cache = false; - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7); + glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); } else { specular_map = specular_map->get_ptr(); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7); + glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7); glBindTexture(GL_TEXTURE_2D, specular_map->tex_id); state.current_specular = ct->specular; ct->use_specular_cache = true; @@ -1249,6 +1251,10 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() { } void RasterizerCanvasGLES3::initialize() { + // !BAS! shouldn't we be obtaining storage here as well? + canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton(); + texture_storage = GLES3::TextureStorage::get_singleton(); + // quad buffer { glGenBuffers(1, &data.canvas_quad_vertices); @@ -1408,7 +1414,7 @@ void RasterizerCanvasGLES3::initialize() { state.canvas_shader_default_version = state.canvas_shader.version_create(); state.canvas_shader.version_bind_shader(state.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD); - //state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows); + //state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_RGBA_SHADOWS, storage->config->use_rgba_2d_shadows); //state.canvas_shader.bind(); @@ -1441,8 +1447,8 @@ void fragment() { storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader); } - default_canvas_texture = storage->canvas_texture_allocate(); - storage->canvas_texture_initialize(default_canvas_texture); + default_canvas_texture = canvas_texture_storage->canvas_texture_allocate(); + canvas_texture_storage->canvas_texture_initialize(default_canvas_texture); state.using_light = nullptr; state.using_transparent_rt = false; @@ -1456,7 +1462,7 @@ RasterizerCanvasGLES3::~RasterizerCanvasGLES3() { state.canvas_shader.version_free(state.canvas_shader_default_version); storage->free(default_canvas_group_material); storage->free(default_canvas_group_shader); - storage->free(default_canvas_texture); + canvas_texture_storage->canvas_texture_free(default_canvas_texture); } void RasterizerCanvasGLES3::finalize() { diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 908d79f9f8..1f57c2b5ea 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -37,6 +37,8 @@ #include "rasterizer_storage_gles3.h" #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_compositor.h" +#include "storage/canvas_texture_storage.h" +#include "storage/texture_storage.h" #include "shaders/canvas.glsl.gen.h" @@ -184,7 +186,7 @@ public: RID current_tex = RID(); RID current_normal = RID(); RID current_specular = RID(); - RasterizerStorageGLES3::Texture *current_tex_ptr; + GLES3::Texture *current_tex_ptr; RID current_shader_version = RID(); RS::PrimitiveType current_primitive = RS::PRIMITIVE_MAX; uint32_t current_primitive_points = 0; @@ -217,6 +219,8 @@ public: RasterizerSceneGLES3 *scene_render; + GLES3::CanvasTextureStorage *canvas_texture_storage; + GLES3::TextureStorage *texture_storage; RasterizerStorageGLES3 *storage; void _set_uniforms(); diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 087bf36473..faadb2a4ed 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -195,7 +195,7 @@ typedef void (*DebugMessageCallbackARB)(DEBUGPROCARB callback, const void *userP void RasterizerGLES3::initialize() { print_verbose("Using OpenGL video driver"); - storage._main_thread_id = Thread::get_caller_id(); + texture_storage.set_main_thread_id(Thread::get_caller_id()); #ifdef GLAD_ENABLED if (!gladLoadGL()) { @@ -271,7 +271,7 @@ void RasterizerGLES3::prepare_for_blitting_render_targets() { void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect) { ERR_FAIL_COND(storage.frame.current_rt); - RasterizerStorageGLES3::RenderTarget *rt = storage.render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = storage.render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); // TODO: do we need a keep 3d linear option? @@ -324,10 +324,10 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c canvas.canvas_begin(); - RID texture = storage.texture_create(); - //storage.texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0); - storage._texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D); - storage.texture_set_data(texture, p_image); + RID texture = texture_storage.texture_create(); + //texture_storage.texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0); + texture_storage._texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D); + texture_storage.texture_set_data(texture, p_image); Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height()); Rect2 screenrect; @@ -349,13 +349,13 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c screenrect.position += ((Size2(win_size.width, win_size.height) - screenrect.size) / 2.0).floor(); } - RasterizerStorageGLES3::Texture *t = storage.texture_owner.get_or_null(texture); - glActiveTexture(GL_TEXTURE0 + storage.config.max_texture_image_units - 1); + GLES3::Texture *t = texture_storage.get_texture(texture); + glActiveTexture(GL_TEXTURE0 + config.max_texture_image_units - 1); glBindTexture(GL_TEXTURE_2D, t->tex_id); glBindTexture(GL_TEXTURE_2D, 0); canvas.canvas_end(); - storage.free(texture); + texture_storage.texture_free(texture); end_frame(true); } diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index a641e189c5..93c58a8d9d 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -37,6 +37,10 @@ #include "rasterizer_scene_gles3.h" #include "rasterizer_storage_gles3.h" #include "servers/rendering/renderer_compositor.h" +#include "storage/canvas_texture_storage.h" +#include "storage/config.h" +#include "storage/render_target_storage.h" +#include "storage/texture_storage.h" class RasterizerGLES3 : public RendererCompositor { private: @@ -46,6 +50,9 @@ private: double time_total = 0.0; protected: + GLES3::Config config; + GLES3::CanvasTextureStorage canvas_texture_storage; + GLES3::TextureStorage texture_storage; RasterizerStorageGLES3 storage; RasterizerCanvasGLES3 canvas; RasterizerSceneGLES3 scene; @@ -53,6 +60,8 @@ protected: void _blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect); public: + RendererCanvasTextureStorage *get_canvas_texture_storage() { return &canvas_texture_storage; } + RendererTextureStorage *get_texture_storage() { return &texture_storage; } RendererStorage *get_storage() { return &storage; } RendererCanvasRender *get_canvas() { return &canvas; } RendererSceneRender *get_scene() { return &scene; } diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index dce515a96d..11d4af126c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -40,45 +40,6 @@ GLuint RasterizerStorageGLES3::system_fbo = 0; -/* TEXTURE API */ - -#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 - -#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB -#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB -#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC -#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD -#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE -#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC -#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD -#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE -#define _EXT_ETC1_RGB8_OES 0x8D64 - -#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C -#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D -#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E -#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F - -#define _GL_TEXTURE_EXTERNAL_OES 0x8D65 - -#ifdef GLES_OVER_GL -#define _GL_HALF_FLOAT_OES 0x140B -#else -#define _GL_HALF_FLOAT_OES 0x8D61 -#endif - -#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F - -#define _RED_OES 0x1903 - -#define _DEPTH_COMPONENT24_OES 0x81A6 - -#ifndef GLES_OVER_GL -#define glClearDepth glClearDepthf -#endif //!GLES_OVER_GL - void RasterizerStorageGLES3::bind_quad_array() const { //glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); //glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); @@ -88,1180 +49,6 @@ void RasterizerStorageGLES3::bind_quad_array() const { //glEnableVertexAttribArray(RS::ARRAY_TEX_UV); } -bool RasterizerStorageGLES3::can_create_resources_async() const { - return false; -} - -Ref<Image> RasterizerStorageGLES3::_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 { - r_gl_format = 0; - Ref<Image> image = p_image; - r_compressed = false; - r_real_format = p_format; - - bool need_decompress = false; - - switch (p_format) { - case Image::FORMAT_L8: { -#ifdef GLES_OVER_GL - r_gl_internal_format = GL_R8; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; -#else - r_gl_internal_format = GL_LUMINANCE; - r_gl_format = GL_LUMINANCE; - r_gl_type = GL_UNSIGNED_BYTE; -#endif - } break; - case Image::FORMAT_LA8: { -#ifdef GLES_OVER_GL - r_gl_internal_format = GL_RG8; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; -#else - r_gl_internal_format = GL_LUMINANCE_ALPHA; - r_gl_format = GL_LUMINANCE_ALPHA; - r_gl_type = GL_UNSIGNED_BYTE; -#endif - } break; - case Image::FORMAT_R8: { - r_gl_internal_format = GL_R8; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; - - } break; - case Image::FORMAT_RG8: { - r_gl_internal_format = GL_RG8; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; - - } break; - case Image::FORMAT_RGB8: { - 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: { - r_gl_internal_format = GL_RGBA4; - r_gl_format = GL_RGBA; - 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; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RGF: { - r_gl_internal_format = GL_RG32F; - r_gl_format = GL_RG; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RGBF: { - r_gl_internal_format = GL_RGB32F; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RGBAF: { - r_gl_internal_format = GL_RGBA32F; - r_gl_format = GL_RGBA; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RH: { - r_gl_internal_format = GL_R16F; - r_gl_format = GL_RED; - r_gl_type = GL_HALF_FLOAT; - } break; - case Image::FORMAT_RGH: { - r_gl_internal_format = GL_RG16F; - r_gl_format = GL_RG; - r_gl_type = GL_HALF_FLOAT; - - } break; - case Image::FORMAT_RGBH: { - r_gl_internal_format = GL_RGB16F; - r_gl_format = GL_RGB; - r_gl_type = GL_HALF_FLOAT; - - } break; - case Image::FORMAT_RGBAH: { - r_gl_internal_format = GL_RGBA16F; - r_gl_format = GL_RGBA; - r_gl_type = GL_HALF_FLOAT; - - } break; - case Image::FORMAT_RGBE9995: { - r_gl_internal_format = GL_RGB9_E5; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV; - - } break; - case Image::FORMAT_DXT1: { - if (config.s3tc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_DXT3: { - if (config.s3tc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_DXT5: { - if (config.s3tc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_RGTC_R: { - if (config.rgtc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_RGTC_RG: { - if (config.rgtc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_BPTC_RGBA: { - if (config.bptc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_BPTC_UNORM; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_BPTC_RGBF: { - if (config.bptc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; - r_compressed = true; - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_BPTC_RGBFU: { - if (config.bptc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; - r_compressed = true; - } else { - 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; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_R11S: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_SIGNED_R11_EAC; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RG11: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RG11_EAC; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RG11S: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_SIGNED_RG11_EAC; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - 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; - } - } break; - case Image::FORMAT_ETC2_RGBA8: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA8_ETC2_EAC; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RGB8A1: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; - 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(Ref<Image>()); - } - } - - if (need_decompress || p_force_decompress) { - if (!image.is_null()) { - image = image->duplicate(); - image->decompress(); - ERR_FAIL_COND_V(image->is_compressed(), image); - switch (image->get_format()) { - case Image::FORMAT_RGB8: { - r_gl_format = GL_RGB; - r_gl_internal_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - r_real_format = Image::FORMAT_RGB8; - r_compressed = false; - } break; - case Image::FORMAT_RGBA8: { - r_gl_format = GL_RGBA; - r_gl_internal_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_real_format = Image::FORMAT_RGBA8; - r_compressed = false; - } break; - default: { - image->convert(Image::FORMAT_RGBA8); - r_gl_format = GL_RGBA; - r_gl_internal_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_real_format = Image::FORMAT_RGBA8; - r_compressed = false; - - } break; - } - } - - return image; - } - - return p_image; -} - -static const GLenum _cube_side_enum[6] = { - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, -}; - -RID RasterizerStorageGLES3::texture_allocate() { - RID id = texture_create(); - ERR_FAIL_COND_V(id == RID(), id); - return id; -} - -void RasterizerStorageGLES3::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - - int w = p_image->get_width(); - int h = p_image->get_height(); - - _texture_allocate_internal(p_texture, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0); - texture_set_data(p_texture, p_image); -} - -void RasterizerStorageGLES3::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { -} - -void RasterizerStorageGLES3::texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { -} - -void RasterizerStorageGLES3::texture_proxy_initialize(RID p_texture, RID p_base) { - texture_set_proxy(p_texture, p_base); -} - -//RID RasterizerStorageGLES3::texture_2d_create(const Ref<Image> &p_image) { -// RID id = texture_create(); -// ERR_FAIL_COND_V(id == RID(), id); - -// int w = p_image->get_width(); -// int h = p_image->get_height(); - -// texture_allocate(id, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0); - -// texture_set_data(id, p_image); - -// return id; -//} - -//RID RasterizerStorageGLES3::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { -// return RID(); -//} - -//void RasterizerStorageGLES3::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) { -// // only 1 layer so far -// texture_set_data(p_texture, p_image); -//} -void RasterizerStorageGLES3::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { - // only 1 layer so far - texture_set_data(p_texture, p_image); -} - -void RasterizerStorageGLES3::texture_2d_placeholder_initialize(RID p_texture) { -} - -void RasterizerStorageGLES3::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) { -} - -void RasterizerStorageGLES3::texture_3d_placeholder_initialize(RID p_texture) { -} - -Ref<Image> RasterizerStorageGLES3::texture_2d_get(RID p_texture) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); - - /* -#ifdef TOOLS_ENABLED - if (tex->image_cache_2d.is_valid()) { - return tex->image_cache_2d; - } -#endif - Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); - ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instance(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->empty(), Ref<Image>()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); - } - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - tex->image_cache_2d = image; - } -#endif -*/ - ERR_FAIL_COND_V(!tex->images.size(), Ref<Image>()); - - return tex->images[0]; - - // return image; - - // return Ref<Image>(); -} - -void RasterizerStorageGLES3::texture_replace(RID p_texture, RID p_by_texture) { - Texture *tex_to = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex_to); - Texture *tex_from = texture_owner.get_or_null(p_by_texture); - ERR_FAIL_COND(!tex_from); - - tex_to->destroy(); - tex_to->copy_from(*tex_from); - - // copy image data and upload to GL - tex_to->images.resize(tex_from->images.size()); - - for (int n = 0; n < tex_from->images.size(); n++) { - texture_set_data(p_texture, tex_from->images[n], n); - } - - free(p_by_texture); -} - -bool RasterizerStorageGLES3::_is_main_thread() { - //#if defined DEBUG_ENABLED && defined TOOLS_ENABLED - // must be called from main thread in OpenGL - bool is_main_thread = _main_thread_id == Thread::get_caller_id(); - //#endif - return is_main_thread; -} - -RID RasterizerStorageGLES3::texture_create() { - ERR_FAIL_COND_V(!_is_main_thread(), RID()); - - Texture *texture = memnew(Texture); - ERR_FAIL_COND_V(!texture, RID()); - glGenTextures(1, &texture->tex_id); - texture->active = false; - texture->total_data_size = 0; - - return texture_owner.make_rid(texture); -} - -void RasterizerStorageGLES3::_texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags) { - // GLenum format; - // GLenum internal_format; - // GLenum type; - - // bool compressed = false; - - if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - p_flags &= ~TEXTURE_FLAG_MIPMAPS; // no mipies for video - } - - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - texture->width = p_width; - texture->height = p_height; - texture->format = p_format; - texture->flags = p_flags; - texture->stored_cube_sides = 0; - texture->type = p_type; - - switch (p_type) { - case RenderingDevice::TEXTURE_TYPE_2D: { - texture->target = GL_TEXTURE_2D; - texture->images.resize(1); - } break; - // case RenderingDevice::TEXTURE_TYPE_EXTERNAL: { - //#ifdef ANDROID_ENABLED - // texture->target = _GL_TEXTURE_EXTERNAL_OES; - //#else - // texture->target = GL_TEXTURE_2D; - //#endif - // texture->images.resize(0); - // } break; - case RenderingDevice::TEXTURE_TYPE_CUBE: { - texture->target = GL_TEXTURE_CUBE_MAP; - texture->images.resize(6); - } break; - case RenderingDevice::TEXTURE_TYPE_2D_ARRAY: - case RenderingDevice::TEXTURE_TYPE_3D: { - texture->target = GL_TEXTURE_3D; - ERR_PRINT("3D textures and Texture Arrays are not supported in OpenGL. Please switch to the Vulkan backend."); - return; - } break; - default: { - ERR_PRINT("Unknown texture type!"); - return; - } - } - -#if 0 - // if (p_type != RS::TEXTURE_TYPE_EXTERNAL) { - if (p_type == RenderingDevice::TEXTURE_TYPE_2D) { - texture->alloc_width = texture->width; - texture->alloc_height = texture->height; - texture->resize_to_po2 = false; - if (!config.support_npot_repeat_mipmap) { - int po2_width = next_power_of_2(p_width); - int po2_height = next_power_of_2(p_height); - - bool is_po2 = p_width == po2_width && p_height == po2_height; - - if (!is_po2 && (p_flags & TEXTURE_FLAG_REPEAT || p_flags & TEXTURE_FLAG_MIPMAPS)) { - if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - //not supported - ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled."); - texture->flags &= ~(TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS); - } else { - texture->alloc_height = po2_height; - texture->alloc_width = po2_width; - texture->resize_to_po2 = true; - } - } - } - - GLenum format; - GLenum internal_format; - GLenum type; - bool compressed = false; - - Image::Format real_format; - _get_gl_image_and_format(Ref<Image>(), - texture->format, - texture->flags, - real_format, - format, - internal_format, - type, - compressed, - texture->resize_to_po2); - - texture->gl_format_cache = format; - texture->gl_type_cache = type; - texture->gl_internal_format_cache = internal_format; - texture->data_size = 0; - texture->mipmaps = 1; - - texture->compressed = compressed; - } -#endif - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - // if (p_type == RS::TEXTURE_TYPE_EXTERNAL) { - // glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - // glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // glTexParameteri(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - // glTexParameteri(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // } else if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - // //prealloc if video - // glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL); - // } - - texture->active = true; -} - -void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND(!_is_main_thread()); - - ERR_FAIL_COND(!texture); - if (texture->target == GL_TEXTURE_3D) { - // Target is set to a 3D texture or array texture, exit early to avoid spamming errors - return; - } - ERR_FAIL_COND(!texture->active); - ERR_FAIL_COND(texture->render_target); - ERR_FAIL_COND(p_image.is_null()); - ERR_FAIL_COND(texture->format != p_image->get_format()); - - ERR_FAIL_COND(!p_image->get_width()); - ERR_FAIL_COND(!p_image->get_height()); - - // ERR_FAIL_COND(texture->type == RS::TEXTURE_TYPE_EXTERNAL); - - GLenum type; - GLenum format; - GLenum internal_format; - bool compressed = false; - - if (config.keep_original_textures && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) { - texture->images.write[p_layer] = 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(), texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2); - - if (texture->resize_to_po2) { - if (p_image->is_compressed()) { - ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage."); - } - - if (img == p_image) { - img = img->duplicate(); - } - img->resize_to_po2(false); - } - - if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) { - texture->alloc_height = MAX(1, texture->alloc_height / 2); - texture->alloc_width = MAX(1, texture->alloc_width / 2); - - 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_RGBA8) { - img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); - } - } - - GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D; - - texture->data_size = img->get_data().size(); - Vector<uint8_t> read = img->get_data(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - texture->ignore_mipmaps = compressed && !img->has_mipmaps(); - - // set filtering and repeat state - _texture_set_state_from_flags(texture); - - //set swizle for older format compatibility -#ifdef GLES_OVER_GL - switch (texture->format) { - case Image::FORMAT_L8: { - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ONE); - - } break; - case Image::FORMAT_LA8: { - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_GREEN); - } break; - default: { - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_GREEN); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_BLUE); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA); - - } break; - } -#endif - - int mipmaps = ((texture->flags & TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; - - int w = img->get_width(); - int h = img->get_height(); - - int tsize = 0; - - for (int i = 0; i < mipmaps; i++) { - int size, ofs; - img->get_mipmap_offset_and_size(i, ofs, size); - - if (compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - - int bw = w; - int bh = h; - - glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]); - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - if (texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]); - } else { - glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]); - } - } - - tsize += size; - - w = MAX(1, w >> 1); - h = MAX(1, h >> 1); - } - - info.texture_mem -= texture->total_data_size; - texture->total_data_size = tsize; - info.texture_mem += texture->total_data_size; - - // printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem); - - 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; -} - -void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) { - // TODO - ERR_PRINT("Not implemented (ask Karroffel to do it :p)"); -} - -/* -Ref<Image> RasterizerStorageGLES3::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>()); - - if (texture->type == RS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) { - return texture->images[p_layer]; - } - -#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 -} -*/ - -void RasterizerStorageGLES3::_texture_set_state_from_flags(Texture *p_tex) { - if ((p_tex->flags & TEXTURE_FLAG_MIPMAPS) && !p_tex->ignore_mipmaps) { - if (p_tex->flags & TEXTURE_FLAG_FILTER) { - // these do not exactly correspond ... - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS); - //texture->glTexParam_MinFilter(texture->target, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); - } else { - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS); - //texture->glTexParam_MinFilter(texture->target, config.use_fast_texture_filter ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR); - } - } else { - if (p_tex->flags & TEXTURE_FLAG_FILTER) { - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR); - //texture->glTexParam_MinFilter(texture->target, GL_LINEAR); - } else { - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST); - // texture->glTexParam_MinFilter(texture->target, GL_NEAREST); - } - } - - if (((p_tex->flags & TEXTURE_FLAG_REPEAT) || (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT)) && p_tex->target != GL_TEXTURE_CUBE_MAP) { - if (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT) { - p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); - } else { - p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - } - } else { - p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - } -} - -void RasterizerStorageGLES3::texture_set_flags(RID p_texture, uint32_t p_flags) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - bool had_mipmaps = texture->flags & TEXTURE_FLAG_MIPMAPS; - - texture->flags = p_flags; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - // set filtering and repeat state - _texture_set_state_from_flags(texture); - - if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) { - if (!had_mipmaps && texture->mipmaps == 1) { - glGenerateMipmap(texture->target); - } - } -} - -uint32_t RasterizerStorageGLES3::texture_get_flags(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->flags; -} - -Image::Format RasterizerStorageGLES3::texture_get_format(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, Image::FORMAT_L8); - - return texture->format; -} - -RenderingDevice::TextureType RasterizerStorageGLES3::texture_get_type(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, RenderingDevice::TEXTURE_TYPE_2D); - - return texture->type; -} - -uint32_t RasterizerStorageGLES3::texture_get_texid(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->tex_id; -} - -void RasterizerStorageGLES3::texture_bind(RID p_texture, uint32_t p_texture_no) { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND(!texture); - - glActiveTexture(GL_TEXTURE0 + p_texture_no); - glBindTexture(texture->target, texture->tex_id); -} - -uint32_t RasterizerStorageGLES3::texture_get_width(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->width; -} - -uint32_t RasterizerStorageGLES3::texture_get_height(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->height; -} - -uint32_t RasterizerStorageGLES3::texture_get_depth(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->depth; -} - -void RasterizerStorageGLES3::texture_set_size_override(RID p_texture, int p_width, int p_height) { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND(!texture); - ERR_FAIL_COND(texture->render_target); - - ERR_FAIL_COND(p_width <= 0 || p_width > 16384); - ERR_FAIL_COND(p_height <= 0 || p_height > 16384); - //real texture size is in alloc width and height - texture->width = p_width; - texture->height = p_height; -} - -void RasterizerStorageGLES3::texture_set_path(RID p_texture, const String &p_path) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - texture->path = p_path; -} - -String RasterizerStorageGLES3::texture_get_path(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!texture, ""); - - return texture->path; -} - -void RasterizerStorageGLES3::texture_debug_usage(List<RS::TextureInfo> *r_info) { - List<RID> textures; - texture_owner.get_owned_list(&textures); - - for (List<RID>::Element *E = textures.front(); E; E = E->next()) { - Texture *t = texture_owner.get_or_null(E->get()); - if (!t) { - continue; - } - RS::TextureInfo tinfo; - tinfo.path = t->path; - tinfo.format = t->format; - tinfo.width = t->alloc_width; - tinfo.height = t->alloc_height; - tinfo.depth = 0; - tinfo.bytes = t->total_data_size; - r_info->push_back(tinfo); - } -} - -void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable) { - config.shrink_textures_x2 = p_enable; -} - -void RasterizerStorageGLES3::textures_keep_original(bool p_enable) { - config.keep_original_textures = p_enable; -} - -Size2 RasterizerStorageGLES3::texture_size_with_proxy(RID p_texture) { - const Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!texture, Size2()); - if (texture->proxy) { - return Size2(texture->proxy->width, texture->proxy->height); - } else { - return Size2(texture->width, texture->height); - } -} - -// example use in 3.2 -// VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid); - -// p_proxy is the source (pre-existing) texture? -// and p_texture is the one that is being made into a proxy? -//This naming is confusing. Comments!!! - -// The naming of the parameters seemed to be reversed? -// The p_proxy is the source texture -// and p_texture is actually the proxy???? - -void RasterizerStorageGLES3::texture_set_proxy(RID p_texture, RID p_proxy) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - if (texture->proxy) { - texture->proxy->proxy_owners.erase(texture); - texture->proxy = nullptr; - } - - if (p_proxy.is_valid()) { - Texture *proxy = texture_owner.get_or_null(p_proxy); - ERR_FAIL_COND(!proxy); - ERR_FAIL_COND(proxy == texture); - proxy->proxy_owners.insert(texture); - texture->proxy = proxy; - } -} - -void RasterizerStorageGLES3::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - texture->redraw_if_visible = p_enable; -} - -void RasterizerStorageGLES3::texture_set_detect_3d_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_3d = p_callback; - texture->detect_3d_ud = p_userdata; -} - -void RasterizerStorageGLES3::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 RasterizerStorageGLES3::texture_set_detect_normal_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_normal = p_callback; - texture->detect_normal_ud = p_userdata; -} - -RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_resolution) const { - return RID(); -} - -RID RasterizerStorageGLES3::canvas_texture_allocate() { - return canvas_texture_owner.allocate_rid(); -} - -void RasterizerStorageGLES3::canvas_texture_initialize(RID p_rid) { - canvas_texture_owner.initialize_rid(p_rid); -} - -void RasterizerStorageGLES3::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - switch (p_channel) { - case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { - ct->diffuse = p_texture; - } break; - case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { - ct->normal_map = p_texture; - } break; - case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { - ct->specular = p_texture; - } break; - } -} - -void RasterizerStorageGLES3::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->specular_color.r = p_specular_color.r; - ct->specular_color.g = p_specular_color.g; - ct->specular_color.b = p_specular_color.b; - ct->specular_color.a = p_shininess; -} - -void RasterizerStorageGLES3::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->texture_filter = p_filter; -} -void RasterizerStorageGLES3::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->texture_repeat = p_repeat; -} - RID RasterizerStorageGLES3::sky_create() { Sky *sky = memnew(Sky); sky->radiance = 0; @@ -1666,7 +453,7 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); - ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); + ERR_FAIL_COND(p_texture.is_valid() && !GLES3::TextureStorage::get_singleton()->owns_texture(p_texture)); if (!p_texture.is_valid()) { if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) { @@ -2897,7 +1684,7 @@ bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const { /* RENDER TARGET */ void RasterizerStorageGLES3::_set_current_render_target(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); if (rt) { if (rt->allocate_is_dirty) { @@ -2923,7 +1710,7 @@ void RasterizerStorageGLES3::_set_current_render_target(RID p_render_target) { } } -void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { +void RasterizerStorageGLES3::_render_target_allocate(GLES3::RenderTarget *rt) { // do not allocate a render target with no size if (rt->width <= 0 || rt->height <= 0) { return; @@ -2964,7 +1751,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { { /* Front FBO */ - Texture *texture = texture_owner.get_or_null(rt->texture); + GLES3::Texture *texture = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture); ERR_FAIL_COND(!texture); // framebuffer @@ -2977,7 +1764,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, nullptr); - if (texture->flags & TEXTURE_FLAG_FILTER) { + if (texture->flags & GLES3::TEXTURE_FLAG_FILTER) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { @@ -2992,10 +1779,10 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { // depth - if (config.support_depth_texture) { + if (config->support_depth_texture) { glGenTextures(1, &rt->depth); glBindTexture(GL_TEXTURE_2D, rt->depth); - glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config.depth_type, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config->depth_type, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -3007,7 +1794,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenRenderbuffers(1, &rt->depth); glBindRenderbuffer(GL_RENDERBUFFER, rt->depth); - glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, rt->width, rt->height); + glRenderbufferStorage(GL_RENDERBUFFER, config->depth_buffer_internalformat, rt->width, rt->height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); } @@ -3016,7 +1803,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { if (status != GL_FRAMEBUFFER_COMPLETE) { glDeleteFramebuffers(1, &rt->fbo); - if (config.support_depth_texture) { + if (config->support_depth_texture) { glDeleteTextures(1, &rt->depth); } else { glDeleteRenderbuffers(1, &rt->depth); @@ -3045,7 +1832,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { texture->alloc_height = rt->height; texture->active = true; - texture_set_flags(rt->texture, texture->flags); + GLES3::TextureStorage::get_singleton()->texture_set_flags(rt->texture, texture->flags); } /* BACK FBO */ @@ -3071,7 +1858,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenRenderbuffers(1, &rt->multisample_depth); glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_buffer_internalformat, rt->width, rt->height); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config->depth_buffer_internalformat, rt->width, rt->height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth); @@ -3160,7 +1947,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { int fb_h = h; while (true) { - RenderTarget::MipMaps::Size mm; + GLES3::RenderTarget::MipMaps::Size mm; mm.width = w; mm.height = h; rt->mip_maps[i].sizes.push_back(mm); @@ -3178,7 +1965,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { GLsizei width = fb_w; GLsizei height = fb_h; - if (config.render_to_mipmap_supported) { + if (config->render_to_mipmap_supported) { glGenTextures(1, &rt->mip_maps[i].color); glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].color); @@ -3211,12 +1998,12 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glDepthMask(GL_TRUE); for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) { - RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j]; + GLES3::RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j]; glGenFramebuffers(1, &mm.fbo); bind_framebuffer(mm.fbo); - if (config.render_to_mipmap_supported) { + if (config->render_to_mipmap_supported) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j); } else { glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color); @@ -3225,7 +2012,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { bool used_depth = false; if (j == 0 && i == 0) { //use always - if (config.support_depth_texture) { + if (config->support_depth_texture) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); } else { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); @@ -3250,7 +2037,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { rt->mip_maps[i].levels = level; - if (config.render_to_mipmap_supported) { + if (config->render_to_mipmap_supported) { 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); @@ -3263,7 +2050,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { bind_framebuffer_system(); } -void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { +void RasterizerStorageGLES3::_render_target_clear(GLES3::RenderTarget *rt) { // there is nothing to clear when DIRECT_TO_SCREEN is used if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) { return; @@ -3280,20 +2067,20 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { glDeleteFramebuffers(1, &rt->external.fbo); // clean up our texture - Texture *t = texture_owner.get_or_null(rt->external.texture); + GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture); t->alloc_height = 0; t->alloc_width = 0; t->width = 0; t->height = 0; t->active = false; - texture_owner.free(rt->external.texture); + GLES3::TextureStorage::get_singleton()->texture_free(rt->external.texture); memdelete(t); rt->external.fbo = 0; } if (rt->depth) { - if (config.support_depth_texture) { + if (config->support_depth_texture) { glDeleteTextures(1, &rt->depth); } else { glDeleteRenderbuffers(1, &rt->depth); @@ -3302,7 +2089,7 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { rt->depth = 0; } - Texture *tex = texture_owner.get_or_null(rt->texture); + GLES3::Texture *tex = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture); tex->alloc_height = 0; tex->alloc_width = 0; tex->width = 0; @@ -3345,8 +2132,8 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { } RID RasterizerStorageGLES3::render_target_create() { - RenderTarget *rt = memnew(RenderTarget); - Texture *t = memnew(Texture); + GLES3::RenderTarget *rt = memnew(GLES3::RenderTarget); + GLES3::Texture *t = memnew(GLES3::Texture); t->type = RenderingDevice::TEXTURE_TYPE_2D; t->flags = 0; @@ -3368,12 +2155,12 @@ RID RasterizerStorageGLES3::render_target_create() { t->tex_id = 0; t->render_target = rt; - rt->texture = texture_owner.make_rid(t); + rt->texture = GLES3::TextureStorage::get_singleton()->make_rid(t); return render_target_owner.make_rid(rt); } void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int p_x, int p_y) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); rt->x = p_x; @@ -3381,7 +2168,7 @@ void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int } void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); if (p_width == rt->width && p_height == rt->height) { @@ -3401,14 +2188,14 @@ void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_w // TODO: convert to Size2i internally Size2i RasterizerStorageGLES3::render_target_get_size(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, Size2()); return Size2i(rt->width, rt->height); } RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, RID()); if (rt->external.fbo == 0) { @@ -3419,7 +2206,7 @@ RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) { } void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); if (p_texture_id == 0) { @@ -3433,13 +2220,13 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar } // clean up our texture - Texture *t = texture_owner.get_or_null(rt->external.texture); + GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture); t->alloc_height = 0; t->alloc_width = 0; t->width = 0; t->height = 0; t->active = false; - texture_owner.free(rt->external.texture); + GLES3::TextureStorage::get_singleton()->texture_free(rt->external.texture); memdelete(t); rt->external.fbo = 0; @@ -3447,7 +2234,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar rt->external.depth = 0; } } else { - Texture *t; + GLES3::Texture *t; if (rt->external.fbo == 0) { // create our fbo @@ -3455,7 +2242,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar bind_framebuffer(rt->external.fbo); // allocate a texture - t = memnew(Texture); + t = memnew(GLES3::Texture); t->type = RenderingDevice::TEXTURE_TYPE_2D; t->flags = 0; @@ -3478,14 +2265,14 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar t->tex_id = 0; t->render_target = rt; - rt->external.texture = texture_owner.make_rid(t); + rt->external.texture = GLES3::TextureStorage::get_singleton()->make_rid(t); } else { // bind our frame buffer bind_framebuffer(rt->external.fbo); // find our texture - t = texture_owner.get_or_null(rt->external.texture); + t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture); } // set our texture @@ -3504,7 +2291,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0); // seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :) - if (config.support_depth_texture) { + if (config->support_depth_texture) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); } else { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); @@ -3524,7 +2311,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar } void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::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 @@ -3556,21 +2343,21 @@ void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderT } bool RasterizerStorageGLES3::render_target_was_used(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, false); return rt->used_in_frame; } void RasterizerStorageGLES3::render_target_clear_used(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); rt->used_in_frame = false; } void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); if (rt->msaa == p_msaa) { @@ -3582,20 +2369,20 @@ void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target, RS::Vie _render_target_allocate(rt); } -//RasterizerStorageGLES3::RenderTarget * RasterizerStorageGLES3::render_target_get(RID p_render_target) +//RasterizerStorageGLES3::GLES3::RenderTarget * RasterizerStorageGLES3::render_target_get(RID p_render_target) //{ // return render_target_owner.get_or_null(p_render_target); //} void RasterizerStorageGLES3::render_target_set_use_fxaa(RID p_render_target, bool p_fxaa) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); rt->use_fxaa = p_fxaa; } void RasterizerStorageGLES3::render_target_set_use_debanding(RID p_render_target, bool p_debanding) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); if (p_debanding) { @@ -3606,7 +2393,7 @@ void RasterizerStorageGLES3::render_target_set_use_debanding(RID p_render_target } void RasterizerStorageGLES3::render_target_request_clear(RID p_render_target, const Color &p_clear_color) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); rt->clear_requested = true; rt->clear_color = p_clear_color; @@ -3617,18 +2404,18 @@ void RasterizerStorageGLES3::render_target_request_clear(RID p_render_target, co } bool RasterizerStorageGLES3::render_target_is_clear_requested(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, false); return rt->clear_requested; } Color RasterizerStorageGLES3::render_target_get_clear_request_color(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, Color()); return rt->clear_color; } void RasterizerStorageGLES3::render_target_disable_clear_request(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); rt->clear_requested = false; } @@ -3651,8 +2438,8 @@ void RasterizerStorageGLES3::render_target_mark_sdf_enabled(RID p_render_target, RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) { CanvasLightShadow *cls = memnew(CanvasLightShadow); - if (p_width > config.max_texture_size) { - p_width = config.max_texture_size; + if (p_width > config->max_texture_size) { + p_width = config->max_texture_size; } cls->size = p_width; @@ -3665,12 +2452,12 @@ RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) { glGenRenderbuffers(1, &cls->depth); glBindRenderbuffer(GL_RENDERBUFFER, cls->depth); - glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, cls->size, cls->height); + glRenderbufferStorage(GL_RENDERBUFFER, config->depth_buffer_internalformat, cls->size, cls->height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth); glGenTextures(1, &cls->distance); glBindTexture(GL_TEXTURE_2D, cls->distance); - if (config.use_rgba_2d_shadows) { + if (config->use_rgba_2d_shadows) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } else { #ifdef GLES_OVER_GL @@ -3822,33 +2609,23 @@ RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { bool RasterizerStorageGLES3::free(RID p_rid) { if (render_target_owner.owns(p_rid)) { - RenderTarget *rt = render_target_owner.get_or_null(p_rid); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_rid); _render_target_clear(rt); - Texture *t = texture_owner.get_or_null(rt->texture); + GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture); if (t) { - texture_owner.free(rt->texture); + GLES3::TextureStorage::get_singleton()->texture_free(rt->texture); memdelete(t); } render_target_owner.free(p_rid); memdelete(rt); return true; - } else if (texture_owner.owns(p_rid)) { - Texture *t = texture_owner.get_or_null(p_rid); - // can't free a render target texture - ERR_FAIL_COND_V(t->render_target, true); - if (t->canvas_texture) { - memdelete(t->canvas_texture); - } - - info.texture_mem -= t->total_data_size; - texture_owner.free(p_rid); - memdelete(t); - + } else if (GLES3::TextureStorage::get_singleton()->owns_texture(p_rid)) { + GLES3::TextureStorage::get_singleton()->texture_free(p_rid); return true; - } else if (canvas_texture_owner.owns(p_rid)) { - canvas_texture_owner.free(p_rid); + } else if (GLES3::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { + GLES3::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid); return true; } else if (sky_owner.owns(p_rid)) { Sky *sky = sky_owner.get_or_null(p_rid); @@ -4042,15 +2819,15 @@ bool RasterizerStorageGLES3::free(RID p_rid) { bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const { if (p_feature == "s3tc") { - return config.s3tc_supported; + return config->s3tc_supported; } if (p_feature == "etc") { - return config.etc_supported; + return config->etc_supported; } if (p_feature == "skinning_fallback") { - return config.use_skeleton_software; + return config->use_skeleton_software; } return false; @@ -4157,105 +2934,11 @@ RenderingDevice::DeviceType RasterizerStorageGLES3::get_video_adapter_type() con void RasterizerStorageGLES3::initialize() { RasterizerStorageGLES3::system_fbo = 0; + config = GLES3::Config::get_singleton(); + config->initialize(); - { - const GLubyte *extension_string = glGetString(GL_EXTENSIONS); - - Vector<String> extensions = String((const char *)extension_string).split(" "); - - for (int i = 0; i < extensions.size(); i++) { - config.extensions.insert(extensions[i]); - } - } - - config.keep_original_textures = true; // false - config.shrink_textures_x2 = false; - config.depth_internalformat = GL_DEPTH_COMPONENT; - config.depth_type = GL_UNSIGNED_INT; - -#ifdef GLES_OVER_GL - config.float_texture_supported = true; - config.s3tc_supported = true; - config.etc_supported = false; - config.support_npot_repeat_mipmap = true; - config.depth_buffer_internalformat = GL_DEPTH_COMPONENT24; -#else - config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float"); - config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc"); - config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1"); - config.support_npot_repeat_mipmap = config.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/ - config.depth_buffer_internalformat = GL_DEPTH_COMPONENT16; - config.depth_type = GL_UNSIGNED_INT; -#else - // on mobile check for 24 bit depth support for RenderBufferStorage - if (config.extensions.has("GL_OES_depth24")) { - config.depth_buffer_internalformat = _DEPTH_COMPONENT24_OES; - config.depth_type = GL_UNSIGNED_INT; - } else { - config.depth_buffer_internalformat = GL_DEPTH_COMPONENT16; - config.depth_type = GL_UNSIGNED_SHORT; - } -#endif -#endif - -#ifdef GLES_OVER_GL - //TODO: causes huge problems with desktop video drivers. Making false for now, needs to be true to render SCREEN_TEXTURE mipmaps - config.render_to_mipmap_supported = false; -#else - //check if mipmaps can be used for SCREEN_TEXTURE and Glow on Mobile and web platforms - config.render_to_mipmap_supported = config.extensions.has("GL_OES_fbo_render_mipmap") && config.extensions.has("GL_EXT_texture_lod"); -#endif - -#ifdef GLES_OVER_GL - config.use_rgba_2d_shadows = false; - config.support_depth_texture = true; - config.use_rgba_3d_shadows = false; - config.support_depth_cubemaps = true; -#else - config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg")); - config.support_depth_texture = config.extensions.has("GL_OES_depth_texture") || config.extensions.has("WEBGL_depth_texture"); - config.use_rgba_3d_shadows = !config.support_depth_texture; - config.support_depth_cubemaps = config.extensions.has("GL_OES_depth_texture_cube_map"); -#endif - -#ifdef GLES_OVER_GL - config.support_32_bits_indices = true; -#else - config.support_32_bits_indices = config.extensions.has("GL_OES_element_index_uint"); -#endif - -#ifdef GLES_OVER_GL - config.support_write_depth = true; -#elif defined(JAVASCRIPT_ENABLED) - config.support_write_depth = false; -#else - config.support_write_depth = config.extensions.has("GL_EXT_frag_depth"); -#endif - - config.support_half_float_vertices = true; -//every platform should support this except web, iOS has issues with their support, so add option to disable -#ifdef JAVASCRIPT_ENABLED - config.support_half_float_vertices = false; -#endif - bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float"); - if (disable_half_float) { - config.support_half_float_vertices = false; - } - - config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); - config.latc_supported = config.extensions.has("GL_EXT_texture_compression_latc"); - config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc"); - config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc"); - config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc") || config.extensions.has("EXT_texture_compression_bptc"); - config.srgb_decode_supported = config.extensions.has("GL_EXT_texture_sRGB_decode"); //determine formats for depth textures (or renderbuffers) - if (config.support_depth_texture) { + if (config->support_depth_texture) { // Will use texture for depth // have to manually see if we can create a valid framebuffer texture using UNSIGNED_INT, // as there is no extension to test for this. @@ -4265,7 +2948,7 @@ void RasterizerStorageGLES3::initialize() { GLuint depth; glGenTextures(1, &depth); glBindTexture(GL_TEXTURE_2D, depth); - glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config.depth_type, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config->depth_type, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -4285,19 +2968,19 @@ void RasterizerStorageGLES3::initialize() { // If it fails, test to see if it supports a framebuffer texture using UNSIGNED_SHORT // This is needed because many OSX devices don't support either UNSIGNED_INT or UNSIGNED_SHORT #ifdef GLES_OVER_GL - config.depth_internalformat = GL_DEPTH_COMPONENT16; + config->depth_internalformat = GL_DEPTH_COMPONENT16; #else // OES_depth_texture extension only specifies GL_DEPTH_COMPONENT. - config.depth_internalformat = GL_DEPTH_COMPONENT; + config->depth_internalformat = GL_DEPTH_COMPONENT; #endif - config.depth_type = GL_UNSIGNED_SHORT; + config->depth_type = GL_UNSIGNED_SHORT; glGenFramebuffers(1, &fbo); bind_framebuffer(fbo); glGenTextures(1, &depth); glBindTexture(GL_TEXTURE_2D, depth); - glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -4309,8 +2992,8 @@ void RasterizerStorageGLES3::initialize() { status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { //if it fails again depth textures aren't supported, use rgba shadows and renderbuffer for depth - config.support_depth_texture = false; - config.use_rgba_3d_shadows = true; + config->support_depth_texture = false; + config->use_rgba_3d_shadows = true; } bind_framebuffer_system(); @@ -4321,20 +3004,16 @@ void RasterizerStorageGLES3::initialize() { } //picky requirements for these - config.support_shadow_cubemaps = config.support_depth_texture && config.support_write_depth && config.support_depth_cubemaps; + config->support_shadow_cubemaps = config->support_depth_texture && config->support_write_depth && config->support_depth_cubemaps; frame.count = 0; frame.delta = 0; frame.current_rt = nullptr; frame.clear_request = false; - 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); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size); - // the use skeleton software path should be used if either float texture is not supported, // OR max_vertex_texture_image_units is zero - config.use_skeleton_software = (config.float_texture_supported == false) || (config.max_vertex_texture_image_units == 0); + config->use_skeleton_software = (config->float_texture_supported == false) || (config->max_vertex_texture_image_units == 0); shaders.copy.initialize(); shaders.copy_version = shaders.copy.version_create(); //TODO @@ -4438,7 +3117,7 @@ void RasterizerStorageGLES3::initialize() { // radical inverse vdc cache texture // used for cubemap filtering - if (true /*||config.float_texture_supported*/) { //uint8 is similar and works everywhere + if (true /*||config->float_texture_supported*/) { //uint8 is similar and works everywhere glGenTextures(1, &resources.radical_inverse_vdc_cache_tex); glActiveTexture(GL_TEXTURE0); @@ -4476,16 +3155,12 @@ void RasterizerStorageGLES3::initialize() { #ifdef GLES_OVER_GL //this needs to be enabled manually in OpenGL 2.1 - if (config.extensions.has("GL_ARB_seamless_cube_map")) { + if (config->extensions.has("GL_ARB_seamless_cube_map")) { glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); } glEnable(GL_POINT_SPRITE); glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); #endif - - config.force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); - config.use_fast_texture_filter = false; //GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter"); - //config.should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers"); } void RasterizerStorageGLES3::finalize() { @@ -4512,7 +3187,6 @@ void RasterizerStorageGLES3::update_dirty_resources() { RasterizerStorageGLES3::RasterizerStorageGLES3() { RasterizerStorageGLES3::system_fbo = 0; - config.should_orphan = true; } RasterizerStorageGLES3::~RasterizerStorageGLES3() { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index de984fa8df..ba457e54b0 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -40,6 +40,10 @@ #include "servers/rendering/renderer_storage.h" #include "servers/rendering/shader_compiler.h" #include "servers/rendering/shader_language.h" +#include "storage/canvas_texture_storage.h" +#include "storage/config.h" +#include "storage/render_target_storage.h" +#include "storage/texture_storage.h" #include "shaders/copy.glsl.gen.h" @@ -47,66 +51,13 @@ class RasterizerCanvasGLES3; class RasterizerSceneGLES3; class RasterizerStorageGLES3 : public RendererStorage { - friend class RasterizerGLES3; - - Thread::ID _main_thread_id = 0; - bool _is_main_thread(); - public: RasterizerCanvasGLES3 *canvas; RasterizerSceneGLES3 *scene; static GLuint system_fbo; - struct Config { - bool shrink_textures_x2; - bool use_fast_texture_filter; - bool use_skeleton_software; - - int max_vertex_texture_image_units; - int max_texture_image_units; - int max_texture_size; - - // TODO implement wireframe in OpenGL - // bool generate_wireframes; - - Set<String> extensions; - - bool float_texture_supported; - bool s3tc_supported; - bool latc_supported; - bool rgtc_supported; - bool bptc_supported; - bool etc_supported; - bool etc2_supported; - bool srgb_decode_supported; - - bool keep_original_textures; - - bool force_vertex_shading; - - bool use_rgba_2d_shadows; - bool use_rgba_3d_shadows; - - bool support_32_bits_indices; - bool support_write_depth; - bool support_half_float_vertices; - bool support_npot_repeat_mipmap; - bool support_depth_texture; - bool support_depth_cubemaps; - - bool support_shadow_cubemaps; - - bool render_to_mipmap_supported; - - GLuint depth_internalformat; - GLuint depth_type; - GLuint depth_buffer_internalformat; - - // 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; - } config; + GLES3::Config *config; struct Resources { GLuint white_tex; @@ -180,334 +131,7 @@ public: //////////////////////////////////API//////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// - bool can_create_resources_async() const override; - - // TEXTURE API - - enum OpenGLTextureFlags { - TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available - TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping - TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter - TEXTURE_FLAG_ANISOTROPIC_FILTER = 8, - TEXTURE_FLAG_CONVERT_TO_LINEAR = 16, - TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored - TEXTURE_FLAG_USED_FOR_STREAMING = 2048, - TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER - }; - - /* CANVAS TEXTURE API (2D) */ - - struct CanvasTexture { - RID diffuse; - RID normal_map; - RID specular; - Color specular_color = Color(1, 1, 1, 1); - float shininess = 1.0; - - RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; - RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; - - Size2i size_cache = Size2i(1, 1); - bool use_normal_cache = false; - bool use_specular_cache = false; - bool cleared_cache = true; - }; - - RID_Owner<CanvasTexture, true> canvas_texture_owner; - - struct RenderTarget; - - struct Texture { - RID self; - - Texture *proxy; - Set<Texture *> proxy_owners; - - String path; - uint32_t flags; - int width, height, depth; - int alloc_width, alloc_height; - Image::Format format; - RenderingDevice::TextureType type; - - GLenum target; - GLenum gl_format_cache; - GLenum gl_internal_format_cache; - GLenum gl_type_cache; - - int data_size; - int total_data_size; - bool ignore_mipmaps; - - bool compressed; - - bool srgb; - - int mipmaps; - - bool resize_to_po2; - - bool active; - GLenum tex_id; - - uint16_t stored_cube_sides; - - RenderTarget *render_target; - - Vector<Ref<Image>> images; - - bool redraw_if_visible; - - RS::TextureDetectCallback detect_3d; - void *detect_3d_ud; - - RS::TextureDetectCallback detect_srgb; - void *detect_srgb_ud; - - RS::TextureDetectCallback detect_normal; - void *detect_normal_ud; - - CanvasTexture *canvas_texture = nullptr; - - // some silly opengl shenanigans where - // texture coords start from bottom left, means we need to draw render target textures upside down - // to be compatible with vulkan etc. - bool is_upside_down() const { - if (proxy) { - return proxy->is_upside_down(); - } - - return render_target != nullptr; - } - - Texture() { - create(); - } - - _ALWAYS_INLINE_ Texture *get_ptr() { - if (proxy) { - return proxy; //->get_ptr(); only one level of indirection, else not inlining possible. - } else { - return this; - } - } - - ~Texture() { - destroy(); - - if (tex_id != 0) { - glDeleteTextures(1, &tex_id); - } - } - - void copy_from(const Texture &o) { - proxy = o.proxy; - flags = o.flags; - width = o.width; - height = o.height; - alloc_width = o.alloc_width; - alloc_height = o.alloc_height; - format = o.format; - type = o.type; - target = o.target; - data_size = o.data_size; - total_data_size = o.total_data_size; - ignore_mipmaps = o.ignore_mipmaps; - compressed = o.compressed; - mipmaps = o.mipmaps; - resize_to_po2 = o.resize_to_po2; - active = o.active; - tex_id = o.tex_id; - stored_cube_sides = o.stored_cube_sides; - render_target = o.render_target; - redraw_if_visible = o.redraw_if_visible; - detect_3d = o.detect_3d; - detect_3d_ud = o.detect_3d_ud; - detect_srgb = o.detect_srgb; - detect_srgb_ud = o.detect_srgb_ud; - detect_normal = o.detect_normal; - detect_normal_ud = o.detect_normal_ud; - - images.clear(); - } - - void create() { - proxy = nullptr; - flags = 0; - width = 0; - height = 0; - alloc_width = 0; - alloc_height = 0; - format = Image::FORMAT_L8; - type = RenderingDevice::TEXTURE_TYPE_2D; - target = 0; - data_size = 0; - total_data_size = 0; - ignore_mipmaps = false; - compressed = false; - mipmaps = 0; - resize_to_po2 = false; - active = false; - tex_id = 0; - stored_cube_sides = 0; - render_target = nullptr; - redraw_if_visible = false; - detect_3d = nullptr; - detect_3d_ud = nullptr; - detect_srgb = nullptr; - detect_srgb_ud = nullptr; - detect_normal = nullptr; - detect_normal_ud = nullptr; - } - void destroy() { - images.clear(); - - for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) { - E->get()->proxy = nullptr; - } - - if (proxy) { - proxy->proxy_owners.erase(this); - } - } - - // texture state - void GLSetFilter(GLenum p_target, RS::CanvasItemTextureFilter p_filter) { - if (p_filter == state_filter) { - return; - } - state_filter = p_filter; - GLint pmin = GL_LINEAR; // param min - GLint pmag = GL_LINEAR; // param mag - switch (state_filter) { - default: { - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { - pmin = GL_LINEAR_MIPMAP_LINEAR; - pmag = GL_LINEAR; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { - pmin = GL_NEAREST; - pmag = GL_NEAREST; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { - pmin = GL_NEAREST_MIPMAP_NEAREST; - pmag = GL_NEAREST; - } break; - } - glTexParameteri(p_target, GL_TEXTURE_MIN_FILTER, pmin); - glTexParameteri(p_target, GL_TEXTURE_MAG_FILTER, pmag); - } - void GLSetRepeat(GLenum p_target, RS::CanvasItemTextureRepeat p_repeat) { - if (p_repeat == state_repeat) { - return; - } - state_repeat = p_repeat; - GLint prep = GL_CLAMP_TO_EDGE; // parameter repeat - switch (state_repeat) { - default: { - } break; - case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { - prep = GL_REPEAT; - } break; - case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { - prep = GL_MIRRORED_REPEAT; - } break; - } - glTexParameteri(p_target, GL_TEXTURE_WRAP_S, prep); - glTexParameteri(p_target, GL_TEXTURE_WRAP_T, prep); - } - - private: - RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; - RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; - }; - - mutable RID_PtrOwner<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; - - void _texture_set_state_from_flags(Texture *p_tex); - - // new - RID texture_allocate() override; - void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override; - void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override; - void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override; - void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent - - void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override; - void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {} - void texture_proxy_update(RID p_proxy, RID p_base) override {} - - void texture_2d_placeholder_initialize(RID p_texture) override; - void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override; - void texture_3d_placeholder_initialize(RID p_texture) override; - - Ref<Image> texture_2d_get(RID p_texture) const override; - Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); } - Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); } - - void texture_replace(RID p_texture, RID p_by_texture) override; - //void texture_set_size_override(RID p_texture, int p_width, int p_height) override {} - - void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - - // old - uint32_t texture_get_width(RID p_texture) const; - uint32_t texture_get_height(RID p_texture) const; - -private: - RID texture_create(); - - //void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT); - void _texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT); - - void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); - void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0); - //Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const; - void texture_set_flags(RID p_texture, uint32_t p_flags); - uint32_t texture_get_flags(RID p_texture) const; - Image::Format texture_get_format(RID p_texture) const; - RenderingDevice::TextureType texture_get_type(RID p_texture) const; - uint32_t texture_get_texid(RID p_texture) const; - uint32_t texture_get_depth(RID p_texture) const; - void texture_set_size_override(RID p_texture, int p_width, int p_height) override; - - void texture_bind(RID p_texture, uint32_t p_texture_no); - - void texture_set_path(RID p_texture, const String &p_path) override; - String texture_get_path(RID p_texture) const override; - - void texture_set_shrink_all_x2_on_set_data(bool p_enable); - - void texture_debug_usage(List<RS::TextureInfo> *r_info) override; - - RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const; - - void textures_keep_original(bool p_enable); - - void texture_set_proxy(RID p_texture, RID p_proxy); - Size2 texture_size_with_proxy(RID p_texture) override; - - void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; - void texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); - void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; - void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {} - - void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override; - public: - RID canvas_texture_allocate() override; - void canvas_texture_initialize(RID p_rid) override; - - void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override; - void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) override; - - void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) override; - void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) override; - /* SKY API */ // not sure if used in godot 4? struct Sky { @@ -971,6 +595,9 @@ public: AABB decal_get_aabb(RID p_decal) const override; + void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} + void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} + /* VOXEL GI API */ RID voxel_gi_allocate() override; @@ -1151,85 +778,10 @@ public: // RENDER TARGET - struct RenderTarget { - RID self; - GLuint fbo = 0; - GLuint color = 0; - GLuint depth = 0; - - GLuint multisample_fbo = 0; - GLuint multisample_color = 0; - GLuint multisample_depth = 0; - bool multisample_active = false; - - struct Effect { - GLuint fbo = 0; - int width = 0; - int height = 0; - - GLuint color = 0; - }; - - Effect copy_screen_effect; - - struct MipMaps { - struct Size { - GLuint fbo = 0; - GLuint color = 0; - int width = 0; - int height = 0; - }; - - Vector<Size> sizes; - GLuint color = 0; - int levels = 0; - }; - - MipMaps mip_maps[2]; - - struct External { - GLuint fbo = 0; - GLuint color = 0; - GLuint depth = 0; - RID texture; - } external; - - int x = 0; - int y = 0; - int width = 0; - int height = 0; - - bool flags[RENDER_TARGET_FLAG_MAX] = {}; - - // 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; - - bool use_fxaa = false; - bool use_debanding = false; - - RID texture; - - bool used_dof_blur_near = false; - bool mip_maps_allocated = false; - - Color clear_color = Color(1, 1, 1, 1); - bool clear_requested = false; - - RenderTarget() { - for (int i = 0; i < RENDER_TARGET_FLAG_MAX; ++i) { - flags[i] = false; - } - external.fbo = 0; - } - }; - - mutable RID_PtrOwner<RenderTarget> render_target_owner; + mutable RID_PtrOwner<GLES3::RenderTarget> render_target_owner; - void _render_target_clear(RenderTarget *rt); - void _render_target_allocate(RenderTarget *rt); + void _render_target_clear(GLES3::RenderTarget *rt); + void _render_target_allocate(GLES3::RenderTarget *rt); void _set_current_render_target(RID p_render_target); RID render_target_create() override; @@ -1262,7 +814,7 @@ public: void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override; // access from canvas - // RenderTarget * render_target_get(RID p_render_target); + // GLES3::RenderTarget * render_target_get(RID p_render_target); /* CANVAS SHADOW */ @@ -1301,7 +853,7 @@ public: bool free(RID p_rid) override; struct Frame { - RenderTarget *current_rt; + GLES3::RenderTarget *current_rt; // these 2 may have been superseded by the equivalents in the render target. // these may be able to be removed. @@ -1408,7 +960,7 @@ inline bool RasterizerStorageGLES3::safe_buffer_sub_data(unsigned int p_total_bu inline void RasterizerStorageGLES3::buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target, GLenum p_usage, bool p_optional_orphan) const { // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData // Was previously #ifndef GLES_OVER_GL however this causes stalls on desktop mac also (and possibly other) - if (!p_optional_orphan || (config.should_orphan)) { + if (!p_optional_orphan || (config->should_orphan)) { glBufferData(p_target, p_buffer_size, nullptr, p_usage); #ifdef RASTERIZER_EXTRA_CHECKS // fill with garbage off the end of the array diff --git a/drivers/gles3/storage/SCsub b/drivers/gles3/storage/SCsub new file mode 100644 index 0000000000..91e1140b75 --- /dev/null +++ b/drivers/gles3/storage/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.drivers_sources, "*.cpp") diff --git a/drivers/gles3/storage/canvas_texture_storage.cpp b/drivers/gles3/storage/canvas_texture_storage.cpp new file mode 100644 index 0000000000..fe12700c21 --- /dev/null +++ b/drivers/gles3/storage/canvas_texture_storage.cpp @@ -0,0 +1,96 @@ +/*************************************************************************/ +/* canvas_texture_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "canvas_texture_storage.h" + +using namespace GLES3; + +CanvasTextureStorage *CanvasTextureStorage::singleton = nullptr; + +CanvasTextureStorage *CanvasTextureStorage::get_singleton() { + return singleton; +} + +CanvasTextureStorage::CanvasTextureStorage() { + singleton = this; +} + +CanvasTextureStorage::~CanvasTextureStorage() { + singleton = nullptr; +} + +RID CanvasTextureStorage::canvas_texture_allocate() { + return canvas_texture_owner.allocate_rid(); +} + +void CanvasTextureStorage::canvas_texture_initialize(RID p_rid) { + canvas_texture_owner.initialize_rid(p_rid); +} + +void CanvasTextureStorage::canvas_texture_free(RID p_rid) { + canvas_texture_owner.free(p_rid); +} + +void CanvasTextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + switch (p_channel) { + case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { + ct->diffuse = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { + ct->normal_map = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { + ct->specular = p_texture; + } break; + } +} + +void CanvasTextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ct->specular_color.r = p_specular_color.r; + ct->specular_color.g = p_specular_color.g; + ct->specular_color.b = p_specular_color.b; + ct->specular_color.a = p_shininess; +} + +void CanvasTextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ct->texture_filter = p_filter; +} + +void CanvasTextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ct->texture_repeat = p_repeat; +} + +#endif // !GLES3_ENABLED diff --git a/drivers/gles3/storage/canvas_texture_storage.h b/drivers/gles3/storage/canvas_texture_storage.h new file mode 100644 index 0000000000..5930e927fe --- /dev/null +++ b/drivers/gles3/storage/canvas_texture_storage.h @@ -0,0 +1,87 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_GLES3_H +#define CANVAS_TEXTURE_STORAGE_GLES3_H + +#ifdef GLES3_ENABLED + +#include "core/templates/rid_owner.h" +#include "servers/rendering/storage/canvas_texture_storage.h" + +namespace GLES3 { + +struct CanvasTexture { + RID diffuse; + RID normal_map; + RID specular; + Color specular_color = Color(1, 1, 1, 1); + float shininess = 1.0; + + RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; + RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; + + Size2i size_cache = Size2i(1, 1); + bool use_normal_cache = false; + bool use_specular_cache = false; + bool cleared_cache = true; +}; + +class CanvasTextureStorage : public RendererCanvasTextureStorage { +private: + static CanvasTextureStorage *singleton; + + RID_Owner<CanvasTexture, true> canvas_texture_owner; + +public: + static CanvasTextureStorage *get_singleton(); + + CanvasTextureStorage(); + virtual ~CanvasTextureStorage(); + + CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); }; + bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; + + virtual RID canvas_texture_allocate() override; + virtual void canvas_texture_initialize(RID p_rid) override; + virtual void canvas_texture_free(RID p_rid) override; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override; +}; + +} // namespace GLES3 + +#endif // !GLES3_ENABLED + +#endif // !CANVAS_TEXTURE_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp new file mode 100644 index 0000000000..1f66401427 --- /dev/null +++ b/drivers/gles3/storage/config.cpp @@ -0,0 +1,156 @@ +/*************************************************************************/ +/* config.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "config.h" +#include "core/templates/vector.h" + +using namespace GLES3; + +Config *Config::singleton = nullptr; + +Config::Config() { + singleton = this; + should_orphan = true; +} + +Config::~Config() { + singleton = nullptr; +} + +void Config::initialize() { + { + const GLubyte *extension_string = glGetString(GL_EXTENSIONS); + + Vector<String> exts = String((const char *)extension_string).split(" "); + + for (int i = 0; i < exts.size(); i++) { + extensions.insert(exts[i]); + } + } + + keep_original_textures = true; // false + shrink_textures_x2 = false; + depth_internalformat = GL_DEPTH_COMPONENT; + depth_type = GL_UNSIGNED_INT; + +#ifdef GLES_OVER_GL + float_texture_supported = true; + s3tc_supported = true; + etc_supported = false; + support_npot_repeat_mipmap = true; + depth_buffer_internalformat = GL_DEPTH_COMPONENT24; +#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"); + 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 +#endif + +#ifdef GLES_OVER_GL + //TODO: causes huge problems with desktop video drivers. Making false for now, needs to be true to render SCREEN_TEXTURE mipmaps + render_to_mipmap_supported = false; +#else + //check if mipmaps can be used for SCREEN_TEXTURE and Glow on Mobile and web platforms + render_to_mipmap_supported = extensions.has("GL_OES_fbo_render_mipmap") && extensions.has("GL_EXT_texture_lod"); +#endif + +#ifdef GLES_OVER_GL + use_rgba_2d_shadows = false; + support_depth_texture = true; + use_rgba_3d_shadows = false; + support_depth_cubemaps = true; +#else + use_rgba_2d_shadows = !(float_texture_supported && extensions.has("GL_EXT_texture_rg")); + support_depth_texture = extensions.has("GL_OES_depth_texture") || extensions.has("WEBGL_depth_texture"); + use_rgba_3d_shadows = !support_depth_texture; + 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 + + support_half_float_vertices = true; +//every platform should support this except web, iOS has issues with their support, so add option to disable +#ifdef JAVASCRIPT_ENABLED + support_half_float_vertices = false; +#endif + bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float"); + if (disable_half_float) { + support_half_float_vertices = false; + } + + etc_supported = extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); + latc_supported = extensions.has("GL_EXT_texture_compression_latc"); + bptc_supported = extensions.has("GL_ARB_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"); + bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc"); + srgb_decode_supported = extensions.has("GL_EXT_texture_sRGB_decode"); + + 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); + + force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); + use_fast_texture_filter = false; //GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter"); + // should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers"); +} + +#endif // GLES3_ENABLED diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h new file mode 100644 index 0000000000..25bd3fd9a1 --- /dev/null +++ b/drivers/gles3/storage/config.h @@ -0,0 +1,113 @@ +/*************************************************************************/ +/* config.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CONFIG_GLES3_H +#define CONFIG_GLES3_H + +#ifdef GLES3_ENABLED + +#include "core/string/ustring.h" +#include "core/templates/set.h" + +// This must come first to avoid windows.h mess +#include "platform_config.h" +#ifndef OPENGL_INCLUDE_H +#include <GLES3/gl3.h> +#else +#include OPENGL_INCLUDE_H +#endif + +namespace GLES3 { + +class Config { +private: + static Config *singleton; + +public: + bool shrink_textures_x2; + bool use_fast_texture_filter; + bool use_skeleton_software; + + int max_vertex_texture_image_units; + int max_texture_image_units; + int max_texture_size; + + // TODO implement wireframe in OpenGL + // bool generate_wireframes; + + Set<String> extensions; + + bool float_texture_supported; + bool s3tc_supported; + bool latc_supported; + bool rgtc_supported; + bool bptc_supported; + bool etc_supported; + bool etc2_supported; + bool srgb_decode_supported; + + bool keep_original_textures; + + bool force_vertex_shading; + + bool use_rgba_2d_shadows; + bool use_rgba_3d_shadows; + + bool support_32_bits_indices; + bool support_write_depth; + bool support_half_float_vertices; + bool support_npot_repeat_mipmap; + bool support_depth_texture; + bool support_depth_cubemaps; + + bool support_shadow_cubemaps; + + bool render_to_mipmap_supported; + + GLuint depth_internalformat; + GLuint depth_type; + GLuint depth_buffer_internalformat; + + // 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; + + static Config *get_singleton() { return singleton; }; + + Config(); + ~Config(); + void initialize(); +}; + +} // namespace GLES3 + +#endif // GLES3_ENABLED + +#endif // !CONFIG_GLES3_H diff --git a/drivers/gles3/storage/render_target_storage.h b/drivers/gles3/storage/render_target_storage.h new file mode 100644 index 0000000000..816cc76e40 --- /dev/null +++ b/drivers/gles3/storage/render_target_storage.h @@ -0,0 +1,132 @@ +/*************************************************************************/ +/* render_target_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDER_TARGET_STORAGE_GLES3_H +#define RENDER_TARGET_STORAGE_GLES3_H + +#ifdef GLES3_ENABLED + +#include "core/templates/rid_owner.h" +#include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_storage.h" // included until we move stuff into storage/render_target_storage.h +// #include "servers/rendering/storage/render_target_storage.h" + +// This must come first to avoid windows.h mess +#include "platform_config.h" +#ifndef OPENGL_INCLUDE_H +#include <GLES3/gl3.h> +#else +#include OPENGL_INCLUDE_H +#endif + +namespace GLES3 { + +// NOTE, this class currently is just a container for the the RenderTarget struct and is not yet implemented further, we'll do that next after we finish with TextureStorage + +struct RenderTarget { + RID self; + GLuint fbo = 0; + GLuint color = 0; + GLuint depth = 0; + + GLuint multisample_fbo = 0; + GLuint multisample_color = 0; + GLuint multisample_depth = 0; + bool multisample_active = false; + + struct Effect { + GLuint fbo = 0; + int width = 0; + int height = 0; + + GLuint color = 0; + }; + + Effect copy_screen_effect; + + struct MipMaps { + struct Size { + GLuint fbo = 0; + GLuint color = 0; + int width = 0; + int height = 0; + }; + + Vector<Size> sizes; + GLuint color = 0; + int levels = 0; + }; + + MipMaps mip_maps[2]; + + struct External { + GLuint fbo = 0; + GLuint color = 0; + GLuint depth = 0; + RID texture; + } external; + + int x = 0; + int y = 0; + int width = 0; + int height = 0; + + bool flags[RendererStorage::RENDER_TARGET_FLAG_MAX] = {}; + + // 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; + + bool use_fxaa = false; + bool use_debanding = false; + + RID texture; + + bool used_dof_blur_near = false; + bool mip_maps_allocated = false; + + Color clear_color = Color(1, 1, 1, 1); + bool clear_requested = false; + + RenderTarget() { + for (int i = 0; i < RendererStorage::RENDER_TARGET_FLAG_MAX; ++i) { + flags[i] = false; + } + external.fbo = 0; + } +}; + +} // namespace GLES3 + +#endif // !GLES3_ENABLED + +#endif // !RENDER_TARGET_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp new file mode 100644 index 0000000000..d199b1032e --- /dev/null +++ b/drivers/gles3/storage/texture_storage.cpp @@ -0,0 +1,1211 @@ +/*************************************************************************/ +/* texture_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "texture_storage.h" +#include "config.h" + +using namespace GLES3; + +TextureStorage *TextureStorage::singleton = nullptr; + +TextureStorage *TextureStorage::get_singleton() { + return singleton; +} + +TextureStorage::TextureStorage() { + singleton = this; +} + +TextureStorage::~TextureStorage() { + singleton = nullptr; +} + +void TextureStorage::set_main_thread_id(Thread::ID p_id) { + _main_thread_id = p_id; +} + +bool TextureStorage::_is_main_thread() { + //#if defined DEBUG_ENABLED && defined TOOLS_ENABLED + // must be called from main thread in OpenGL + bool is_main_thread = _main_thread_id == Thread::get_caller_id(); + //#endif + return is_main_thread; +} + +bool TextureStorage::can_create_resources_async() const { + return false; +} + +static const GLenum _cube_side_enum[6] = { + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, +}; + +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 { + Config *config = Config::get_singleton(); + r_gl_format = 0; + Ref<Image> image = p_image; + r_compressed = false; + r_real_format = p_format; + + bool need_decompress = false; + + switch (p_format) { + case Image::FORMAT_L8: { +#ifdef GLES_OVER_GL + r_gl_internal_format = GL_R8; + r_gl_format = GL_RED; + r_gl_type = GL_UNSIGNED_BYTE; +#else + r_gl_internal_format = GL_LUMINANCE; + r_gl_format = GL_LUMINANCE; + r_gl_type = GL_UNSIGNED_BYTE; +#endif + } break; + case Image::FORMAT_LA8: { +#ifdef GLES_OVER_GL + r_gl_internal_format = GL_RG8; + r_gl_format = GL_RG; + r_gl_type = GL_UNSIGNED_BYTE; +#else + r_gl_internal_format = GL_LUMINANCE_ALPHA; + r_gl_format = GL_LUMINANCE_ALPHA; + r_gl_type = GL_UNSIGNED_BYTE; +#endif + } break; + case Image::FORMAT_R8: { + r_gl_internal_format = GL_R8; + r_gl_format = GL_RED; + r_gl_type = GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_RG8: { + r_gl_internal_format = GL_RG8; + r_gl_format = GL_RG; + r_gl_type = GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_RGB8: { + 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: { + r_gl_internal_format = GL_RGBA4; + r_gl_format = GL_RGBA; + 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; + r_gl_type = GL_FLOAT; + + } break; + case Image::FORMAT_RGF: { + r_gl_internal_format = GL_RG32F; + r_gl_format = GL_RG; + r_gl_type = GL_FLOAT; + + } break; + case Image::FORMAT_RGBF: { + r_gl_internal_format = GL_RGB32F; + r_gl_format = GL_RGB; + r_gl_type = GL_FLOAT; + + } break; + case Image::FORMAT_RGBAF: { + r_gl_internal_format = GL_RGBA32F; + r_gl_format = GL_RGBA; + r_gl_type = GL_FLOAT; + + } break; + case Image::FORMAT_RH: { + r_gl_internal_format = GL_R16F; + r_gl_format = GL_RED; + r_gl_type = GL_HALF_FLOAT; + } break; + case Image::FORMAT_RGH: { + r_gl_internal_format = GL_RG16F; + r_gl_format = GL_RG; + r_gl_type = GL_HALF_FLOAT; + + } break; + case Image::FORMAT_RGBH: { + r_gl_internal_format = GL_RGB16F; + r_gl_format = GL_RGB; + r_gl_type = GL_HALF_FLOAT; + + } break; + case Image::FORMAT_RGBAH: { + r_gl_internal_format = GL_RGBA16F; + r_gl_format = GL_RGBA; + r_gl_type = GL_HALF_FLOAT; + + } break; + case Image::FORMAT_RGBE9995: { + r_gl_internal_format = GL_RGB9_E5; + r_gl_format = GL_RGB; + r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV; + + } break; + case Image::FORMAT_DXT1: { + if (config->s3tc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_DXT3: { + if (config->s3tc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_DXT5: { + if (config->s3tc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_RGTC_R: { + if (config->rgtc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_RGTC_RG: { + if (config->rgtc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_BPTC_RGBA: { + if (config->bptc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_BPTC_UNORM; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_BPTC_RGBF: { + if (config->bptc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; + r_gl_format = GL_RGB; + r_gl_type = GL_FLOAT; + r_compressed = true; + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_BPTC_RGBFU: { + if (config->bptc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; + r_gl_format = GL_RGB; + r_gl_type = GL_FLOAT; + r_compressed = true; + } else { + 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; + r_gl_format = GL_RED; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC2_R11S: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_SIGNED_R11_EAC; + r_gl_format = GL_RED; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC2_RG11: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RG11_EAC; + r_gl_format = GL_RG; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC2_RG11S: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_SIGNED_RG11_EAC; + r_gl_format = GL_RG; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + 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; + } + } break; + case Image::FORMAT_ETC2_RGBA8: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA8_ETC2_EAC; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC2_RGB8A1: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + 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(Ref<Image>()); + } + } + + if (need_decompress || p_force_decompress) { + if (!image.is_null()) { + image = image->duplicate(); + image->decompress(); + ERR_FAIL_COND_V(image->is_compressed(), image); + switch (image->get_format()) { + case Image::FORMAT_RGB8: { + r_gl_format = GL_RGB; + r_gl_internal_format = GL_RGB; + r_gl_type = GL_UNSIGNED_BYTE; + r_real_format = Image::FORMAT_RGB8; + r_compressed = false; + } break; + case Image::FORMAT_RGBA8: { + r_gl_format = GL_RGBA; + r_gl_internal_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_real_format = Image::FORMAT_RGBA8; + r_compressed = false; + } break; + default: { + image->convert(Image::FORMAT_RGBA8); + r_gl_format = GL_RGBA; + r_gl_internal_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_real_format = Image::FORMAT_RGBA8; + r_compressed = false; + + } break; + } + } + + return image; + } + + return p_image; +} + +void TextureStorage::_texture_set_state_from_flags(Texture *p_tex) { + // Config *config = Config::get_singleton(); + + if ((p_tex->flags & TEXTURE_FLAG_MIPMAPS) && !p_tex->ignore_mipmaps) { + if (p_tex->flags & TEXTURE_FLAG_FILTER) { + // these do not exactly correspond ... + p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS); + //texture->glTexParam_MinFilter(texture->target, config->use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); + } else { + p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS); + //texture->glTexParam_MinFilter(texture->target, config->use_fast_texture_filter ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR); + } + } else { + if (p_tex->flags & TEXTURE_FLAG_FILTER) { + p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR); + //texture->glTexParam_MinFilter(texture->target, GL_LINEAR); + } else { + p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST); + //texture->glTexParam_MinFilter(texture->target, GL_NEAREST); + } + } + + if (((p_tex->flags & TEXTURE_FLAG_REPEAT) || (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT)) && p_tex->target != GL_TEXTURE_CUBE_MAP) { + if (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT) { + p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); + } else { + p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + } + } else { + p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + } +} + +void TextureStorage::_texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags) { + // GLenum format; + // GLenum internal_format; + // GLenum type; + + // bool compressed = false; + + // Config *config = Config::get_singleton(); + + if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { + p_flags &= ~TEXTURE_FLAG_MIPMAPS; // no mipies for video + } + + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + texture->width = p_width; + texture->height = p_height; + texture->format = p_format; + texture->flags = p_flags; + texture->stored_cube_sides = 0; + texture->type = p_type; + + switch (p_type) { + case RenderingDevice::TEXTURE_TYPE_2D: { + texture->target = GL_TEXTURE_2D; + texture->images.resize(1); + } break; + // case RenderingDevice::TEXTURE_TYPE_EXTERNAL: { + //#ifdef ANDROID_ENABLED + // texture->target = _GL_TEXTURE_EXTERNAL_OES; + //#else + // texture->target = GL_TEXTURE_2D; + //#endif + // texture->images.resize(0); + // } break; + case RenderingDevice::TEXTURE_TYPE_CUBE: { + texture->target = GL_TEXTURE_CUBE_MAP; + texture->images.resize(6); + } break; + case RenderingDevice::TEXTURE_TYPE_2D_ARRAY: + case RenderingDevice::TEXTURE_TYPE_3D: { + texture->target = GL_TEXTURE_3D; + ERR_PRINT("3D textures and Texture Arrays are not supported in OpenGL. Please switch to the Vulkan backend."); + return; + } break; + default: { + ERR_PRINT("Unknown texture type!"); + return; + } + } + +#if 0 + // if (p_type != RS::TEXTURE_TYPE_EXTERNAL) { + if (p_type == RenderingDevice::TEXTURE_TYPE_2D) { + texture->alloc_width = texture->width; + texture->alloc_height = texture->height; + texture->resize_to_po2 = false; + if (!config->support_npot_repeat_mipmap) { + int po2_width = next_power_of_2(p_width); + int po2_height = next_power_of_2(p_height); + + bool is_po2 = p_width == po2_width && p_height == po2_height; + + if (!is_po2 && (p_flags & TEXTURE_FLAG_REPEAT || p_flags & TEXTURE_FLAG_MIPMAPS)) { + if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { + //not supported + ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled."); + texture->flags &= ~(TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS); + } else { + texture->alloc_height = po2_height; + texture->alloc_width = po2_width; + texture->resize_to_po2 = true; + } + } + } + + GLenum format; + GLenum internal_format; + GLenum type; + bool compressed = false; + + Image::Format real_format; + _get_gl_image_and_format(Ref<Image>(), + texture->format, + texture->flags, + real_format, + format, + internal_format, + type, + compressed, + texture->resize_to_po2); + + texture->gl_format_cache = format; + texture->gl_type_cache = type; + texture->gl_internal_format_cache = internal_format; + texture->data_size = 0; + texture->mipmaps = 1; + + texture->compressed = compressed; + } +#endif + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + // if (p_type == RS::TEXTURE_TYPE_EXTERNAL) { + // glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // glTexParameteri(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + // glTexParameteri(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + // } else if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { + // //prealloc if video + // glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL); + // } + + texture->active = true; +} + +RID TextureStorage::texture_create() { + ERR_FAIL_COND_V(!_is_main_thread(), RID()); + + Texture *texture = memnew(Texture); + ERR_FAIL_COND_V(!texture, RID()); + glGenTextures(1, &texture->tex_id); + texture->active = false; + texture->total_data_size = 0; + + return texture_owner.make_rid(texture); +} + +RID TextureStorage::texture_allocate() { + RID id = texture_create(); + ERR_FAIL_COND_V(id == RID(), id); + return id; +} + +void TextureStorage::texture_free(RID p_rid) { + Texture *t = texture_owner.get_or_null(p_rid); + + // can't free a render target texture + ERR_FAIL_COND(t->render_target); + if (t->canvas_texture) { + memdelete(t->canvas_texture); + } + + // info.texture_mem -= t->total_data_size; // TODO make this work again!! + texture_owner.free(p_rid); + memdelete(t); +} + +void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + int w = p_image->get_width(); + int h = p_image->get_height(); + + _texture_allocate_internal(p_texture, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0); + texture_set_data(p_texture, p_image); +} + +void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { +} + +void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { +} + +void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) { + texture_set_proxy(p_texture, p_base); +} + +//RID TextureStorage::texture_2d_create(const Ref<Image> &p_image) { +// RID id = texture_create(); +// ERR_FAIL_COND_V(id == RID(), id); + +// int w = p_image->get_width(); +// int h = p_image->get_height(); + +// texture_allocate(id, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0); + +// texture_set_data(id, p_image); + +// return id; +//} + +//RID TextureStorage::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { +// return RID(); +//} + +//void TextureStorage::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) { +// // only 1 layer so far +// texture_set_data(p_texture, p_image); +//} + +void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { + // only 1 layer so far + texture_set_data(p_texture, p_image); +} + +void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { +} + +void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) { +} + +void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { +} + +Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Ref<Image>()); + + /* +#ifdef TOOLS_ENABLED + if (tex->image_cache_2d.is_valid()) { + return tex->image_cache_2d; + } +#endif + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); + Ref<Image> image; + image.instance(); + image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + ERR_FAIL_COND_V(image->empty(), Ref<Image>()); + if (tex->format != tex->validated_format) { + image->convert(tex->format); + } + +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + tex->image_cache_2d = image; + } +#endif +*/ + ERR_FAIL_COND_V(!tex->images.size(), Ref<Image>()); + + return tex->images[0]; + + // return image; + + // return Ref<Image>(); +} + +void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { + Texture *tex_to = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex_to); + Texture *tex_from = texture_owner.get_or_null(p_by_texture); + ERR_FAIL_COND(!tex_from); + + tex_to->destroy(); + tex_to->copy_from(*tex_from); + + // copy image data and upload to GL + tex_to->images.resize(tex_from->images.size()); + + for (int n = 0; n < tex_from->images.size(); n++) { + texture_set_data(p_texture, tex_from->images[n], n); + } + + texture_free(p_by_texture); +} + +void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND(!texture); + ERR_FAIL_COND(texture->render_target); + + ERR_FAIL_COND(p_width <= 0 || p_width > 16384); + ERR_FAIL_COND(p_height <= 0 || p_height > 16384); + //real texture size is in alloc width and height + texture->width = p_width; + texture->height = p_height; +} + +void TextureStorage::texture_set_path(RID p_texture, const String &p_path) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + texture->path = p_path; +} + +String TextureStorage::texture_get_path(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!texture, ""); + + return texture->path; +} + +void TextureStorage::texture_set_detect_3d_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_3d = p_callback; + texture->detect_3d_ud = p_userdata; +} + +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) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + texture->detect_normal = p_callback; + texture->detect_normal_ud = p_userdata; +} + +void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) { + List<RID> textures; + texture_owner.get_owned_list(&textures); + + for (List<RID>::Element *E = textures.front(); E; E = E->next()) { + Texture *t = texture_owner.get_or_null(E->get()); + if (!t) { + continue; + } + RS::TextureInfo tinfo; + tinfo.path = t->path; + tinfo.format = t->format; + tinfo.width = t->alloc_width; + tinfo.height = t->alloc_height; + tinfo.depth = 0; + tinfo.bytes = t->total_data_size; + r_info->push_back(tinfo); + } +} + +void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + texture->redraw_if_visible = p_enable; +} + +Size2 TextureStorage::texture_size_with_proxy(RID p_texture) { + const Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!texture, Size2()); + if (texture->proxy) { + return Size2(texture->proxy->width, texture->proxy->height); + } else { + return Size2(texture->width, texture->height); + } +} + +// example use in 3.2 +// VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid); + +// p_proxy is the source (pre-existing) texture? +// and p_texture is the one that is being made into a proxy? +//This naming is confusing. Comments!!! + +// The naming of the parameters seemed to be reversed? +// The p_proxy is the source texture +// and p_texture is actually the proxy???? + +void TextureStorage::texture_set_proxy(RID p_texture, RID p_proxy) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + if (texture->proxy) { + texture->proxy->proxy_owners.erase(texture); + texture->proxy = nullptr; + } + + if (p_proxy.is_valid()) { + Texture *proxy = texture_owner.get_or_null(p_proxy); + ERR_FAIL_COND(!proxy); + ERR_FAIL_COND(proxy == texture); + proxy->proxy_owners.insert(texture); + texture->proxy = proxy; + } +} + +void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) { + Config *config = Config::get_singleton(); + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND(!_is_main_thread()); + + ERR_FAIL_COND(!texture); + if (texture->target == GL_TEXTURE_3D) { + // Target is set to a 3D texture or array texture, exit early to avoid spamming errors + return; + } + ERR_FAIL_COND(!texture->active); + ERR_FAIL_COND(texture->render_target); + ERR_FAIL_COND(p_image.is_null()); + ERR_FAIL_COND(texture->format != p_image->get_format()); + + ERR_FAIL_COND(!p_image->get_width()); + ERR_FAIL_COND(!p_image->get_height()); + + // ERR_FAIL_COND(texture->type == RS::TEXTURE_TYPE_EXTERNAL); + + GLenum type; + GLenum format; + GLenum internal_format; + bool compressed = false; + + if (config->keep_original_textures && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) { + texture->images.write[p_layer] = 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(), texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2); + + if (texture->resize_to_po2) { + if (p_image->is_compressed()) { + ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage."); + } + + if (img == p_image) { + img = img->duplicate(); + } + img->resize_to_po2(false); + } + + if (config->shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) { + texture->alloc_height = MAX(1, texture->alloc_height / 2); + texture->alloc_width = MAX(1, texture->alloc_width / 2); + + 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_RGBA8) { + img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); + } + } + + GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D; + + texture->data_size = img->get_data().size(); + Vector<uint8_t> read = img->get_data(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + texture->ignore_mipmaps = compressed && !img->has_mipmaps(); + + // set filtering and repeat state + _texture_set_state_from_flags(texture); + + //set swizle for older format compatibility +#ifdef GLES_OVER_GL + switch (texture->format) { + case Image::FORMAT_L8: { + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ONE); + + } break; + case Image::FORMAT_LA8: { + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_GREEN); + } break; + default: { + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_GREEN); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_BLUE); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA); + + } break; + } +#endif + + int mipmaps = ((texture->flags & TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; + + int w = img->get_width(); + int h = img->get_height(); + + int tsize = 0; + + for (int i = 0; i < mipmaps; i++) { + int size, ofs; + img->get_mipmap_offset_and_size(i, ofs, size); + + if (compressed) { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + int bw = w; + int bh = h; + + glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]); + } else { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING) { + glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]); + } else { + glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]); + } + } + + tsize += size; + + w = MAX(1, w >> 1); + h = MAX(1, h >> 1); + } + + // info.texture_mem -= texture->total_data_size; // TODO make this work again!! + texture->total_data_size = tsize; + // info.texture_mem += texture->total_data_size; // TODO make this work again!! + + // printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem); + + 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; +} + +void TextureStorage::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) { + // TODO + ERR_PRINT("Not implemented (ask Karroffel to do it :p)"); +} + +/* +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>()); + + if (texture->type == RS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) { + return texture->images[p_layer]; + } + +#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 +} +*/ + +void TextureStorage::texture_set_flags(RID p_texture, uint32_t p_flags) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + bool had_mipmaps = texture->flags & TEXTURE_FLAG_MIPMAPS; + + texture->flags = p_flags; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + // set filtering and repeat state + _texture_set_state_from_flags(texture); + + if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) { + if (!had_mipmaps && texture->mipmaps == 1) { + glGenerateMipmap(texture->target); + } + } +} + +uint32_t TextureStorage::texture_get_flags(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->flags; +} + +Image::Format TextureStorage::texture_get_format(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, Image::FORMAT_L8); + + return texture->format; +} + +RenderingDevice::TextureType TextureStorage::texture_get_type(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, RenderingDevice::TEXTURE_TYPE_2D); + + return texture->type; +} + +uint32_t TextureStorage::texture_get_texid(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->tex_id; +} + +uint32_t TextureStorage::texture_get_width(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->width; +} + +uint32_t TextureStorage::texture_get_height(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->height; +} + +uint32_t TextureStorage::texture_get_depth(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->depth; +} + +void TextureStorage::texture_bind(RID p_texture, uint32_t p_texture_no) { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND(!texture); + + glActiveTexture(GL_TEXTURE0 + p_texture_no); + glBindTexture(texture->target, texture->tex_id); +} + +void TextureStorage::texture_set_shrink_all_x2_on_set_data(bool p_enable) { + Config::get_singleton()->shrink_textures_x2 = p_enable; +} + +RID TextureStorage::texture_create_radiance_cubemap(RID p_source, int p_resolution) const { + return RID(); +} + +void TextureStorage::textures_keep_original(bool p_enable) { + Config::get_singleton()->keep_original_textures = p_enable; +} + +#endif // GLES3_ENABLED diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h new file mode 100644 index 0000000000..8a921fbe10 --- /dev/null +++ b/drivers/gles3/storage/texture_storage.h @@ -0,0 +1,389 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_GLES3_H +#define TEXTURE_STORAGE_GLES3_H + +#ifdef GLES3_ENABLED + +#include "canvas_texture_storage.h" +#include "config.h" +#include "core/os/os.h" +#include "core/templates/rid_owner.h" +#include "render_target_storage.h" +#include "servers/rendering/storage/texture_storage.h" + +namespace GLES3 { + +#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB +#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD +#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE +#define _EXT_ETC1_RGB8_OES 0x8D64 + +#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C +#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D +#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E +#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F + +#define _GL_TEXTURE_EXTERNAL_OES 0x8D65 + +#ifdef GLES_OVER_GL +#define _GL_HALF_FLOAT_OES 0x140B +#else +#define _GL_HALF_FLOAT_OES 0x8D61 +#endif + +#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F + +#define _RED_OES 0x1903 + +#define _DEPTH_COMPONENT24_OES 0x81A6 + +#ifndef GLES_OVER_GL +#define glClearDepth glClearDepthf +#endif //!GLES_OVER_GL + +enum OpenGLTextureFlags { + TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available + TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping + TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter + TEXTURE_FLAG_ANISOTROPIC_FILTER = 8, + TEXTURE_FLAG_CONVERT_TO_LINEAR = 16, + TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored + TEXTURE_FLAG_USED_FOR_STREAMING = 2048, + TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER +}; + +struct Texture { + RID self; + + Texture *proxy; + Set<Texture *> proxy_owners; + + String path; + uint32_t flags; + int width, height, depth; + int alloc_width, alloc_height; + Image::Format format; + RenderingDevice::TextureType type; + + GLenum target; + GLenum gl_format_cache; + GLenum gl_internal_format_cache; + GLenum gl_type_cache; + + int data_size; + int total_data_size; + bool ignore_mipmaps; + + bool compressed; + + bool srgb; + + int mipmaps; + + bool resize_to_po2; + + bool active; + GLenum tex_id; + + uint16_t stored_cube_sides; + + RenderTarget *render_target; + + Vector<Ref<Image>> images; + + bool redraw_if_visible; + + RS::TextureDetectCallback detect_3d; + void *detect_3d_ud; + + RS::TextureDetectCallback detect_srgb; + void *detect_srgb_ud; + + RS::TextureDetectCallback detect_normal; + void *detect_normal_ud; + + CanvasTexture *canvas_texture = nullptr; + + // some silly opengl shenanigans where + // texture coords start from bottom left, means we need to draw render target textures upside down + // to be compatible with vulkan etc. + bool is_upside_down() const { + if (proxy) { + return proxy->is_upside_down(); + } + + return render_target != nullptr; + } + + Texture() { + create(); + } + + _ALWAYS_INLINE_ Texture *get_ptr() { + if (proxy) { + return proxy; //->get_ptr(); only one level of indirection, else not inlining possible. + } else { + return this; + } + } + + ~Texture() { + destroy(); + + if (tex_id != 0) { + glDeleteTextures(1, &tex_id); + } + } + + void copy_from(const Texture &o) { + proxy = o.proxy; + flags = o.flags; + width = o.width; + height = o.height; + alloc_width = o.alloc_width; + alloc_height = o.alloc_height; + format = o.format; + type = o.type; + target = o.target; + data_size = o.data_size; + total_data_size = o.total_data_size; + ignore_mipmaps = o.ignore_mipmaps; + compressed = o.compressed; + mipmaps = o.mipmaps; + resize_to_po2 = o.resize_to_po2; + active = o.active; + tex_id = o.tex_id; + stored_cube_sides = o.stored_cube_sides; + render_target = o.render_target; + redraw_if_visible = o.redraw_if_visible; + detect_3d = o.detect_3d; + detect_3d_ud = o.detect_3d_ud; + detect_srgb = o.detect_srgb; + detect_srgb_ud = o.detect_srgb_ud; + detect_normal = o.detect_normal; + detect_normal_ud = o.detect_normal_ud; + + images.clear(); + } + + void create() { + proxy = nullptr; + flags = 0; + width = 0; + height = 0; + alloc_width = 0; + alloc_height = 0; + format = Image::FORMAT_L8; + type = RenderingDevice::TEXTURE_TYPE_2D; + target = 0; + data_size = 0; + total_data_size = 0; + ignore_mipmaps = false; + compressed = false; + mipmaps = 0; + resize_to_po2 = false; + active = false; + tex_id = 0; + stored_cube_sides = 0; + render_target = nullptr; + redraw_if_visible = false; + detect_3d = nullptr; + detect_3d_ud = nullptr; + detect_srgb = nullptr; + detect_srgb_ud = nullptr; + detect_normal = nullptr; + detect_normal_ud = nullptr; + } + void destroy() { + images.clear(); + + for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) { + E->get()->proxy = nullptr; + } + + if (proxy) { + proxy->proxy_owners.erase(this); + } + } + + // texture state + void GLSetFilter(GLenum p_target, RS::CanvasItemTextureFilter p_filter) { + if (p_filter == state_filter) { + return; + } + state_filter = p_filter; + GLint pmin = GL_LINEAR; // param min + GLint pmag = GL_LINEAR; // param mag + switch (state_filter) { + default: { + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { + pmin = GL_LINEAR_MIPMAP_LINEAR; + pmag = GL_LINEAR; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { + pmin = GL_NEAREST; + pmag = GL_NEAREST; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { + pmin = GL_NEAREST_MIPMAP_NEAREST; + pmag = GL_NEAREST; + } break; + } + glTexParameteri(p_target, GL_TEXTURE_MIN_FILTER, pmin); + glTexParameteri(p_target, GL_TEXTURE_MAG_FILTER, pmag); + } + void GLSetRepeat(GLenum p_target, RS::CanvasItemTextureRepeat p_repeat) { + if (p_repeat == state_repeat) { + return; + } + state_repeat = p_repeat; + GLint prep = GL_CLAMP_TO_EDGE; // parameter repeat + switch (state_repeat) { + default: { + } break; + case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { + prep = GL_REPEAT; + } break; + case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { + prep = GL_MIRRORED_REPEAT; + } break; + } + glTexParameteri(p_target, GL_TEXTURE_WRAP_S, prep); + glTexParameteri(p_target, GL_TEXTURE_WRAP_T, prep); + } + +private: + RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; + RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; +}; + +class TextureStorage : public RendererTextureStorage { +private: + static TextureStorage *singleton; + + Thread::ID _main_thread_id = 0; + bool _is_main_thread(); + + mutable RID_PtrOwner<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; + void _texture_set_state_from_flags(Texture *p_tex); + + void texture_set_proxy(RID p_texture, RID p_proxy); + +public: + static TextureStorage *get_singleton(); + + TextureStorage(); + virtual ~TextureStorage(); + + Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + RID make_rid(Texture *p_texture) { return texture_owner.make_rid(p_texture); }; + + void set_main_thread_id(Thread::ID p_id); + + virtual bool can_create_resources_async() const override; + + RID texture_create(); + void _texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT); + + virtual RID texture_allocate() override; + virtual void texture_free(RID p_rid) override; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{}; + virtual void texture_proxy_update(RID p_proxy, RID p_base) override{}; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) override; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override; + virtual void texture_3d_placeholder_initialize(RID p_texture) override; + + virtual Ref<Image> texture_2d_get(RID p_texture) const override; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }; + + virtual void texture_replace(RID p_texture, RID p_by_texture) override; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override; + + virtual void texture_set_path(RID p_texture, const String &p_path) override; + virtual String texture_get_path(RID p_texture) const override; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; + void texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override{}; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override; + + virtual Size2 texture_size_with_proxy(RID p_proxy) override; + + void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); + void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0); + //Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const; + void texture_set_flags(RID p_texture, uint32_t p_flags); + uint32_t texture_get_flags(RID p_texture) const; + Image::Format texture_get_format(RID p_texture) const; + RenderingDevice::TextureType texture_get_type(RID p_texture) const; + uint32_t texture_get_texid(RID p_texture) const; + uint32_t texture_get_width(RID p_texture) const; + uint32_t texture_get_height(RID p_texture) const; + uint32_t texture_get_depth(RID p_texture) const; + void texture_bind(RID p_texture, uint32_t p_texture_no); + void texture_set_shrink_all_x2_on_set_data(bool p_enable); + RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const; + void textures_keep_original(bool p_enable); +}; + +} // namespace GLES3 + +#endif // !GLES3_ENABLED + +#endif // !TEXTURE_STORAGE_GLES3_H diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index 2caf369354..a38040922d 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -34,7 +34,7 @@ #include "drivers/gles3/rasterizer_gles3.h" #endif #include "platform/javascript/os_javascript.h" -#include "servers/rendering/rasterizer_dummy.h" +#include "servers/rendering/dummy/rasterizer_dummy.h" #include <emscripten.h> #include <png.h> diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 1930fa2682..3113987fbc 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -212,7 +212,7 @@ void ImageTexture::update(const Ref<Image> &p_image) { ERR_FAIL_COND_MSG(mipmaps != p_image->has_mipmaps(), "The new image mipmaps configuration must match the texture's image mipmaps configuration"); - RenderingServer::get_singleton()->texture_2d_update(texture, p_image); + RS::get_singleton()->texture_2d_update(texture, p_image); notify_property_list_changed(); emit_changed(); diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index f74a8fad23..3853ff4fdc 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -33,7 +33,7 @@ #include "servers/display_server.h" -#include "servers/rendering/rasterizer_dummy.h" +#include "servers/rendering/dummy/rasterizer_dummy.h" class DisplayServerHeadless : public DisplayServer { private: diff --git a/servers/rendering/SCsub b/servers/rendering/SCsub index 0939b68482..06d1d28b08 100644 --- a/servers/rendering/SCsub +++ b/servers/rendering/SCsub @@ -5,3 +5,4 @@ Import("env") env.add_source_files(env.servers_sources, "*.cpp") SConscript("renderer_rd/SCsub") +SConscript("storage/SCsub") diff --git a/servers/rendering/dummy/rasterizer_canvas_dummy.h b/servers/rendering/dummy/rasterizer_canvas_dummy.h new file mode 100644 index 0000000000..194b5b5cfe --- /dev/null +++ b/servers/rendering/dummy/rasterizer_canvas_dummy.h @@ -0,0 +1,63 @@ +/*************************************************************************/ +/* rasterizer_canvas_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_CANVAS_DUMMY_H +#define RASTERIZER_CANVAS_DUMMY_H + +#include "servers/rendering/renderer_canvas_render.h" + +class RasterizerCanvasDummy : public RendererCanvasRender { +public: + PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; } + void free_polygon(PolygonID p_polygon) override {} + + void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override {} + void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {} + + RID light_create() override { return RID(); } + void light_set_texture(RID p_rid, RID p_texture) override {} + void light_set_use_shadow(RID p_rid, bool p_enable) override {} + void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {} + void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {} + + void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {} + RID occluder_polygon_create() override { return RID(); } + void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {} + void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {} + void set_shadow_texture_size(int p_size) override {} + + bool free(RID p_rid) override { return true; } + void update() override {} + + RasterizerCanvasDummy() {} + ~RasterizerCanvasDummy() {} +}; + +#endif // !RASTERIZER_CANVAS_DUMMY_H diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h new file mode 100644 index 0000000000..b3fbc18c46 --- /dev/null +++ b/servers/rendering/dummy/rasterizer_dummy.h @@ -0,0 +1,99 @@ +/*************************************************************************/ +/* rasterizer_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_DUMMY_H +#define RASTERIZER_DUMMY_H + +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "scene/resources/mesh.h" +#include "servers/rendering/dummy/rasterizer_canvas_dummy.h" +#include "servers/rendering/dummy/rasterizer_scene_dummy.h" +#include "servers/rendering/dummy/rasterizer_storage_dummy.h" +#include "servers/rendering/dummy/storage/canvas_texture_storage.h" +#include "servers/rendering/dummy/storage/texture_storage.h" +#include "servers/rendering/renderer_compositor.h" +#include "servers/rendering_server.h" + +class RasterizerDummy : public RendererCompositor { +private: + uint64_t frame = 1; + double delta = 0; + +protected: + RasterizerCanvasDummy canvas; + RendererDummy::CanvasTextureStorage canvas_texture_storage; + RendererDummy::TextureStorage texture_storage; + RasterizerStorageDummy storage; + RasterizerSceneDummy scene; + +public: + RendererCanvasTextureStorage *get_canvas_texture_storage() override { return &canvas_texture_storage; }; + RendererTextureStorage *get_texture_storage() override { return &texture_storage; }; + RendererStorage *get_storage() override { return &storage; } + RendererCanvasRender *get_canvas() override { return &canvas; } + RendererSceneRender *get_scene() override { return &scene; } + + void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {} + + void initialize() override {} + void begin_frame(double frame_step) override { + frame++; + delta = frame_step; + } + + void prepare_for_blitting_render_targets() override {} + void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {} + + void end_frame(bool p_swap_buffers) override { + if (p_swap_buffers) { + DisplayServer::get_singleton()->swap_buffers(); + } + } + + void finalize() override {} + + static RendererCompositor *_create_current() { + return memnew(RasterizerDummy); + } + + static void make_current() { + _create_func = _create_current; + } + + bool is_low_end() const override { return true; } + uint64_t get_frame_number() const override { return frame; } + double get_frame_delta_time() const override { return delta; } + + RasterizerDummy() {} + ~RasterizerDummy() {} +}; + +#endif // RASTERIZER_DUMMY_H diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h new file mode 100644 index 0000000000..3855222554 --- /dev/null +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -0,0 +1,217 @@ +/*************************************************************************/ +/* rasterizer_scene_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_SCENE_DUMMY_H +#define RASTERIZER_SCENE_DUMMY_H + +#include "servers/rendering/renderer_scene_render.h" + +class RasterizerSceneDummy : public RendererSceneRender { +public: + GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; } + void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {} + void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {} + void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {} + void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {} + void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {} + void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {} + void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {} + void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {} + void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {} + void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {} + void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {} + void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {} + void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {} + void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {} + void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {} + void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {} + void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {} + + uint32_t geometry_instance_get_pair_mask() override { return 0; } + void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {} + void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} + void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} + void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} + void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {} + + void geometry_instance_free(GeometryInstance *p_geometry_instance) override {} + + /* SHADOW ATLAS API */ + + RID shadow_atlas_create() override { return RID(); } + void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {} + void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {} + bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; } + + void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {} + int get_directional_light_shadow_size(RID p_light_intance) override { return 0; } + void set_directional_shadow_count(int p_count) override {} + + /* SDFGI UPDATE */ + + void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} + int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; } + AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); } + uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; } + + /* SKY API */ + + RID sky_allocate() override { return RID(); } + void sky_initialize(RID p_rid) override {} + void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {} + void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {} + void sky_set_material(RID p_sky, RID p_material) override {} + Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } + + /* ENVIRONMENT API */ + + RID environment_allocate() override { return RID(); } + void environment_initialize(RID p_rid) override {} + void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {} + void environment_set_sky(RID p_env, RID p_sky) override {} + void environment_set_sky_custom_fov(RID p_env, float p_scale) override {} + void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {} + void environment_set_bg_color(RID p_env, const Color &p_color) override {} + void environment_set_bg_energy(RID p_env, float p_energy) override {} + void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {} + void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {} + + void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {} + void environment_glow_set_use_bicubic_upscale(bool p_enable) override {} + void environment_glow_set_use_high_quality(bool p_enable) override {} + + void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {} + void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {} + void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {} + void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} + void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {} + void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} + + void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {} + + void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {} + void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {} + void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {} + + void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {} + + void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {} + + void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {} + void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {} + void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {} + void environment_set_volumetric_fog_filter_active(bool p_enable) override {} + + Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } + + bool is_environment(RID p_env) const override { return false; } + RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; } + int environment_get_canvas_max_layer(RID p_env) const override { return 0; } + + RID camera_effects_allocate() override { return RID(); } + void camera_effects_initialize(RID p_rid) override {} + void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {} + void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {} + + void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {} + void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {} + + void shadows_quality_set(RS::ShadowQuality p_quality) override {} + void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {} + + RID light_instance_create(RID p_light) override { return RID(); } + void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {} + void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {} + void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {} + void light_instance_mark_visible(RID p_light_instance) override {} + + RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); } + void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {} + void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {} + RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); } + Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); } + + RID reflection_atlas_create() override { return RID(); } + int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; } + void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {} + + RID reflection_probe_instance_create(RID p_probe) override { return RID(); } + void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {} + void reflection_probe_release_atlas_index(RID p_instance) override {} + bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; } + bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; } + bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; } + bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; } + + RID decal_instance_create(RID p_decal) override { return RID(); } + void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {} + + RID lightmap_instance_create(RID p_lightmap) override { return RID(); } + void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {} + + RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); } + void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {} + bool voxel_gi_needs_update(RID p_probe) const override { return false; } + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {} + + void voxel_gi_set_quality(RS::VoxelGIQuality) override {} + + void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} + void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} + void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {} + + void set_scene_pass(uint64_t p_pass) override {} + void set_time(double p_time, double p_step) override {} + void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {} + + RID render_buffers_create() override { return RID(); } + void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {} + void gi_set_use_half_resolution(bool p_enable) override {} + + void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {} + bool screen_space_roughness_limiter_is_active() const override { return false; } + + void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {} + void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {} + + TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); } + + bool free(RID p_rid) override { return false; } + void update() override {} + void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {} + + virtual void decals_set_filter(RS::DecalFilter p_filter) override {} + virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {} + + RasterizerSceneDummy() {} + ~RasterizerSceneDummy() {} +}; + +#endif // !RASTERIZER_SCENE_DUMMY_H diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h index 8f82356d11..1c8258da32 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/dummy/rasterizer_storage_dummy.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* rasterizer_dummy.h */ +/* rasterizer_storage_dummy.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,265 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_DUMMY_H -#define RASTERIZER_DUMMY_H +#ifndef RASTERIZER_STORAGE_DUMMY_H +#define RASTERIZER_STORAGE_DUMMY_H -#include "core/templates/rid_owner.h" -#include "core/templates/self_list.h" -#include "scene/resources/mesh.h" -#include "servers/rendering/renderer_compositor.h" -#include "servers/rendering/renderer_scene_render.h" -#include "servers/rendering_server.h" - -class RasterizerSceneDummy : public RendererSceneRender { -public: - GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; } - void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {} - void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {} - void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {} - void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {} - void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {} - void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {} - void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {} - void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {} - void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {} - void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {} - void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {} - void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {} - void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {} - void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {} - - uint32_t geometry_instance_get_pair_mask() override { return 0; } - void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {} - void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} - void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} - void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} - void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {} - - void geometry_instance_free(GeometryInstance *p_geometry_instance) override {} - - /* SHADOW ATLAS API */ - - RID shadow_atlas_create() override { return RID(); } - void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {} - void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {} - bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; } - - void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {} - int get_directional_light_shadow_size(RID p_light_intance) override { return 0; } - void set_directional_shadow_count(int p_count) override {} - - /* SDFGI UPDATE */ - - void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} - int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; } - AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); } - uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; } - - /* SKY API */ - - RID sky_allocate() override { return RID(); } - void sky_initialize(RID p_rid) override {} - void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {} - void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {} - void sky_set_material(RID p_sky, RID p_material) override {} - Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } - - /* ENVIRONMENT API */ - - RID environment_allocate() override { return RID(); } - void environment_initialize(RID p_rid) override {} - void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {} - void environment_set_sky(RID p_env, RID p_sky) override {} - void environment_set_sky_custom_fov(RID p_env, float p_scale) override {} - void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {} - void environment_set_bg_color(RID p_env, const Color &p_color) override {} - void environment_set_bg_energy(RID p_env, float p_energy) override {} - void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {} - void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {} - - void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {} - void environment_glow_set_use_bicubic_upscale(bool p_enable) override {} - void environment_glow_set_use_high_quality(bool p_enable) override {} - - void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {} - void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {} - void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {} - void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} - void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {} - void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} - - void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {} - - void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {} - void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {} - void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {} - - void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {} - - void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {} - - void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {} - void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {} - void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {} - void environment_set_volumetric_fog_filter_active(bool p_enable) override {} - - Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } - - bool is_environment(RID p_env) const override { return false; } - RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; } - int environment_get_canvas_max_layer(RID p_env) const override { return 0; } - - RID camera_effects_allocate() override { return RID(); } - void camera_effects_initialize(RID p_rid) override {} - void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {} - void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {} - - void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {} - void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {} - - void shadows_quality_set(RS::ShadowQuality p_quality) override {} - void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {} - - RID light_instance_create(RID p_light) override { return RID(); } - void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {} - void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {} - void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {} - void light_instance_mark_visible(RID p_light_instance) override {} - - RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); } - void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {} - void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {} - RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); } - Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); } - - RID reflection_atlas_create() override { return RID(); } - int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; } - void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {} - - RID reflection_probe_instance_create(RID p_probe) override { return RID(); } - void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {} - void reflection_probe_release_atlas_index(RID p_instance) override {} - bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; } - bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; } - bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; } - bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; } - - RID decal_instance_create(RID p_decal) override { return RID(); } - void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {} - - RID lightmap_instance_create(RID p_lightmap) override { return RID(); } - void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {} - - RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); } - void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {} - bool voxel_gi_needs_update(RID p_probe) const override { return false; } - void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {} - - void voxel_gi_set_quality(RS::VoxelGIQuality) override {} - - void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} - void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} - void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {} - - void set_scene_pass(uint64_t p_pass) override {} - void set_time(double p_time, double p_step) override {} - void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {} - - RID render_buffers_create() override { return RID(); } - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {} - void gi_set_use_half_resolution(bool p_enable) override {} - - void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {} - bool screen_space_roughness_limiter_is_active() const override { return false; } - - void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {} - void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {} - - TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); } - - bool free(RID p_rid) override { return false; } - void update() override {} - void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {} - - virtual void decals_set_filter(RS::DecalFilter p_filter) override {} - virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {} - - RasterizerSceneDummy() {} - ~RasterizerSceneDummy() {} -}; +#include "servers/rendering/renderer_storage.h" +#include "storage/texture_storage.h" class RasterizerStorageDummy : public RendererStorage { public: - bool can_create_resources_async() const override { return false; } - - /* TEXTURE API */ - struct DummyTexture { - Ref<Image> image; - }; - mutable RID_PtrOwner<DummyTexture> texture_owner; - - RID texture_allocate() override { - DummyTexture *texture = memnew(DummyTexture); - ERR_FAIL_COND_V(!texture, RID()); - return texture_owner.make_rid(texture); - } - void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override { - DummyTexture *t = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!t); - t->image = p_image->duplicate(); - } - - void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {} - void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {} - void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {} - void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {} - void texture_proxy_initialize(RID p_texture, RID p_base) override {} - void texture_proxy_update(RID p_proxy, RID p_base) override {} - - void texture_2d_placeholder_initialize(RID p_texture) override {} - void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override {} - void texture_3d_placeholder_initialize(RID p_texture) override {} - - Ref<Image> texture_2d_get(RID p_texture) const override { - DummyTexture *t = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!t, Ref<Image>()); - return t->image; - } - - Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); } - Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); } - - void texture_replace(RID p_texture, RID p_by_texture) override { free(p_by_texture); } - void texture_set_size_override(RID p_texture, int p_width, int p_height) override {} - - void texture_set_path(RID p_texture, const String &p_path) override {} - String texture_get_path(RID p_texture) const override { return String(); } - - void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {} - void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {} - void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {} - - void texture_debug_usage(List<RS::TextureInfo> *r_info) override {} - void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {} - Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); } - - void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - - /* CANVAS TEXTURE API */ - - RID canvas_texture_allocate() override { return RID(); } - void canvas_texture_initialize(RID p_rid) override {} - void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override {} - void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override {} - - void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override {} - void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override {} - /* SHADER API */ RID shader_allocate() override { return RID(); } @@ -481,6 +230,9 @@ public: AABB decal_get_aabb(RID p_decal) const override { return AABB(); } + void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} + void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} + /* VOXEL GI API */ RID voxel_gi_allocate() override { return RID(); } @@ -682,11 +434,8 @@ public: RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; } bool free(RID p_rid) override { - if (texture_owner.owns(p_rid)) { - // delete the texture - DummyTexture *texture = texture_owner.get_or_null(p_rid); - texture_owner.free(p_rid); - memdelete(texture); + if (RendererDummy::TextureStorage::get_singleton()->owns_texture(p_rid)) { + RendererDummy::TextureStorage::get_singleton()->texture_free(p_rid); return true; } return false; @@ -721,81 +470,4 @@ public: ~RasterizerStorageDummy() {} }; -class RasterizerCanvasDummy : public RendererCanvasRender { -public: - PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; } - void free_polygon(PolygonID p_polygon) override {} - - void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override {} - void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {} - - RID light_create() override { return RID(); } - void light_set_texture(RID p_rid, RID p_texture) override {} - void light_set_use_shadow(RID p_rid, bool p_enable) override {} - void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {} - void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {} - - void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {} - RID occluder_polygon_create() override { return RID(); } - void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {} - void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {} - void set_shadow_texture_size(int p_size) override {} - - bool free(RID p_rid) override { return true; } - void update() override {} - - RasterizerCanvasDummy() {} - ~RasterizerCanvasDummy() {} -}; - -class RasterizerDummy : public RendererCompositor { -private: - uint64_t frame = 1; - double delta = 0; - -protected: - RasterizerCanvasDummy canvas; - RasterizerStorageDummy storage; - RasterizerSceneDummy scene; - -public: - RendererStorage *get_storage() override { return &storage; } - RendererCanvasRender *get_canvas() override { return &canvas; } - RendererSceneRender *get_scene() override { return &scene; } - - void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {} - - void initialize() override {} - void begin_frame(double frame_step) override { - frame++; - delta = frame_step; - } - - void prepare_for_blitting_render_targets() override {} - void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {} - - void end_frame(bool p_swap_buffers) override { - if (p_swap_buffers) { - DisplayServer::get_singleton()->swap_buffers(); - } - } - - void finalize() override {} - - static RendererCompositor *_create_current() { - return memnew(RasterizerDummy); - } - - static void make_current() { - _create_func = _create_current; - } - - bool is_low_end() const override { return true; } - uint64_t get_frame_number() const override { return frame; } - double get_frame_delta_time() const override { return delta; } - - RasterizerDummy() {} - ~RasterizerDummy() {} -}; - -#endif // RASTERIZER_DUMMY_H +#endif // !RASTERIZER_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/canvas_texture_storage.h b/servers/rendering/dummy/storage/canvas_texture_storage.h new file mode 100644 index 0000000000..daa3ac5e42 --- /dev/null +++ b/servers/rendering/dummy/storage/canvas_texture_storage.h @@ -0,0 +1,53 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_DUMMY_H +#define CANVAS_TEXTURE_STORAGE_DUMMY_H + +#include "servers/rendering/storage/canvas_texture_storage.h" + +namespace RendererDummy { + +class CanvasTextureStorage : public RendererCanvasTextureStorage { +public: + virtual RID canvas_texture_allocate() override { return RID(); }; + virtual void canvas_texture_initialize(RID p_rid) override{}; + virtual void canvas_texture_free(RID p_rid) override{}; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override{}; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override{}; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override{}; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override{}; +}; + +} // namespace RendererDummy + +#endif // !CANVAS_TEXTURE_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h new file mode 100644 index 0000000000..d40a1842a4 --- /dev/null +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -0,0 +1,116 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_DUMMY_H +#define TEXTURE_STORAGE_DUMMY_H + +#include "servers/rendering/rendering_server_globals.h" +#include "servers/rendering/storage/texture_storage.h" + +namespace RendererDummy { + +class TextureStorage : public RendererTextureStorage { +private: + struct DummyTexture { + Ref<Image> image; + }; + mutable RID_PtrOwner<DummyTexture> texture_owner; + +public: + static TextureStorage *get_singleton() { + // Here we cheat until we can retire RasterizerStorageDummy::free() + + return (TextureStorage *)RSG::texture_storage; + }; + + virtual bool can_create_resources_async() const override { return false; } + + DummyTexture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + + virtual RID texture_allocate() override { + DummyTexture *texture = memnew(DummyTexture); + ERR_FAIL_COND_V(!texture, RID()); + return texture_owner.make_rid(texture); + }; + + virtual void texture_free(RID p_rid) override { + // delete the texture + DummyTexture *texture = texture_owner.get_or_null(p_rid); + texture_owner.free(p_rid); + memdelete(texture); + }; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override { + DummyTexture *t = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!t); + t->image = p_image->duplicate(); + }; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override{}; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override{}; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) override{}; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override{}; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{}; + virtual void texture_proxy_update(RID p_proxy, RID p_base) override{}; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) override{}; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override{}; + virtual void texture_3d_placeholder_initialize(RID p_texture) override{}; + + virtual Ref<Image> texture_2d_get(RID p_texture) const override { + DummyTexture *t = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!t, Ref<Image>()); + return t->image; + }; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }; + + virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); }; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override{}; + + virtual void texture_set_path(RID p_texture, const String &p_path) override{}; + virtual String texture_get_path(RID p_texture) const override { return String(); }; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{}; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{}; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override{}; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override{}; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override{}; + + virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }; +}; + +} // namespace RendererDummy + +#endif // !TEXTURE_STORAGE_DUMMY_H diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index a96f873088..56eaa396c8 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -34,6 +34,7 @@ #include "renderer_viewport.h" #include "rendering_server_default.h" #include "rendering_server_globals.h" +#include "servers/rendering/storage/canvas_texture_storage.h" static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; @@ -1530,26 +1531,26 @@ void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) { } RID RendererCanvasCull::canvas_texture_allocate() { - return RSG::storage->canvas_texture_allocate(); + return RSG::canvas_texture_storage->canvas_texture_allocate(); } void RendererCanvasCull::canvas_texture_initialize(RID p_rid) { - RSG::storage->canvas_texture_initialize(p_rid); + RSG::canvas_texture_storage->canvas_texture_initialize(p_rid); } void RendererCanvasCull::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { - RSG::storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture); + RSG::canvas_texture_storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture); } void RendererCanvasCull::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) { - RSG::storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess); + RSG::canvas_texture_storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess); } void RendererCanvasCull::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { - RSG::storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter); + RSG::canvas_texture_storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter); } void RendererCanvasCull::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { - RSG::storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat); + RSG::canvas_texture_storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat); } void RendererCanvasCull::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) { diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index e58fd7bebc..c2bc2c03d0 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -34,6 +34,8 @@ #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_scene.h" #include "servers/rendering/renderer_storage.h" +#include "servers/rendering/storage/canvas_texture_storage.h" +#include "servers/rendering/storage/texture_storage.h" #include "servers/rendering_server.h" class RendererSceneRender; @@ -70,6 +72,8 @@ protected: public: static RendererCompositor *create(); + virtual RendererCanvasTextureStorage *get_canvas_texture_storage() = 0; + virtual RendererTextureStorage *get_texture_storage() = 0; virtual RendererStorage *get_storage() = 0; virtual RendererCanvasRender *get_canvas() = 0; virtual RendererSceneRender *get_scene() = 0; diff --git a/servers/rendering/renderer_rd/SCsub b/servers/rendering/renderer_rd/SCsub index 64e613ab91..d3ad381965 100644 --- a/servers/rendering/renderer_rd/SCsub +++ b/servers/rendering/renderer_rd/SCsub @@ -7,3 +7,4 @@ env.add_source_files(env.servers_sources, "*.cpp") SConscript("forward_clustered/SCsub") SConscript("forward_mobile/SCsub") SConscript("shaders/SCsub") +SConscript("storage_rd/SCsub") diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index f1bd179f44..3aabc5058e 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -2213,7 +2213,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; } else { - radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; u.binding = 2; @@ -2230,7 +2230,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (ref_texture.is_valid()) { u.append_id(ref_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -2244,7 +2244,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { - texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } u.append_id(texture); uniforms.push_back(u); @@ -2256,7 +2256,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } uniforms.push_back(u); } @@ -2265,12 +2265,12 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); RID texture = storage->lightmap_get_texture(base); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); u.append_id(rd_texture); } else { u.append_id(default_tex); @@ -2283,7 +2283,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) { RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]); @@ -2313,7 +2313,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -2322,7 +2322,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); - RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2332,7 +2332,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL); + RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); u.append_id(texture); uniforms.push_back(u); } @@ -2342,7 +2342,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 12; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID(); - RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2352,7 +2352,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID(); - RID texture = ambient_buffer.is_valid() ? ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2362,7 +2362,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 14; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID(); - RID texture = reflection_buffer.is_valid() ? reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2374,7 +2374,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { t = render_buffers_get_sdfgi_irradiance_probes(p_render_data->render_buffers); } else { - t = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + t = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } u.append_id(t); uniforms.push_back(u); @@ -2386,7 +2386,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers)); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -2405,10 +2405,10 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) { vfog = render_buffers_get_volumetric_fog_texture(p_render_data->render_buffers); if (vfog.is_null()) { - vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } } else { - vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } u.append_id(vfog); uniforms.push_back(u); @@ -2418,7 +2418,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 19; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID(); - RID texture = ssil.is_valid() ? ssil : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2446,7 +2446,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te } { // No radiance texture. - RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2456,7 +2456,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { // No reflection atlas. - RID ref_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2469,7 +2469,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -2479,7 +2479,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -2490,7 +2490,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { u.append_id(default_tex); } @@ -2504,7 +2504,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { u.append_id(default_tex); } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 957b490664..99584ad757 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -315,7 +315,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; } else { - radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; u.binding = 2; @@ -332,7 +332,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (ref_texture.is_valid()) { u.append_id(ref_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -346,7 +346,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { - texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } u.append_id(texture); uniforms.push_back(u); @@ -358,7 +358,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } uniforms.push_back(u); } @@ -369,12 +369,12 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); RID texture = storage->lightmap_get_texture(base); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); u.append_id(rd_texture); } else { u.append_id(default_tex); @@ -390,7 +390,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.resize(MAX_VOXEL_GI_INSTANCESS); - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (i < (int)p_voxel_gi_instances.size()) { RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]); @@ -421,7 +421,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -430,7 +430,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); - RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index e6fc50afbf..9a1c4505fa 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -358,7 +358,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI bool use_normal; bool use_specular; - bool success = storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular); + bool success = canvas_texture_storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular); //something odd happened if (!success) { _bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size); @@ -977,7 +977,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo } else { screen = storage->render_target_get_rd_backbuffer(p_to_render_target); if (screen.is_null()) { //unallocated backbuffer - screen = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + screen = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } } u.append_id(screen); @@ -2245,6 +2245,8 @@ void RendererCanvasRenderRD::update() { } RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { + canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton(); + texture_storage = RendererRD::TextureStorage::get_singleton(); storage = p_storage; { //create default samplers @@ -2575,8 +2577,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { state.default_transforms_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); } - default_canvas_texture = storage->canvas_texture_allocate(); - storage->canvas_texture_initialize(default_canvas_texture); + default_canvas_texture = canvas_texture_storage->canvas_texture_allocate(); + canvas_texture_storage->canvas_texture_initialize(default_canvas_texture); state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size"); @@ -2696,6 +2698,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() { } RD::get_singleton()->free(state.shadow_texture); - storage->free(default_canvas_texture); + canvas_texture_storage->canvas_texture_free(default_canvas_texture); //pipelines don't need freeing, they are all gone after shaders are gone } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 84f64b6fda..c0138c4fe0 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -37,10 +37,14 @@ #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/shader_compiler.h" class RendererCanvasRenderRD : public RendererCanvasRender { + RendererRD::CanvasTextureStorage *canvas_texture_storage; + RendererRD::TextureStorage *texture_storage; RendererStorageRD *storage; enum { diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index e8978e7dca..bbd1498417 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -46,7 +46,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID for (int i = 0; i < p_amount; i++) { RID texture = storage->render_target_get_texture(p_render_targets[i].render_target); ERR_CONTINUE(texture.is_null()); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); ERR_CONTINUE(rd_texture.is_null()); // TODO if keep_3d_linear was set when rendering to this render target we need to add a linear->sRGB conversion in. @@ -155,6 +155,8 @@ void RendererCompositorRD::finalize() { memdelete(scene); memdelete(canvas); memdelete(storage); + memdelete(texture_storage); + memdelete(canvas_texture_storage); //only need to erase these, the rest are erased by cascade blit.shader.version_free(blit.shader_version); @@ -165,9 +167,9 @@ void RendererCompositorRD::finalize() { void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { RD::get_singleton()->prepare_screen_for_drawing(); - RID texture = storage->texture_allocate(); - storage->texture_2d_initialize(texture, p_image); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID texture = texture_storage->texture_allocate(); + texture_storage->texture_2d_initialize(texture, p_image); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); RID uset; { @@ -235,7 +237,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RD::get_singleton()->swap_buffers(); - storage->free(texture); + texture_storage->texture_free(texture); } RendererCompositorRD *RendererCompositorRD::singleton = nullptr; @@ -283,6 +285,8 @@ RendererCompositorRD::RendererCompositorRD() { singleton = this; time = 0; + canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage); + texture_storage = memnew(RendererRD::TextureStorage); storage = memnew(RendererStorageRD); canvas = memnew(RendererCanvasRenderRD(storage)); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index e526b95677..07df38b2b2 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -39,12 +39,16 @@ #include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h" #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" class RendererCompositorRD : public RendererCompositor { protected: UniformSetCacheRD *uniform_set_cache; RendererCanvasRenderRD *canvas; + RendererRD::CanvasTextureStorage *canvas_texture_storage; + RendererRD::TextureStorage *texture_storage; RendererStorageRD *storage; RendererSceneRenderRD *scene; @@ -88,6 +92,8 @@ protected: static uint64_t frame; public: + RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; }; + RendererTextureStorage *get_texture_storage() { return texture_storage; }; RendererStorage *get_storage() { return storage; } RendererCanvasRender *get_canvas() { return canvas; } RendererSceneRender *get_scene() { return scene; } diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 8f0e1d36db..7d79bf7707 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -40,6 +40,7 @@ const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFF // SDFGI void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); storage = p_gi->storage; gi = p_gi; num_cascades = p_env->sdfgi_cascades; @@ -377,7 +378,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -620,7 +621,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -633,7 +634,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].light_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -646,7 +647,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_0_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -659,7 +660,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_1_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1108,6 +1109,8 @@ void RendererSceneGIRD::SDFGI::update_cascades() { } void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) { Vector<RD::Uniform> uniforms; { @@ -1118,7 +1121,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1131,7 +1134,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].light_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1144,7 +1147,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_0_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1157,7 +1160,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_1_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -2807,6 +2810,8 @@ RendererSceneGIRD::~RendererSceneGIRD() { } void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + storage = p_storage; /* GI */ @@ -2924,7 +2929,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); uniforms.push_back(u); } { @@ -3023,6 +3028,8 @@ RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironme } void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + r_voxel_gi_instances_used = 0; // feels a little dirty to use our container this way but.... @@ -3085,7 +3092,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra } if (texture == RID()) { - texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } if (texture != rb->gi.voxel_gi_textures[i]) { @@ -3121,6 +3128,8 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra } void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RD::get_singleton()->draw_command_begin_label("GI Render"); RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); @@ -3186,7 +3195,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3199,7 +3208,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3212,7 +3221,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3225,7 +3234,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3237,7 +3246,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi) { u.append_id(rb->sdfgi->occlusion_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -3279,7 +3288,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi) { u.append_id(rb->sdfgi->lightprobe_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); } uniforms.push_back(u); } @@ -3301,7 +3310,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 14; - RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(buffer); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h index f2d1a17099..d51b1bf691 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h @@ -45,6 +45,7 @@ #include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/voxel_gi.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 14207c6620..ad9b2e62fa 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2490,7 +2490,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.exposure_texture = rb->luminance.current; tonemap.auto_exposure_grey = env->auto_exp_scale; } else { - tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } if (can_use_effects && env && env->glow_enabled) { @@ -2506,15 +2506,15 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.glow_texture = rb->blur[1].texture; if (env->glow_map.is_valid()) { tonemap.glow_map_strength = env->glow_map_strength; - tonemap.glow_map = storage->texture_get_rd_texture(env->glow_map); + tonemap.glow_map = texture_storage->texture_get_rd_texture(env->glow_map); } else { tonemap.glow_map_strength = 0.0f; - tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } } else { - tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); - tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { @@ -2536,7 +2536,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; - tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); if (can_use_effects && env) { tonemap.use_bcs = env->adjustments_enabled; @@ -2546,7 +2546,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende if (env->adjustments_enabled && env->color_correction.is_valid()) { tonemap.use_color_correction = true; tonemap.use_1d_color_correction = env->use_1d_color_correction; - tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction); + tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction); } } @@ -2606,14 +2606,14 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr } tonemap.use_glow = false; - tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); - tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_auto_exposure = false; - tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; - tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); if (can_use_effects && env) { tonemap.use_bcs = env->adjustments_enabled; @@ -2623,7 +2623,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr if (env->adjustments_enabled && env->color_correction.is_valid()) { tonemap.use_color_correction = true; tonemap.use_1d_color_correction = env->use_1d_color_correction; - tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction); + tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction); } } @@ -2656,7 +2656,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); if (shadow_atlas_texture.is_null()) { - shadow_atlas_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); } Size2 rtsize = storage->render_target_get_size(rb->render_target); @@ -2716,7 +2716,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) { if (p_occlusion_buffer.is_valid()) { Size2 rtsize = storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(storage->texture_get_rd_texture(p_occlusion_buffer), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); + effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); } } } @@ -4364,7 +4364,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.binding = 1; ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); } else { u.append_id(shadow_atlas->depth); } @@ -4380,7 +4380,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e if (directional_shadow.depth.is_valid()) { u.append_id(directional_shadow.depth); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); copy_uniforms.push_back(u); @@ -4545,7 +4545,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 19; - RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID(); u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); uniforms.push_back(u); @@ -5600,6 +5600,7 @@ uint32_t RendererSceneRenderRD::get_max_elements() const { } RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { + texture_storage = RendererRD::TextureStorage::get_singleton(); storage = p_storage; singleton = this; } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 4a86ced322..e302db2631 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -41,6 +41,7 @@ #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_scene.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" @@ -92,6 +93,7 @@ class RendererSceneRenderRD : public RendererSceneRender { friend RendererSceneGIRD; protected: + RendererRD::TextureStorage *texture_storage; RendererStorageRD *storage; double time; double time_step = 0; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 45fc37bd02..1785a6b180 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -33,6 +33,7 @@ #include "core/math/math_defs.h" #include "renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" //////////////////////////////////////////////////////////////////////////////// @@ -621,6 +622,8 @@ void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) { } RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) { return texture_uniform_sets[p_version]; } @@ -632,7 +635,7 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) { u.append_id(radiance); } else { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } uniforms.push_back(u); } @@ -648,9 +651,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -667,9 +670,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -793,6 +796,7 @@ RendererSceneSkyRD::RendererSceneSkyRD() { } void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); storage = p_storage; { @@ -972,7 +976,7 @@ void sky() { RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); u.append_id(vfog); uniforms.push_back(u); } @@ -1006,21 +1010,21 @@ void sky() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index f00931cf47..2a17a86e42 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -35,1114 +35,13 @@ #include "core/io/resource_loader.h" #include "core/math/math_defs.h" #include "renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_globals.h" #include "servers/rendering/shader_language.h" -bool RendererStorageRD::can_create_resources_async() const { - return true; -} - -Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) { - Ref<Image> image = p_image->duplicate(); - - switch (p_image->get_format()) { - case Image::FORMAT_L8: { - r_format.format = RD::DATA_FORMAT_R8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //luminance - case Image::FORMAT_LA8: { - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G; - } break; //luminance-alpha - case Image::FORMAT_R8: { - r_format.format = RD::DATA_FORMAT_R8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RG8: { - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGB8: { - //this format is not mandatory for specification, check if supported first - if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGBA8: { - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RGBA4444: { - r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RGB565: { - r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RF: { - r_format.format = RD::DATA_FORMAT_R32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //float - case Image::FORMAT_RGF: { - r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBF: { - //this format is not mandatory for specification, check if supported first - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - image->convert(Image::FORMAT_RGBAF); - } - - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBAF: { - r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; - case Image::FORMAT_RH: { - r_format.format = RD::DATA_FORMAT_R16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //half float - case Image::FORMAT_RGH: { - r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGBH: { - //this format is not mandatory for specification, check if supported first - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->convert(Image::FORMAT_RGBAH); - } - - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBAH: { - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; - case Image::FORMAT_RGBE9995: { - r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; -#ifndef _MSC_VER -#warning TODO need to make a function in Image to swap bits for this -#endif - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY; - } break; - case Image::FORMAT_DXT1: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //s3tc bc1 - case Image::FORMAT_DXT3: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; //bc2 - case Image::FORMAT_DXT5: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; //bc3 - case Image::FORMAT_RGTC_R: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGTC_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_BPTC_RGBA: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; //btpc bc7 - case Image::FORMAT_BPTC_RGBF: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->decompress(); - image->convert(Image::FORMAT_RGBAH); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //float bc6h - case Image::FORMAT_BPTC_RGBFU: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->decompress(); - image->convert(Image::FORMAT_RGBAH); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //unsigned float bc6hu - case Image::FORMAT_ETC2_R11: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //etc2 - case Image::FORMAT_ETC2_R11S: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_SNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //signed: {} break; NOT srgb. - case Image::FORMAT_ETC2_RG11: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_ETC2_RG11S: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_SNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_ETC: - case Image::FORMAT_ETC2_RGB8: { - //ETC2 is backwards compatible with ETC1, and all modern platforms support it - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_ETC2_RGBA8: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_ETC2_RGB8A1: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_ETC2_RA_AS_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_DXT5_RA_AS_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - - default: { - } - } - - return image; -} - -RID RendererStorageRD::texture_allocate() { - return texture_owner.allocate_rid(); -} - -void RendererStorageRD::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { - ERR_FAIL_COND(p_image.is_null()); - ERR_FAIL_COND(p_image->is_empty()); - - TextureToRDFormat ret_format; - Ref<Image> image = _validate_texture_format(p_image, ret_format); - - Texture texture; - - texture.type = Texture::TYPE_2D; - - texture.width = p_image->get_width(); - texture.height = p_image->get_height(); - texture.layers = 1; - texture.mipmaps = p_image->get_mipmap_count() + 1; - texture.depth = 1; - texture.format = p_image->get_format(); - texture.validated_format = image->get_format(); - - texture.rd_type = RD::TEXTURE_TYPE_2D; - texture.rd_format = ret_format.format; - texture.rd_format_srgb = ret_format.format_srgb; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = texture.rd_format; - rd_format.width = texture.width; - rd_format.height = texture.height; - rd_format.depth = 1; - rd_format.array_layers = 1; - rd_format.mipmaps = texture.mipmaps; - rd_format.texture_type = texture.rd_type; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_format.shareable_formats.push_back(texture.rd_format); - rd_format.shareable_formats.push_back(texture.rd_format_srgb); - } - } - { - rd_view.swizzle_r = ret_format.swizzle_r; - rd_view.swizzle_g = ret_format.swizzle_g; - rd_view.swizzle_b = ret_format.swizzle_b; - rd_view.swizzle_a = ret_format.swizzle_a; - } - Vector<uint8_t> data = image->get_data(); //use image data - Vector<Vector<uint8_t>> data_slices; - data_slices.push_back(data); - texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); - ERR_FAIL_COND(texture.rd_texture.is_null()); - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = texture.rd_format_srgb; - texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); - if (texture.rd_texture_srgb.is_null()) { - RD::get_singleton()->free(texture.rd_texture); - ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); - } - } - - //used for 2D, overridable - texture.width_2d = texture.width; - texture.height_2d = texture.height; - texture.is_render_target = false; - texture.rd_view = rd_view; - texture.is_proxy = false; - - texture_owner.initialize_rid(p_texture, texture); -} - -void RendererStorageRD::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { - ERR_FAIL_COND(p_layers.size() == 0); - - ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6); - ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0)); - - TextureToRDFormat ret_format; - Vector<Ref<Image>> images; - { - int valid_width = 0; - int valid_height = 0; - bool valid_mipmaps = false; - Image::Format valid_format = Image::FORMAT_MAX; - - for (int i = 0; i < p_layers.size(); i++) { - ERR_FAIL_COND(p_layers[i]->is_empty()); - - if (i == 0) { - valid_width = p_layers[i]->get_width(); - valid_height = p_layers[i]->get_height(); - valid_format = p_layers[i]->get_format(); - valid_mipmaps = p_layers[i]->has_mipmaps(); - } else { - ERR_FAIL_COND(p_layers[i]->get_width() != valid_width); - ERR_FAIL_COND(p_layers[i]->get_height() != valid_height); - ERR_FAIL_COND(p_layers[i]->get_format() != valid_format); - ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps); - } - - images.push_back(_validate_texture_format(p_layers[i], ret_format)); - } - } - - Texture texture; - - texture.type = Texture::TYPE_LAYERED; - texture.layered_type = p_layered_type; - - texture.width = p_layers[0]->get_width(); - texture.height = p_layers[0]->get_height(); - texture.layers = p_layers.size(); - texture.mipmaps = p_layers[0]->get_mipmap_count() + 1; - texture.depth = 1; - texture.format = p_layers[0]->get_format(); - texture.validated_format = images[0]->get_format(); - - switch (p_layered_type) { - case RS::TEXTURE_LAYERED_2D_ARRAY: { - texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY; - } break; - case RS::TEXTURE_LAYERED_CUBEMAP: { - texture.rd_type = RD::TEXTURE_TYPE_CUBE; - } break; - case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: { - texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY; - } break; - } - - texture.rd_format = ret_format.format; - texture.rd_format_srgb = ret_format.format_srgb; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = texture.rd_format; - rd_format.width = texture.width; - rd_format.height = texture.height; - rd_format.depth = 1; - rd_format.array_layers = texture.layers; - rd_format.mipmaps = texture.mipmaps; - rd_format.texture_type = texture.rd_type; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_format.shareable_formats.push_back(texture.rd_format); - rd_format.shareable_formats.push_back(texture.rd_format_srgb); - } - } - { - rd_view.swizzle_r = ret_format.swizzle_r; - rd_view.swizzle_g = ret_format.swizzle_g; - rd_view.swizzle_b = ret_format.swizzle_b; - rd_view.swizzle_a = ret_format.swizzle_a; - } - Vector<Vector<uint8_t>> data_slices; - for (int i = 0; i < images.size(); i++) { - Vector<uint8_t> data = images[i]->get_data(); //use image data - data_slices.push_back(data); - } - texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); - ERR_FAIL_COND(texture.rd_texture.is_null()); - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = texture.rd_format_srgb; - texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); - if (texture.rd_texture_srgb.is_null()) { - RD::get_singleton()->free(texture.rd_texture); - ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); - } - } - - //used for 2D, overridable - texture.width_2d = texture.width; - texture.height_2d = texture.height; - texture.is_render_target = false; - texture.rd_view = rd_view; - texture.is_proxy = false; - - texture_owner.initialize_rid(p_texture, texture); -} - -void RendererStorageRD::texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { - ERR_FAIL_COND(p_data.size() == 0); - Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); - if (verr != Image::VALIDATE_3D_OK) { - ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); - } - - TextureToRDFormat ret_format; - Image::Format validated_format = Image::FORMAT_MAX; - Vector<uint8_t> all_data; - uint32_t mipmap_count = 0; - Vector<Texture::BufferSlice3D> slices; - { - Vector<Ref<Image>> images; - uint32_t all_data_size = 0; - images.resize(p_data.size()); - for (int i = 0; i < p_data.size(); i++) { - TextureToRDFormat f; - images.write[i] = _validate_texture_format(p_data[i], f); - if (i == 0) { - ret_format = f; - validated_format = images[0]->get_format(); - } - - all_data_size += images[i]->get_data().size(); - } - - all_data.resize(all_data_size); //consolidate all data here - uint32_t offset = 0; - Size2i prev_size; - for (int i = 0; i < p_data.size(); i++) { - uint32_t s = images[i]->get_data().size(); - - memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); - { - Texture::BufferSlice3D slice; - slice.size.width = images[i]->get_width(); - slice.size.height = images[i]->get_height(); - slice.offset = offset; - slice.buffer_size = s; - slices.push_back(slice); - } - offset += s; - - Size2i img_size(images[i]->get_width(), images[i]->get_height()); - if (img_size != prev_size) { - mipmap_count++; - } - prev_size = img_size; - } - } - - Texture texture; - - texture.type = Texture::TYPE_3D; - texture.width = p_width; - texture.height = p_height; - texture.depth = p_depth; - texture.mipmaps = mipmap_count; - texture.format = p_data[0]->get_format(); - texture.validated_format = validated_format; - - texture.buffer_size_3d = all_data.size(); - texture.buffer_slices_3d = slices; - - texture.rd_type = RD::TEXTURE_TYPE_3D; - texture.rd_format = ret_format.format; - texture.rd_format_srgb = ret_format.format_srgb; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = texture.rd_format; - rd_format.width = texture.width; - rd_format.height = texture.height; - rd_format.depth = texture.depth; - rd_format.array_layers = 1; - rd_format.mipmaps = texture.mipmaps; - rd_format.texture_type = texture.rd_type; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_format.shareable_formats.push_back(texture.rd_format); - rd_format.shareable_formats.push_back(texture.rd_format_srgb); - } - } - { - rd_view.swizzle_r = ret_format.swizzle_r; - rd_view.swizzle_g = ret_format.swizzle_g; - rd_view.swizzle_b = ret_format.swizzle_b; - rd_view.swizzle_a = ret_format.swizzle_a; - } - Vector<Vector<uint8_t>> data_slices; - data_slices.push_back(all_data); //one slice - - texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); - ERR_FAIL_COND(texture.rd_texture.is_null()); - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = texture.rd_format_srgb; - texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); - if (texture.rd_texture_srgb.is_null()) { - RD::get_singleton()->free(texture.rd_texture); - ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); - } - } - - //used for 2D, overridable - texture.width_2d = texture.width; - texture.height_2d = texture.height; - texture.is_render_target = false; - texture.rd_view = rd_view; - texture.is_proxy = false; - - texture_owner.initialize_rid(p_texture, texture); -} - -void RendererStorageRD::texture_proxy_initialize(RID p_texture, RID p_base) { - Texture *tex = texture_owner.get_or_null(p_base); - ERR_FAIL_COND(!tex); - Texture proxy_tex = *tex; - - proxy_tex.rd_view.format_override = tex->rd_format; - proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); - if (proxy_tex.rd_texture_srgb.is_valid()) { - proxy_tex.rd_view.format_override = tex->rd_format_srgb; - proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); - } - proxy_tex.proxy_to = p_base; - proxy_tex.is_render_target = false; - proxy_tex.is_proxy = true; - proxy_tex.proxies.clear(); - - texture_owner.initialize_rid(p_texture, proxy_tex); - - tex->proxies.push_back(p_texture); -} - -void RendererStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) { - ERR_FAIL_COND(p_image.is_null() || p_image->is_empty()); - - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->is_render_target); - ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); - ERR_FAIL_COND(p_image->get_format() != tex->format); - - if (tex->type == Texture::TYPE_LAYERED) { - ERR_FAIL_INDEX(p_layer, tex->layers); - } - -#ifdef TOOLS_ENABLED - tex->image_cache_2d.unref(); -#endif - TextureToRDFormat f; - Ref<Image> validated = _validate_texture_format(p_image, f); - - RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data()); -} - -void RendererStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { - _texture_2d_update(p_texture, p_image, p_layer, false); -} - -void RendererStorageRD::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_3D); - Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data); - if (verr != Image::VALIDATE_3D_OK) { - ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); - } - - Vector<uint8_t> all_data; - { - Vector<Ref<Image>> images; - uint32_t all_data_size = 0; - images.resize(p_data.size()); - for (int i = 0; i < p_data.size(); i++) { - Ref<Image> image = p_data[i]; - if (image->get_format() != tex->validated_format) { - image = image->duplicate(); - image->convert(tex->validated_format); - } - all_data_size += images[i]->get_data().size(); - images.push_back(image); - } - - all_data.resize(all_data_size); //consolidate all data here - uint32_t offset = 0; - - for (int i = 0; i < p_data.size(); i++) { - uint32_t s = images[i]->get_data().size(); - memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); - offset += s; - } - } - - RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data); -} - -void RendererStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(!tex->is_proxy); - Texture *proxy_to = texture_owner.get_or_null(p_proxy_to); - ERR_FAIL_COND(!proxy_to); - ERR_FAIL_COND(proxy_to->is_proxy); - - if (tex->proxy_to.is_valid()) { - //unlink proxy - if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { - RD::get_singleton()->free(tex->rd_texture); - tex->rd_texture = RID(); - } - if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) { - RD::get_singleton()->free(tex->rd_texture_srgb); - tex->rd_texture_srgb = RID(); - } - Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to); - ERR_FAIL_COND(!prev_tex); - prev_tex->proxies.erase(p_texture); - } - - *tex = *proxy_to; - - tex->proxy_to = p_proxy_to; - tex->is_render_target = false; - tex->is_proxy = true; - tex->proxies.clear(); - proxy_to->proxies.push_back(p_texture); - - tex->rd_view.format_override = tex->rd_format; - tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); - if (tex->rd_texture_srgb.is_valid()) { - tex->rd_view.format_override = tex->rd_format_srgb; - tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); - } -} - -//these two APIs can be used together or in combination with the others. -void RendererStorageRD::texture_2d_placeholder_initialize(RID p_texture) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - texture_2d_initialize(p_texture, image); -} - -void RendererStorageRD::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - Vector<Ref<Image>> images; - if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) { - images.push_back(image); - } else { - //cube - for (int i = 0; i < 6; i++) { - images.push_back(image); - } - } - - texture_2d_layered_initialize(p_texture, images, p_layered_type); -} - -void RendererStorageRD::texture_3d_placeholder_initialize(RID p_texture) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - Vector<Ref<Image>> images; - //cube - for (int i = 0; i < 4; i++) { - images.push_back(image); - } - - texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images); -} - -Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); - -#ifdef TOOLS_ENABLED - if (tex->image_cache_2d.is_valid() && !tex->is_render_target) { - return tex->image_cache_2d; - } -#endif - Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); - ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instantiate(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); - } - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) { - tex->image_cache_2d = image; - } -#endif - - return image; -} - -Ref<Image> RendererStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); - - Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer); - ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instantiate(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); - } - - return image; -} - -Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); - ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>()); - - Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); - - ERR_FAIL_COND_V(all_data.size() != (int)tex->buffer_size_3d, Vector<Ref<Image>>()); - - Vector<Ref<Image>> ret; - - for (int i = 0; i < tex->buffer_slices_3d.size(); i++) { - const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i]; - ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>()); - ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>()); - Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size); - - Ref<Image> img; - img.instantiate(); - img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region); - ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>()); - if (tex->format != tex->validated_format) { - img->convert(tex->format); - } - - ret.push_back(img); - } - - return ret; -} - -void RendererStorageRD::texture_replace(RID p_texture, RID p_by_texture) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy - Texture *by_tex = texture_owner.get_or_null(p_by_texture); - ERR_FAIL_COND(!by_tex); - ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy - - if (tex == by_tex) { - return; - } - - if (tex->rd_texture_srgb.is_valid()) { - RD::get_singleton()->free(tex->rd_texture_srgb); - } - RD::get_singleton()->free(tex->rd_texture); - - if (tex->canvas_texture) { - memdelete(tex->canvas_texture); - tex->canvas_texture = nullptr; - } - - Vector<RID> proxies_to_update = tex->proxies; - Vector<RID> proxies_to_redirect = by_tex->proxies; - - *tex = *by_tex; - - tex->proxies = proxies_to_update; //restore proxies, so they can be updated - - if (tex->canvas_texture) { - tex->canvas_texture->diffuse = p_texture; //update - } - - for (int i = 0; i < proxies_to_update.size(); i++) { - texture_proxy_update(proxies_to_update[i], p_texture); - } - for (int i = 0; i < proxies_to_redirect.size(); i++) { - texture_proxy_update(proxies_to_redirect[i], p_texture); - } - //delete last, so proxies can be updated - texture_owner.free(p_by_texture); - - if (decal_atlas.textures.has(p_texture)) { - //belongs to decal atlas.. - - decal_atlas.dirty = true; //mark it dirty since it was most likely modified - } -} - -void RendererStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_2D); - tex->width_2d = p_width; - tex->height_2d = p_height; -} - -void RendererStorageRD::texture_set_path(RID p_texture, const String &p_path) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->path = p_path; -} - -String RendererStorageRD::texture_get_path(RID p_texture) const { - return String(); -} - -void RendererStorageRD::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_3d_callback_ud = p_userdata; - tex->detect_3d_callback = p_callback; -} - -void RendererStorageRD::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_normal_callback_ud = p_userdata; - tex->detect_normal_callback = p_callback; -} - -void RendererStorageRD::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_roughness_callback_ud = p_userdata; - tex->detect_roughness_callback = p_callback; -} - -void RendererStorageRD::texture_debug_usage(List<RS::TextureInfo> *r_info) { -} - -void RendererStorageRD::texture_set_proxy(RID p_proxy, RID p_base) { -} - -void RendererStorageRD::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { -} - -Size2 RendererStorageRD::texture_size_with_proxy(RID p_proxy) { - return texture_2d_get_size(p_proxy); -} - /* CANVAS TEXTURE */ -void RendererStorageRD::CanvasTexture::clear_sets() { - if (cleared_cache) { - return; - } - for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { - for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { - if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) { - RD::get_singleton()->free(uniform_sets[i][j]); - uniform_sets[i][j] = RID(); - } - } - } - cleared_cache = true; -} - -RendererStorageRD::CanvasTexture::~CanvasTexture() { - clear_sets(); -} - void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) { for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { @@ -1237,149 +136,6 @@ void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) { } } -RID RendererStorageRD::canvas_texture_allocate() { - return canvas_texture_owner.allocate_rid(); -} -void RendererStorageRD::canvas_texture_initialize(RID p_rid) { - canvas_texture_owner.initialize_rid(p_rid); -} - -void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - switch (p_channel) { - case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { - ct->diffuse = p_texture; - } break; - case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { - ct->normal_map = p_texture; - } break; - case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { - ct->specular = p_texture; - } break; - } - - ct->clear_sets(); -} - -void RendererStorageRD::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->specular_color.r = p_specular_color.r; - ct->specular_color.g = p_specular_color.g; - ct->specular_color.b = p_specular_color.b; - ct->specular_color.a = p_shininess; - ct->clear_sets(); -} - -void RendererStorageRD::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->texture_filter = p_filter; - ct->clear_sets(); -} - -void RendererStorageRD::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->texture_repeat = p_repeat; - ct->clear_sets(); -} - -bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) { - CanvasTexture *ct = nullptr; - - Texture *t = texture_owner.get_or_null(p_texture); - - if (t) { - //regular texture - if (!t->canvas_texture) { - t->canvas_texture = memnew(CanvasTexture); - t->canvas_texture->diffuse = p_texture; - } - - ct = t->canvas_texture; - } else { - ct = canvas_texture_owner.get_or_null(p_texture); - } - - if (!ct) { - return false; //invalid texture RID - } - - RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter; - ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false); - - RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat; - ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false); - - RID uniform_set = ct->uniform_sets[filter][repeat]; - if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //create and update - Vector<RD::Uniform> uniforms; - { //diffuse - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 0; - - t = texture_owner.get_or_null(ct->diffuse); - if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); - ct->size_cache = Size2i(1, 1); - } else { - u.append_id(t->rd_texture); - ct->size_cache = Size2i(t->width_2d, t->height_2d); - } - uniforms.push_back(u); - } - { //normal - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - - t = texture_owner.get_or_null(ct->normal_map); - if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); - ct->use_normal_cache = false; - } else { - u.append_id(t->rd_texture); - ct->use_normal_cache = true; - } - uniforms.push_back(u); - } - { //specular - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - - t = texture_owner.get_or_null(ct->specular); - if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); - ct->use_specular_cache = false; - } else { - u.append_id(t->rd_texture); - ct->use_specular_cache = true; - } - uniforms.push_back(u); - } - { //sampler - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 3; - u.append_id(sampler_rd_get_default(filter, repeat)); - uniforms.push_back(u); - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set); - ct->uniform_sets[filter][repeat] = uniform_set; - ct->cleared_cache = false; - } - - r_uniform_set = uniform_set; - r_size = ct->size_cache; - r_specular_shininess = ct->specular_color; - r_use_normal = ct->use_normal_cache; - r_use_specular = ct->use_specular_cache; - - return true; -} - /* SHADER API */ RID RendererStorageRD::shader_allocate() { @@ -1487,7 +243,7 @@ void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const Str Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); - if (p_texture.is_valid() && texture_owner.owns(p_texture)) { + if (p_texture.is_valid() && RendererRD::TextureStorage::get_singleton()->owns_texture(p_texture)) { if (!shader->default_texture_parameter.has(p_name)) { shader->default_texture_parameter[p_name] = Map<int, RID>(); } @@ -2642,11 +1398,12 @@ RendererStorageRD::MaterialData::~MaterialData() { } void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { - RendererStorageRD *singleton = (RendererStorageRD *)RendererStorage::base_singleton; + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + #ifdef TOOLS_ENABLED - Texture *roughness_detect_texture = nullptr; + RendererRD::Texture *roughness_detect_texture = nullptr; RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R; - Texture *normal_detect_texture = nullptr; + RendererRD::Texture *normal_detect_texture = nullptr; #endif bool uses_global_textures = false; @@ -2732,19 +1489,19 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari switch (p_texture_uniforms[i].hint) { case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_ANISO); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); } break; default: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } break; } } break; @@ -2753,27 +1510,27 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari switch (p_texture_uniforms[i].hint) { case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } break; default: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); } break; } } break; case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); } break; case ShaderLanguage::TYPE_ISAMPLER3D: case ShaderLanguage::TYPE_USAMPLER3D: case ShaderLanguage::TYPE_SAMPLER3D: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } break; case ShaderLanguage::TYPE_ISAMPLER2DARRAY: case ShaderLanguage::TYPE_USAMPLER2DARRAY: case ShaderLanguage::TYPE_SAMPLER2DARRAY: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } break; default: { @@ -2795,7 +1552,7 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO); for (int j = 0; j < textures.size(); j++) { - Texture *tex = singleton->texture_owner.get_or_null(textures[j]); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(textures[j]); if (tex) { rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; @@ -2817,7 +1574,7 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari #endif } if (rd_texture.is_null()) { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } #ifdef TOOLS_ENABLED if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { @@ -4946,6 +3703,8 @@ void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool } void RendererStorageRD::_particles_process(Particles *p_particles, double p_delta) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) { Vector<RD::Uniform> uniforms; @@ -5248,14 +4007,14 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) { RID rd_tex; if (i < collision_3d_textures_used) { - Texture *t = texture_owner.get_or_null(collision_3d_textures[i]); - if (t && t->type == Texture::TYPE_3D) { + RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]); + if (t && t->type == RendererRD::Texture::TYPE_3D) { rd_tex = t->rd_texture; } } if (rd_tex == RID()) { - rd_tex = default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE]; + rd_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } u.append_id(rd_tex); } @@ -5268,7 +4027,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt if (collision_heightmap_texture.is_valid()) { u.append_id(collision_heightmap_texture); } else { - u.append_id(default_rd_textures[DEFAULT_RD_TEXTURE_BLACK]); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); } @@ -6991,9 +5750,9 @@ void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, return; } - ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); + ERR_FAIL_COND(p_texture.is_valid() && !RendererRD::TextureStorage::get_singleton()->owns_texture(p_texture)); - if (decal->textures[p_type].is_valid() && texture_owner.owns(decal->textures[p_type])) { + if (decal->textures[p_type].is_valid() && RendererRD::TextureStorage::get_singleton()->owns_texture(decal->textures[p_type])) { texture_remove_from_decal_atlas(decal->textures[p_type]); } @@ -7398,6 +6157,8 @@ void RendererStorageRD::lightmap_initialize(RID p_lightmap) { } void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); ERR_FAIL_COND(!lm); @@ -7405,17 +6166,17 @@ void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool //erase lightmap users if (lm->light_texture.is_valid()) { - Texture *t = texture_owner.get_or_null(lm->light_texture); + RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture); if (t) { t->lightmap_users.erase(p_lightmap); } } - Texture *t = texture_owner.get_or_null(p_light); + RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light); lm->light_texture = p_light; lm->uses_spherical_harmonics = p_uses_spherical_haromics; - RID default_2d_array = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE]; + RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); if (!t) { if (using_lightmap_array) { if (lm->array_index >= 0) { @@ -7593,9 +6354,9 @@ void RendererStorageRD::_clear_render_target(RenderTarget *rt) { void RendererStorageRD::_update_render_target(RenderTarget *rt) { if (rt->texture.is_null()) { //create a placeholder until updated - rt->texture = texture_allocate(); - texture_2d_placeholder_initialize(rt->texture); - Texture *tex = texture_owner.get_or_null(rt->texture); + rt->texture = RendererRD::TextureStorage::get_singleton()->texture_allocate(); + RendererRD::TextureStorage::get_singleton()->texture_2d_placeholder_initialize(rt->texture); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture); tex->is_render_target = true; } @@ -7642,7 +6403,7 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) { { //update texture - Texture *tex = texture_owner.get_or_null(rt->texture); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture); //free existing textures if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { @@ -7678,7 +6439,7 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) { Vector<RID> proxies = tex->proxies; //make a copy, since update may change it for (int i = 0; i < proxies.size(); i++) { - texture_proxy_update(proxies[i], rt->texture); + RendererRD::TextureStorage::get_singleton()->texture_proxy_update(proxies[i], rt->texture); } } } @@ -8341,6 +7102,21 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { return RS::INSTANCE_NONE; } +void RendererStorageRD::decal_atlas_remove_texture(RID p_texture) { + if (decal_atlas.textures.has(p_texture)) { + decal_atlas.textures.erase(p_texture); + //there is not much a point of making it dirty, just let it be. + } +} + +void RendererStorageRD::decal_atlas_mark_dirty_on_texture(RID p_texture) { + if (decal_atlas.textures.has(p_texture)) { + //belongs to decal atlas.. + + decal_atlas.dirty = true; //mark it dirty since it was most likely modified + } +} + void RendererStorageRD::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) { if (!decal_atlas.textures.has(p_texture)) { DecalAtlas::Texture t; @@ -8406,7 +7182,7 @@ void RendererStorageRD::_update_decal_atlas() { while ((K = decal_atlas.textures.next(K))) { DecalAtlas::SortItem &si = itemsv.write[idx]; - Texture *src_tex = texture_owner.get_or_null(*K); + RendererRD::Texture *src_tex = RendererRD::TextureStorage::get_singleton()->get_texture(*K); si.size.width = (src_tex->width / border) + 1; si.size.height = (src_tex->height / border) + 1; @@ -8555,7 +7331,7 @@ void RendererStorageRD::_update_decal_atlas() { const RID *K = nullptr; while ((K = decal_atlas.textures.next(K))) { DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K); - Texture *src_tex = texture_owner.get_or_null(*K); + RendererRD::Texture *src_tex = RendererRD::TextureStorage::get_singleton()->get_texture(*K); effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0); } @@ -9265,47 +8041,10 @@ bool RendererStorageRD::has_os_feature(const String &p_feature) const { } bool RendererStorageRD::free(RID p_rid) { - if (texture_owner.owns(p_rid)) { - Texture *t = texture_owner.get_or_null(p_rid); - - ERR_FAIL_COND_V(!t, false); - ERR_FAIL_COND_V(t->is_render_target, false); - - if (RD::get_singleton()->texture_is_valid(t->rd_texture_srgb)) { - //erase this first, as it's a dependency of the one below - RD::get_singleton()->free(t->rd_texture_srgb); - } - if (RD::get_singleton()->texture_is_valid(t->rd_texture)) { - RD::get_singleton()->free(t->rd_texture); - } - - if (t->is_proxy && t->proxy_to.is_valid()) { - Texture *proxy_to = texture_owner.get_or_null(t->proxy_to); - if (proxy_to) { - proxy_to->proxies.erase(p_rid); - } - } - - if (decal_atlas.textures.has(p_rid)) { - decal_atlas.textures.erase(p_rid); - //there is not much a point of making it dirty, just let it be. - } - - for (int i = 0; i < t->proxies.size(); i++) { - Texture *p = texture_owner.get_or_null(t->proxies[i]); - ERR_CONTINUE(!p); - p->proxy_to = RID(); - p->rd_texture = RID(); - p->rd_texture_srgb = RID(); - } - - if (t->canvas_texture) { - memdelete(t->canvas_texture); - } - texture_owner.free(p_rid); - - } else if (canvas_texture_owner.owns(p_rid)) { - canvas_texture_owner.free(p_rid); + if (RendererRD::TextureStorage::get_singleton()->owns_texture(p_rid)) { + RendererRD::TextureStorage::get_singleton()->texture_free(p_rid); + } else if (RendererRD::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { + RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid); } else if (shader_owner.owns(p_rid)) { Shader *shader = shader_owner.get_or_null(p_rid); //make material unreference this @@ -9367,7 +8106,7 @@ bool RendererStorageRD::free(RID p_rid) { } else if (decal_owner.owns(p_rid)) { Decal *decal = decal_owner.get_or_null(p_rid); for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) { - if (decal->textures[i].is_valid() && texture_owner.owns(decal->textures[i])) { + if (decal->textures[i].is_valid() && RendererRD::TextureStorage::get_singleton()->owns_texture(decal->textures[i])) { texture_remove_from_decal_atlas(decal->textures[i]); } } @@ -9421,7 +8160,7 @@ bool RendererStorageRD::free(RID p_rid) { _clear_render_target(rt); if (rt->texture.is_valid()) { - Texture *tex = texture_owner.get_or_null(rt->texture); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture); tex->is_render_target = false; free(rt->texture); } @@ -9504,6 +8243,8 @@ RendererStorageRD *RendererStorageRD::base_singleton = nullptr; RendererStorageRD::RendererStorageRD() { base_singleton = this; + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + for (int i = 0; i < SHADER_TYPE_MAX; i++) { shader_data_request_func[i] = nullptr; } @@ -9518,8 +8259,7 @@ RendererStorageRD::RendererStorageRD() { memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size); - { //create default textures - + { // default atlas texture RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; tformat.width = 4; @@ -9529,18 +8269,6 @@ RendererStorageRD::RendererStorageRD() { Vector<uint8_t> pv; pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } for (int i = 0; i < 16; i++) { pv.set(i * 4 + 0, 0); @@ -9550,211 +8278,12 @@ RendererStorageRD::RendererStorageRD() { } { + //take the chance and initialize decal atlas to something Vector<Vector<uint8_t>> vpv; vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - - //take the chance and initialize decal atlas to something decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); decal_atlas.texture_srgb = decal_atlas.texture; } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 128); - pv.set(i * 4 + 1, 128); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 128); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv); - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT; - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default cubemap - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector<Vector<uint8_t>> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default cubemap array - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_CUBE; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector<Vector<uint8_t>> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default cubemap white array - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_CUBE; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default 3D - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.depth = 4; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_3D; - - Vector<uint8_t> pv; - pv.resize(64 * 4); - for (int i = 0; i < 64; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - for (int i = 0; i < 64; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default array - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 1; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } } //default samplers @@ -9970,7 +8499,7 @@ RendererStorageRD::RendererStorageRD() { } for (int i = 0; i < lightmap_textures.size(); i++) { - lightmap_textures.write[i] = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE]; + lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } } @@ -10177,11 +8706,6 @@ RendererStorageRD::~RendererStorageRD() { memdelete_arr(global_variables.buffer_dirty_regions); RD::get_singleton()->free(global_variables.buffer); - //def textures - for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) { - RD::get_singleton()->free(default_rd_textures[i]); - } - //def samplers for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 9416d04cdd..16f1b265a3 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -41,9 +41,12 @@ #include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/shader_compiler.h" + class RendererStorageRD : public RendererStorage { public: static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) { @@ -179,22 +182,6 @@ public: typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); static void _material_uniform_set_erased(void *p_material); - enum DefaultRDTexture { - DEFAULT_RD_TEXTURE_WHITE, - DEFAULT_RD_TEXTURE_BLACK, - DEFAULT_RD_TEXTURE_NORMAL, - DEFAULT_RD_TEXTURE_ANISO, - DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, - DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, - DEFAULT_RD_TEXTURE_3D_WHITE, - DEFAULT_RD_TEXTURE_3D_BLACK, - DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, - DEFAULT_RD_TEXTURE_2D_UINT, - DEFAULT_RD_TEXTURE_MAX - }; - enum DefaultRDBuffer { DEFAULT_RD_BUFFER_VERTEX, DEFAULT_RD_BUFFER_NORMAL, @@ -212,113 +199,8 @@ public: }; private: - /* CANVAS TEXTURE API (2D) */ - - struct CanvasTexture { - RID diffuse; - RID normal_map; - RID specular; - Color specular_color = Color(1, 1, 1, 1); - float shininess = 1.0; - - RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; - RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; - RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; - - Size2i size_cache = Size2i(1, 1); - bool use_normal_cache = false; - bool use_specular_cache = false; - bool cleared_cache = true; - void clear_sets(); - ~CanvasTexture(); - }; - - RID_Owner<CanvasTexture, true> canvas_texture_owner; - /* TEXTURE API */ - struct Texture { - enum Type { - TYPE_2D, - TYPE_LAYERED, - TYPE_3D - }; - - Type type; - RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; - - RenderingDevice::TextureType rd_type; - RID rd_texture; - RID rd_texture_srgb; - RenderingDevice::DataFormat rd_format; - RenderingDevice::DataFormat rd_format_srgb; - RD::TextureView rd_view; - - Image::Format format; - Image::Format validated_format; - - int width; - int height; - int depth; - int layers; - int mipmaps; - - int height_2d; - int width_2d; - - struct BufferSlice3D { - Size2i size; - uint32_t offset = 0; - uint32_t buffer_size = 0; - }; - Vector<BufferSlice3D> buffer_slices_3d; - uint32_t buffer_size_3d = 0; - - bool is_render_target; - bool is_proxy; - - Ref<Image> image_cache_2d; - String path; - - RID proxy_to; - Vector<RID> proxies; - Set<RID> lightmap_users; - - RS::TextureDetectCallback detect_3d_callback = nullptr; - void *detect_3d_callback_ud = nullptr; - - RS::TextureDetectCallback detect_normal_callback = nullptr; - void *detect_normal_callback_ud = nullptr; - - RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; - void *detect_roughness_callback_ud = nullptr; - - CanvasTexture *canvas_texture = nullptr; - }; - - struct TextureToRDFormat { - RD::DataFormat format; - RD::DataFormat format_srgb; - RD::TextureSwizzle swizzle_r; - RD::TextureSwizzle swizzle_g; - RD::TextureSwizzle swizzle_b; - RD::TextureSwizzle swizzle_a; - TextureToRDFormat() { - format = RD::DATA_FORMAT_MAX; - format_srgb = RD::DATA_FORMAT_MAX; - swizzle_r = RD::TEXTURE_SWIZZLE_R; - swizzle_g = RD::TEXTURE_SWIZZLE_G; - swizzle_b = RD::TEXTURE_SWIZZLE_B; - swizzle_a = RD::TEXTURE_SWIZZLE_A; - } - }; - - //textures can be created from threads, so this RID_Owner is thread safe - mutable RID_Owner<Texture, true> texture_owner; - - Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format); - - RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; RID default_rd_storage_buffer; @@ -1308,52 +1190,6 @@ private: EffectsRD *effects = nullptr; public: - virtual bool can_create_resources_async() const; - - /* TEXTURE API */ - - virtual RID texture_allocate(); - - virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image); - virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type); - virtual void texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); //all slices, then all the mipmaps, must be coherent - virtual void texture_proxy_initialize(RID p_texture, RID p_base); - - virtual void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate); - - virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); - virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data); - virtual void texture_proxy_update(RID p_texture, RID p_proxy_to); - - //these two APIs can be used together or in combination with the others. - virtual void texture_2d_placeholder_initialize(RID p_texture); - virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type); - virtual void texture_3d_placeholder_initialize(RID p_texture); - - virtual Ref<Image> texture_2d_get(RID p_texture) const; - virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const; - virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const; - - virtual void texture_replace(RID p_texture, RID p_by_texture); - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height); - - virtual void texture_set_path(RID p_texture, const String &p_path); - virtual String texture_get_path(RID p_texture) const; - - virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata); - - virtual void texture_debug_usage(List<RS::TextureInfo> *r_info); - - virtual void texture_set_proxy(RID p_proxy, RID p_base); - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable); - - virtual Size2 texture_size_with_proxy(RID p_proxy); - - virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false); - virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false); - RID decal_atlas_get_texture() const; RID decal_atlas_get_texture_srgb() const; _FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) { @@ -1367,33 +1203,6 @@ public: //internal usage - _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) { - if (p_texture.is_null()) { - return RID(); - } - Texture *tex = texture_owner.get_or_null(p_texture); - - if (!tex) { - return RID(); - } - return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; - } - - _FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) { - if (p_texture.is_null()) { - return Size2i(); - } - Texture *tex = texture_owner.get_or_null(p_texture); - - if (!tex) { - return Size2i(); - } - return Size2i(tex->width_2d, tex->height_2d); - } - - _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) { - return default_rd_textures[p_texture]; - } _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { return default_rd_samplers[p_filter][p_repeat]; } @@ -1405,19 +1214,6 @@ public: void sampler_rd_set_default(float p_mipmap_bias); - /* CANVAS TEXTURE API */ - - RID canvas_texture_allocate(); - void canvas_texture_initialize(RID p_canvas_texture); - - virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture); - virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess); - - virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter); - virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat); - - bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular); - /* SHADER API */ RID shader_allocate(); @@ -1926,7 +1722,7 @@ public: const Light *light = light_owner.get_or_null(p_light); ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); - return texture_owner.owns(light->projector); + return light_owner.owns(light->projector); } _FORCE_INLINE_ bool light_is_negative(RID p_light) const { @@ -2010,6 +1806,12 @@ public: virtual void decal_set_fade(RID p_decal, float p_above, float p_below); virtual void decal_set_normal_fade(RID p_decal, float p_fade); + void decal_atlas_mark_dirty_on_texture(RID p_texture); + void decal_atlas_remove_texture(RID p_texture); + + virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false); + virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false); + _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) { const Decal *decal = decal_owner.get_or_null(p_decal); return decal->extents; diff --git a/servers/rendering/renderer_rd/storage_rd/SCsub b/servers/rendering/renderer_rd/storage_rd/SCsub new file mode 100644 index 0000000000..86681f9c74 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp new file mode 100644 index 0000000000..3299b93ee2 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp @@ -0,0 +1,235 @@ +/*************************************************************************/ +/* canvas_texture_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "canvas_texture_storage.h" +#include "texture_storage.h" + +// Until we move things into their own storage classes, also include our old class +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" + +using namespace RendererRD; + +/////////////////////////////////////////////////////////////////////////// +// CanvasTexture + +void CanvasTexture::clear_sets() { + if (cleared_cache) { + return; + } + for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { + for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { + if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) { + RD::get_singleton()->free(uniform_sets[i][j]); + uniform_sets[i][j] = RID(); + } + } + } + cleared_cache = true; +} + +CanvasTexture::~CanvasTexture() { + clear_sets(); +} + +/////////////////////////////////////////////////////////////////////////// +// CanvasTextureStorage + +CanvasTextureStorage *CanvasTextureStorage::singleton = nullptr; + +CanvasTextureStorage *CanvasTextureStorage::get_singleton() { + return singleton; +} + +CanvasTextureStorage::CanvasTextureStorage() { + singleton = this; +} + +CanvasTextureStorage::~CanvasTextureStorage() { + singleton = nullptr; +} + +RID CanvasTextureStorage::canvas_texture_allocate() { + return canvas_texture_owner.allocate_rid(); +} + +void CanvasTextureStorage::canvas_texture_initialize(RID p_rid) { + canvas_texture_owner.initialize_rid(p_rid); +} + +void CanvasTextureStorage::canvas_texture_free(RID p_rid) { + canvas_texture_owner.free(p_rid); +} + +void CanvasTextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + + switch (p_channel) { + case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { + ct->diffuse = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { + ct->normal_map = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { + ct->specular = p_texture; + } break; + } + + ct->clear_sets(); +} + +void CanvasTextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + + ct->specular_color.r = p_specular_color.r; + ct->specular_color.g = p_specular_color.g; + ct->specular_color.b = p_specular_color.b; + ct->specular_color.a = p_shininess; + ct->clear_sets(); +} + +void CanvasTextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + + ct->texture_filter = p_filter; + ct->clear_sets(); +} + +void CanvasTextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + ct->texture_repeat = p_repeat; + ct->clear_sets(); +} + +bool CanvasTextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) { + RendererStorageRD *storage = RendererStorageRD::base_singleton; + + CanvasTexture *ct = nullptr; + TextureStorage *texture_storage = TextureStorage::get_singleton(); + Texture *t = texture_storage->get_texture(p_texture); + + // TODO once we have our texture storage split off we'll look into moving this code into canvas_texture + + if (t) { + //regular texture + if (!t->canvas_texture) { + t->canvas_texture = memnew(CanvasTexture); + t->canvas_texture->diffuse = p_texture; + } + + ct = t->canvas_texture; + } else { + ct = get_canvas_texture(p_texture); + } + + if (!ct) { + return false; //invalid texture RID + } + + RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter; + ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false); + + RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat; + ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false); + + RID uniform_set = ct->uniform_sets[filter][repeat]; + if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //create and update + Vector<RD::Uniform> uniforms; + { //diffuse + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + + t = texture_storage->get_texture(ct->diffuse); + if (!t) { + u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + ct->size_cache = Size2i(1, 1); + } else { + u.append_id(t->rd_texture); + ct->size_cache = Size2i(t->width_2d, t->height_2d); + } + uniforms.push_back(u); + } + { //normal + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + + t = texture_storage->get_texture(ct->normal_map); + if (!t) { + u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); + ct->use_normal_cache = false; + } else { + u.append_id(t->rd_texture); + ct->use_normal_cache = true; + } + uniforms.push_back(u); + } + { //specular + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + + t = texture_storage->get_texture(ct->specular); + if (!t) { + u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + ct->use_specular_cache = false; + } else { + u.append_id(t->rd_texture); + ct->use_specular_cache = true; + } + uniforms.push_back(u); + } + { //sampler + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 3; + u.append_id(storage->sampler_rd_get_default(filter, repeat)); + uniforms.push_back(u); + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set); + ct->uniform_sets[filter][repeat] = uniform_set; + ct->cleared_cache = false; + } + + r_uniform_set = uniform_set; + r_size = ct->size_cache; + r_specular_shininess = ct->specular_color; + r_use_normal = ct->use_normal_cache; + r_use_specular = ct->use_specular_cache; + + return true; +} diff --git a/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h new file mode 100644 index 0000000000..6d3868edd5 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h @@ -0,0 +1,90 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_RD_H +#define CANVAS_TEXTURE_STORAGE_RD_H + +#include "core/templates/rid_owner.h" +#include "servers/rendering/storage/canvas_texture_storage.h" + +namespace RendererRD { + +class CanvasTexture { +public: + RID diffuse; + RID normal_map; + RID specular; + Color specular_color = Color(1, 1, 1, 1); + float shininess = 1.0; + + RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; + RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; + RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + + Size2i size_cache = Size2i(1, 1); + bool use_normal_cache = false; + bool use_specular_cache = false; + bool cleared_cache = true; + + void clear_sets(); + ~CanvasTexture(); +}; + +class CanvasTextureStorage : public RendererCanvasTextureStorage { +private: + static CanvasTextureStorage *singleton; + + RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner; + +public: + static CanvasTextureStorage *get_singleton(); + + CanvasTextureStorage(); + virtual ~CanvasTextureStorage(); + + CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); }; + bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; + + virtual RID canvas_texture_allocate() override; + virtual void canvas_texture_initialize(RID p_rid) override; + virtual void canvas_texture_free(RID p_rid) override; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override; + + bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular); +}; + +} // namespace RendererRD + +#endif // !CANVAS_TEXTURE_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp new file mode 100644 index 0000000000..acdaaae7a4 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -0,0 +1,1420 @@ +/*************************************************************************/ +/* texture_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "texture_storage.h" + +// only include until we have DecalStorage sorted +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" + +using namespace RendererRD; + +/////////////////////////////////////////////////////////////////////////// +// Texture + +void Texture::cleanup() { + if (RD::get_singleton()->texture_is_valid(rd_texture_srgb)) { + //erase this first, as it's a dependency of the one below + RD::get_singleton()->free(rd_texture_srgb); + } + if (RD::get_singleton()->texture_is_valid(rd_texture)) { + RD::get_singleton()->free(rd_texture); + } + if (canvas_texture) { + memdelete(canvas_texture); + } +} + +/////////////////////////////////////////////////////////////////////////// +// TextureStorage + +TextureStorage *TextureStorage::singleton = nullptr; + +TextureStorage *TextureStorage::get_singleton() { + return singleton; +} + +TextureStorage::TextureStorage() { + singleton = this; + + { //create default textures + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 128); + pv.set(i * 4 + 1, 128); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 128); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv); + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT; + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap white array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default 3D + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.depth = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_3D; + + Vector<uint8_t> pv; + pv.resize(64 * 4); + for (int i = 0; i < 64; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + for (int i = 0; i < 64; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 1; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } +} + +TextureStorage::~TextureStorage() { + singleton = nullptr; + + //def textures + for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) { + texture_free(default_rd_textures[i]); + } +} + +bool TextureStorage::can_create_resources_async() const { + return true; +} + +RID TextureStorage::texture_allocate() { + return texture_owner.allocate_rid(); +} + +void TextureStorage::texture_free(RID p_texture) { + Texture *t = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!t); + ERR_FAIL_COND(t->is_render_target); + + t->cleanup(); + + if (t->is_proxy && t->proxy_to.is_valid()) { + Texture *proxy_to = texture_owner.get_or_null(t->proxy_to); + if (proxy_to) { + proxy_to->proxies.erase(p_texture); + } + } + + RendererStorageRD::base_singleton->decal_atlas_remove_texture(p_texture); + + for (int i = 0; i < t->proxies.size(); i++) { + Texture *p = texture_owner.get_or_null(t->proxies[i]); + ERR_CONTINUE(!p); + p->proxy_to = RID(); + p->rd_texture = RID(); + p->rd_texture_srgb = RID(); + } + + texture_owner.free(p_texture); +} + +void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { + TextureToRDFormat ret_format; + Ref<Image> image = _validate_texture_format(p_image, ret_format); + + Texture texture; + + texture.type = Texture::TYPE_2D; + + texture.width = p_image->get_width(); + texture.height = p_image->get_height(); + texture.layers = 1; + texture.mipmaps = p_image->get_mipmap_count() + 1; + texture.depth = 1; + texture.format = p_image->get_format(); + texture.validated_format = image->get_format(); + + texture.rd_type = RD::TEXTURE_TYPE_2D; + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = 1; + rd_format.array_layers = 1; + rd_format.mipmaps = texture.mipmaps; + rd_format.texture_type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector<uint8_t> data = image->get_data(); //use image data + Vector<Vector<uint8_t>> data_slices; + data_slices.push_back(data); + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND(texture.rd_texture.is_null()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + texture_owner.initialize_rid(p_texture, texture); +} + +void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { + ERR_FAIL_COND(p_layers.size() == 0); + + ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6); + ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0)); + + TextureToRDFormat ret_format; + Vector<Ref<Image>> images; + { + int valid_width = 0; + int valid_height = 0; + bool valid_mipmaps = false; + Image::Format valid_format = Image::FORMAT_MAX; + + for (int i = 0; i < p_layers.size(); i++) { + ERR_FAIL_COND(p_layers[i]->is_empty()); + + if (i == 0) { + valid_width = p_layers[i]->get_width(); + valid_height = p_layers[i]->get_height(); + valid_format = p_layers[i]->get_format(); + valid_mipmaps = p_layers[i]->has_mipmaps(); + } else { + ERR_FAIL_COND(p_layers[i]->get_width() != valid_width); + ERR_FAIL_COND(p_layers[i]->get_height() != valid_height); + ERR_FAIL_COND(p_layers[i]->get_format() != valid_format); + ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps); + } + + images.push_back(_validate_texture_format(p_layers[i], ret_format)); + } + } + + Texture texture; + + texture.type = Texture::TYPE_LAYERED; + texture.layered_type = p_layered_type; + + texture.width = p_layers[0]->get_width(); + texture.height = p_layers[0]->get_height(); + texture.layers = p_layers.size(); + texture.mipmaps = p_layers[0]->get_mipmap_count() + 1; + texture.depth = 1; + texture.format = p_layers[0]->get_format(); + texture.validated_format = images[0]->get_format(); + + switch (p_layered_type) { + case RS::TEXTURE_LAYERED_2D_ARRAY: { + texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY; + } break; + case RS::TEXTURE_LAYERED_CUBEMAP: { + texture.rd_type = RD::TEXTURE_TYPE_CUBE; + } break; + case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: { + texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + } break; + } + + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = 1; + rd_format.array_layers = texture.layers; + rd_format.mipmaps = texture.mipmaps; + rd_format.texture_type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector<Vector<uint8_t>> data_slices; + for (int i = 0; i < images.size(); i++) { + Vector<uint8_t> data = images[i]->get_data(); //use image data + data_slices.push_back(data); + } + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND(texture.rd_texture.is_null()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + texture_owner.initialize_rid(p_texture, texture); +} + +void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { + ERR_FAIL_COND(p_data.size() == 0); + + Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); + if (verr != Image::VALIDATE_3D_OK) { + ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); + } + + TextureToRDFormat ret_format; + Image::Format validated_format = Image::FORMAT_MAX; + Vector<uint8_t> all_data; + uint32_t mipmap_count = 0; + Vector<Texture::BufferSlice3D> slices; + { + Vector<Ref<Image>> images; + uint32_t all_data_size = 0; + images.resize(p_data.size()); + for (int i = 0; i < p_data.size(); i++) { + TextureToRDFormat f; + images.write[i] = _validate_texture_format(p_data[i], f); + if (i == 0) { + ret_format = f; + validated_format = images[0]->get_format(); + } + + all_data_size += images[i]->get_data().size(); + } + + all_data.resize(all_data_size); //consolidate all data here + uint32_t offset = 0; + Size2i prev_size; + for (int i = 0; i < p_data.size(); i++) { + uint32_t s = images[i]->get_data().size(); + + memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); + { + Texture::BufferSlice3D slice; + slice.size.width = images[i]->get_width(); + slice.size.height = images[i]->get_height(); + slice.offset = offset; + slice.buffer_size = s; + slices.push_back(slice); + } + offset += s; + + Size2i img_size(images[i]->get_width(), images[i]->get_height()); + if (img_size != prev_size) { + mipmap_count++; + } + prev_size = img_size; + } + } + + Texture texture; + + texture.type = Texture::TYPE_3D; + texture.width = p_width; + texture.height = p_height; + texture.depth = p_depth; + texture.mipmaps = mipmap_count; + texture.format = p_data[0]->get_format(); + texture.validated_format = validated_format; + + texture.buffer_size_3d = all_data.size(); + texture.buffer_slices_3d = slices; + + texture.rd_type = RD::TEXTURE_TYPE_3D; + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = texture.depth; + rd_format.array_layers = 1; + rd_format.mipmaps = texture.mipmaps; + rd_format.texture_type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector<Vector<uint8_t>> data_slices; + data_slices.push_back(all_data); //one slice + + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND(texture.rd_texture.is_null()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + texture_owner.initialize_rid(p_texture, texture); +} + +void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) { + Texture *tex = texture_owner.get_or_null(p_base); + ERR_FAIL_COND(!tex); + Texture proxy_tex = *tex; + + proxy_tex.rd_view.format_override = tex->rd_format; + proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); + if (proxy_tex.rd_texture_srgb.is_valid()) { + proxy_tex.rd_view.format_override = tex->rd_format_srgb; + proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); + } + proxy_tex.proxy_to = p_base; + proxy_tex.is_render_target = false; + proxy_tex.is_proxy = true; + proxy_tex.proxies.clear(); + + texture_owner.initialize_rid(p_texture, proxy_tex); + + tex->proxies.push_back(p_texture); +} + +void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) { + ERR_FAIL_COND(p_image.is_null() || p_image->is_empty()); + + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->is_render_target); + ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); + ERR_FAIL_COND(p_image->get_format() != tex->format); + + if (tex->type == Texture::TYPE_LAYERED) { + ERR_FAIL_INDEX(p_layer, tex->layers); + } + +#ifdef TOOLS_ENABLED + tex->image_cache_2d.unref(); +#endif + TextureToRDFormat f; + Ref<Image> validated = _validate_texture_format(p_image, f); + + RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data()); +} + +void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { + _texture_2d_update(p_texture, p_image, p_layer, false); +} + +void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->type != Texture::TYPE_3D); + + Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data); + if (verr != Image::VALIDATE_3D_OK) { + ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); + } + + Vector<uint8_t> all_data; + { + Vector<Ref<Image>> images; + uint32_t all_data_size = 0; + images.resize(p_data.size()); + for (int i = 0; i < p_data.size(); i++) { + Ref<Image> image = p_data[i]; + if (image->get_format() != tex->validated_format) { + image = image->duplicate(); + image->convert(tex->validated_format); + } + all_data_size += images[i]->get_data().size(); + images.push_back(image); + } + + all_data.resize(all_data_size); //consolidate all data here + uint32_t offset = 0; + + for (int i = 0; i < p_data.size(); i++) { + uint32_t s = images[i]->get_data().size(); + memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); + offset += s; + } + } + + RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data); +} + +void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(!tex->is_proxy); + Texture *proxy_to = texture_owner.get_or_null(p_proxy_to); + ERR_FAIL_COND(!proxy_to); + ERR_FAIL_COND(proxy_to->is_proxy); + + if (tex->proxy_to.is_valid()) { + //unlink proxy + if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { + RD::get_singleton()->free(tex->rd_texture); + tex->rd_texture = RID(); + } + if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) { + RD::get_singleton()->free(tex->rd_texture_srgb); + tex->rd_texture_srgb = RID(); + } + Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to); + ERR_FAIL_COND(!prev_tex); + prev_tex->proxies.erase(p_texture); + } + + *tex = *proxy_to; + + tex->proxy_to = p_proxy_to; + tex->is_render_target = false; + tex->is_proxy = true; + tex->proxies.clear(); + proxy_to->proxies.push_back(p_texture); + + tex->rd_view.format_override = tex->rd_format; + tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); + if (tex->rd_texture_srgb.is_valid()) { + tex->rd_view.format_override = tex->rd_format_srgb; + tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); + } +} + +//these two APIs can be used together or in combination with the others. +void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref<Image> image; + image.instantiate(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + image->fill(Color(1, 0, 1, 1)); + + texture_2d_initialize(p_texture, image); +} + +void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) { + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref<Image> image; + image.instantiate(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + image->fill(Color(1, 0, 1, 1)); + + Vector<Ref<Image>> images; + if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) { + images.push_back(image); + } else { + //cube + for (int i = 0; i < 6; i++) { + images.push_back(image); + } + } + + texture_2d_layered_initialize(p_texture, images, p_layered_type); +} + +void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref<Image> image; + image.instantiate(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + image->fill(Color(1, 0, 1, 1)); + + Vector<Ref<Image>> images; + //cube + for (int i = 0; i < 4; i++) { + images.push_back(image); + } + + texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images); +} + +Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Ref<Image>()); + +#ifdef TOOLS_ENABLED + if (tex->image_cache_2d.is_valid() && !tex->is_render_target) { + return tex->image_cache_2d; + } +#endif + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); + Ref<Image> image; + image.instantiate(); + image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); + if (tex->format != tex->validated_format) { + image->convert(tex->format); + } + +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) { + tex->image_cache_2d = image; + } +#endif + + return image; +} + +Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Ref<Image>()); + + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer); + ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); + Ref<Image> image; + image.instantiate(); + image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); + if (tex->format != tex->validated_format) { + image->convert(tex->format); + } + + return image; +} + +Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); + ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>()); + + Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + + ERR_FAIL_COND_V(all_data.size() != (int)tex->buffer_size_3d, Vector<Ref<Image>>()); + + Vector<Ref<Image>> ret; + + for (int i = 0; i < tex->buffer_slices_3d.size(); i++) { + const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i]; + ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>()); + ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>()); + Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size); + + Ref<Image> img; + img.instantiate(); + img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region); + ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>()); + if (tex->format != tex->validated_format) { + img->convert(tex->format); + } + + ret.push_back(img); + } + + return ret; +} + +void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy + Texture *by_tex = texture_owner.get_or_null(p_by_texture); + ERR_FAIL_COND(!by_tex); + ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy + + if (tex == by_tex) { + return; + } + + if (tex->rd_texture_srgb.is_valid()) { + RD::get_singleton()->free(tex->rd_texture_srgb); + } + RD::get_singleton()->free(tex->rd_texture); + + if (tex->canvas_texture) { + memdelete(tex->canvas_texture); + tex->canvas_texture = nullptr; + } + + Vector<RID> proxies_to_update = tex->proxies; + Vector<RID> proxies_to_redirect = by_tex->proxies; + + *tex = *by_tex; + + tex->proxies = proxies_to_update; //restore proxies, so they can be updated + + if (tex->canvas_texture) { + tex->canvas_texture->diffuse = p_texture; //update + } + + for (int i = 0; i < proxies_to_update.size(); i++) { + texture_proxy_update(proxies_to_update[i], p_texture); + } + for (int i = 0; i < proxies_to_redirect.size(); i++) { + texture_proxy_update(proxies_to_redirect[i], p_texture); + } + //delete last, so proxies can be updated + texture_owner.free(p_by_texture); + + RendererStorageRD::base_singleton->decal_atlas_mark_dirty_on_texture(p_texture); +} + +void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->type != Texture::TYPE_2D); + + tex->width_2d = p_width; + tex->height_2d = p_height; +} + +void TextureStorage::texture_set_path(RID p_texture, const String &p_path) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->path = p_path; +} + +String TextureStorage::texture_get_path(RID p_texture) const { + RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, String()); + + return tex->path; +} + +void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->detect_3d_callback_ud = p_userdata; + tex->detect_3d_callback = p_callback; +} + +void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->detect_normal_callback_ud = p_userdata; + tex->detect_normal_callback = p_callback; +} + +void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->detect_roughness_callback_ud = p_userdata; + tex->detect_roughness_callback = p_callback; +} + +void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) { +} + +void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { +} + +Size2 TextureStorage::texture_size_with_proxy(RID p_proxy) { + return texture_2d_get_size(p_proxy); +} + +Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) { + Ref<Image> image = p_image->duplicate(); + + switch (p_image->get_format()) { + case Image::FORMAT_L8: { + r_format.format = RD::DATA_FORMAT_R8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //luminance + case Image::FORMAT_LA8: { + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G; + } break; //luminance-alpha + case Image::FORMAT_R8: { + r_format.format = RD::DATA_FORMAT_R8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RG8: { + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGB8: { + //this format is not mandatory for specification, check if supported first + if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGBA8: { + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RGBA4444: { + r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RGB565: { + r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RF: { + r_format.format = RD::DATA_FORMAT_R32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //float + case Image::FORMAT_RGF: { + r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBF: { + //this format is not mandatory for specification, check if supported first + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + image->convert(Image::FORMAT_RGBAF); + } + + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBAF: { + r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; + case Image::FORMAT_RH: { + r_format.format = RD::DATA_FORMAT_R16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //half float + case Image::FORMAT_RGH: { + r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGBH: { + //this format is not mandatory for specification, check if supported first + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->convert(Image::FORMAT_RGBAH); + } + + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBAH: { + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; + case Image::FORMAT_RGBE9995: { + r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; +#ifndef _MSC_VER +#warning TODO need to make a function in Image to swap bits for this +#endif + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY; + } break; + case Image::FORMAT_DXT1: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //s3tc bc1 + case Image::FORMAT_DXT3: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; //bc2 + case Image::FORMAT_DXT5: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; //bc3 + case Image::FORMAT_RGTC_R: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGTC_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_BPTC_RGBA: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; //btpc bc7 + case Image::FORMAT_BPTC_RGBF: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->decompress(); + image->convert(Image::FORMAT_RGBAH); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //float bc6h + case Image::FORMAT_BPTC_RGBFU: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->decompress(); + image->convert(Image::FORMAT_RGBAH); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //unsigned float bc6hu + case Image::FORMAT_ETC2_R11: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //etc2 + case Image::FORMAT_ETC2_R11S: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_SNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //signed: {} break; NOT srgb. + case Image::FORMAT_ETC2_RG11: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_ETC2_RG11S: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_SNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_ETC: + case Image::FORMAT_ETC2_RGB8: { + //ETC2 is backwards compatible with ETC1, and all modern platforms support it + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_ETC2_RGBA8: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_ETC2_RGB8A1: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_ETC2_RA_AS_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_DXT5_RA_AS_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + + default: { + } + } + + return image; +} diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h new file mode 100644 index 0000000000..5d8d165a08 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -0,0 +1,230 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_RD_H +#define TEXTURE_STORAGE_RD_H + +#include "canvas_texture_storage.h" +#include "core/templates/rid_owner.h" +#include "servers/rendering/storage/texture_storage.h" + +namespace RendererRD { + +enum DefaultRDTexture { + DEFAULT_RD_TEXTURE_WHITE, + DEFAULT_RD_TEXTURE_BLACK, + DEFAULT_RD_TEXTURE_NORMAL, + DEFAULT_RD_TEXTURE_ANISO, + DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, + DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, + DEFAULT_RD_TEXTURE_3D_WHITE, + DEFAULT_RD_TEXTURE_3D_BLACK, + DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, + DEFAULT_RD_TEXTURE_2D_UINT, + DEFAULT_RD_TEXTURE_MAX +}; + +class Texture { +public: + enum Type { + TYPE_2D, + TYPE_LAYERED, + TYPE_3D + }; + + Type type; + RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; + + RenderingDevice::TextureType rd_type; + RID rd_texture; + RID rd_texture_srgb; + RenderingDevice::DataFormat rd_format; + RenderingDevice::DataFormat rd_format_srgb; + + RD::TextureView rd_view; + + Image::Format format; + Image::Format validated_format; + + int width; + int height; + int depth; + int layers; + int mipmaps; + + int height_2d; + int width_2d; + + struct BufferSlice3D { + Size2i size; + uint32_t offset = 0; + uint32_t buffer_size = 0; + }; + Vector<BufferSlice3D> buffer_slices_3d; + uint32_t buffer_size_3d = 0; + + bool is_render_target; + bool is_proxy; + + Ref<Image> image_cache_2d; + String path; + + RID proxy_to; + Vector<RID> proxies; + + Set<RID> lightmap_users; + + RS::TextureDetectCallback detect_3d_callback = nullptr; + void *detect_3d_callback_ud = nullptr; + + RS::TextureDetectCallback detect_normal_callback = nullptr; + void *detect_normal_callback_ud = nullptr; + + RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; + void *detect_roughness_callback_ud = nullptr; + + CanvasTexture *canvas_texture = nullptr; + + void cleanup(); +}; + +class TextureStorage : public RendererTextureStorage { +private: + static TextureStorage *singleton; + + //textures can be created from threads, so this RID_Owner is thread safe + mutable RID_Owner<Texture, true> texture_owner; + + struct TextureToRDFormat { + RD::DataFormat format; + RD::DataFormat format_srgb; + RD::TextureSwizzle swizzle_r; + RD::TextureSwizzle swizzle_g; + RD::TextureSwizzle swizzle_b; + RD::TextureSwizzle swizzle_a; + TextureToRDFormat() { + format = RD::DATA_FORMAT_MAX; + format_srgb = RD::DATA_FORMAT_MAX; + swizzle_r = RD::TEXTURE_SWIZZLE_R; + swizzle_g = RD::TEXTURE_SWIZZLE_G; + swizzle_b = RD::TEXTURE_SWIZZLE_B; + swizzle_a = RD::TEXTURE_SWIZZLE_A; + } + }; + + Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format); + void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0, bool p_immediate = false); + +public: + static TextureStorage *get_singleton(); + + RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; + + _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) { + return default_rd_textures[p_texture]; + } + + TextureStorage(); + virtual ~TextureStorage(); + + Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + + virtual bool can_create_resources_async() const override; + + virtual RID texture_allocate() override; + virtual void texture_free(RID p_rid) override; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override; + virtual void texture_proxy_update(RID p_proxy, RID p_base) override; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) override; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override; + virtual void texture_3d_placeholder_initialize(RID p_texture) override; + + virtual Ref<Image> texture_2d_get(RID p_texture) const override; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override; + + virtual void texture_replace(RID p_texture, RID p_by_texture) override; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override; + + virtual void texture_set_path(RID p_texture, const String &p_path) override; + virtual String texture_get_path(RID p_texture) const override; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override; + + virtual Size2 texture_size_with_proxy(RID p_proxy) override; + + //internal usage + + _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) { + if (p_texture.is_null()) { + return RID(); + } + RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + + if (!tex) { + return RID(); + } + return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; + } + + _FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) { + if (p_texture.is_null()) { + return Size2i(); + } + RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + + if (!tex) { + return Size2i(); + } + return Size2i(tex->width_2d, tex->height_2d); + } +}; + +} // namespace RendererRD + +#endif // !_TEXTURE_STORAGE_RD_H diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index ca3d3a048d..af4c697751 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -121,59 +121,6 @@ public: Set<Dependency *> dependencies; }; - virtual bool can_create_resources_async() const = 0; - /* TEXTURE API */ - - virtual RID texture_allocate() = 0; - - virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0; - virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0; - virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; - virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent - - virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; - virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; - virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; - - //these two APIs can be used together or in combination with the others. - virtual void texture_2d_placeholder_initialize(RID p_texture) = 0; - virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0; - virtual void texture_3d_placeholder_initialize(RID p_texture) = 0; - - virtual Ref<Image> texture_2d_get(RID p_texture) const = 0; - virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0; - virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0; - - virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; - - 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_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; - - virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0; - - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; - - virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; - - virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; - virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; - - /* CANVAS TEXTURE API */ - - virtual RID canvas_texture_allocate() = 0; - virtual void canvas_texture_initialize(RID p_rid) = 0; - - virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0; - virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; - - virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0; - virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0; - /* SHADER API */ virtual RID shader_allocate() = 0; @@ -397,6 +344,9 @@ public: virtual AABB decal_get_aabb(RID p_decal) const = 0; + virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; + virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; + /* VOXEL GI API */ virtual RID voxel_gi_allocate() = 0; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index b448a15d8e..f492c5e9bd 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -293,7 +293,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasRender::Light *cl = F->get(); if (cl->enabled && cl->texture.is_valid()) { //not super efficient.. - Size2 tsize = RSG::storage->texture_size_with_proxy(cl->texture); + Size2 tsize = RSG::texture_storage->texture_size_with_proxy(cl->texture); tsize *= cl->scale; Vector2 offset = tsize / 2.0; diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index d93aad5d7b..af02e25cd9 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -398,6 +398,8 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) : RendererSceneCull *sr = memnew(RendererSceneCull); RSG::scene = sr; RSG::rasterizer = RendererCompositor::create(); + RSG::canvas_texture_storage = RSG::rasterizer->get_canvas_texture_storage(); + RSG::texture_storage = RSG::rasterizer->get_texture_storage(); RSG::storage = RSG::rasterizer->get_storage(); RSG::canvas_render = RSG::rasterizer->get_canvas(); sr->set_scene_render(RSG::rasterizer->get_scene()); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 4a8944ccdd..8c93308e38 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -126,54 +126,53 @@ public: #include "servers/server_wrap_mt_common.h" -//from now on, calls forwarded to this singleton -#define ServerName RendererStorage -#define server_name RSG::storage - /* TEXTURE API */ -#define FUNCRIDTEX0(m_type) \ - virtual RID m_type##_create() override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret); \ - } \ - return ret; \ +#define ServerName RendererTextureStorage +#define server_name RSG::texture_storage + +#define FUNCRIDTEX0(m_type) \ + virtual RID m_type##_create() override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret); \ + } \ + return ret; \ } -#define FUNCRIDTEX1(m_type, m_type1) \ - virtual RID m_type##_create(m_type1 p1) override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret, p1); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1); \ - } \ - return ret; \ +#define FUNCRIDTEX1(m_type, m_type1) \ + virtual RID m_type##_create(m_type1 p1) override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret, p1); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1); \ + } \ + return ret; \ } -#define FUNCRIDTEX2(m_type, m_type1, m_type2) \ - virtual RID m_type##_create(m_type1 p1, m_type2 p2) override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret, p1, p2); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2); \ - } \ - return ret; \ +#define FUNCRIDTEX2(m_type, m_type1, m_type2) \ + virtual RID m_type##_create(m_type1 p1, m_type2 p2) override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret, p1, p2); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2); \ + } \ + return ret; \ } -#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ - virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6); \ - } \ - return ret; \ +#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ + virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6); \ + } \ + return ret; \ } //these go pass-through, as they can be called from any thread @@ -214,6 +213,13 @@ public: FUNC2(texture_set_force_redraw_if_visible, RID, bool) +//from now on, calls forwarded to this singleton +#undef ServerName +#undef server_name + +#define ServerName RendererStorage +#define server_name RSG::storage + /* SHADER API */ FUNCRIDSPLIT(shader) @@ -246,7 +252,9 @@ public: virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override { RID mesh = RSG::storage->mesh_allocate(); - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { + // TODO once we have RSG::mesh_storage, add can_create_resources_async and call here instead of texture_storage!! + + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { if (Thread::get_caller_id() == server_thread) { command_queue.flush_if_pending(); } diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp index b8b06b5eea..83aa8959c1 100644 --- a/servers/rendering/rendering_server_globals.cpp +++ b/servers/rendering/rendering_server_globals.cpp @@ -32,6 +32,8 @@ bool RenderingServerGlobals::threaded = false; +RendererCanvasTextureStorage *RenderingServerGlobals::canvas_texture_storage = nullptr; +RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr; RendererStorage *RenderingServerGlobals::storage = nullptr; RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr; RendererCompositor *RenderingServerGlobals::rasterizer = nullptr; diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h index 4351830a5f..2bef490760 100644 --- a/servers/rendering/rendering_server_globals.h +++ b/servers/rendering/rendering_server_globals.h @@ -34,6 +34,8 @@ #include "servers/rendering/renderer_canvas_cull.h" #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_scene.h" +#include "servers/rendering/storage/canvas_texture_storage.h" +#include "servers/rendering/storage/texture_storage.h" class RendererCanvasCull; class RendererViewport; @@ -43,6 +45,8 @@ class RenderingServerGlobals { public: static bool threaded; + static RendererCanvasTextureStorage *canvas_texture_storage; + static RendererTextureStorage *texture_storage; static RendererStorage *storage; static RendererCanvasRender *canvas_render; static RendererCompositor *rasterizer; diff --git a/servers/rendering/storage/SCsub b/servers/rendering/storage/SCsub new file mode 100644 index 0000000000..86681f9c74 --- /dev/null +++ b/servers/rendering/storage/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/rendering/storage/canvas_texture_storage.h b/servers/rendering/storage/canvas_texture_storage.h new file mode 100644 index 0000000000..ad4c67f649 --- /dev/null +++ b/servers/rendering/storage/canvas_texture_storage.h @@ -0,0 +1,51 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_H +#define CANVAS_TEXTURE_STORAGE_H + +#include "servers/rendering_server.h" + +class RendererCanvasTextureStorage { +public: + virtual ~RendererCanvasTextureStorage(){}; + + virtual RID canvas_texture_allocate() = 0; + virtual void canvas_texture_initialize(RID p_rid) = 0; + virtual void canvas_texture_free(RID p_rid) = 0; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0; +}; + +#endif // !CANVAS_TEXTURE_STORAGE_H diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h new file mode 100644 index 0000000000..bef5e3e146 --- /dev/null +++ b/servers/rendering/storage/texture_storage.h @@ -0,0 +1,80 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_H +#define TEXTURE_STORAGE_H + +#include "servers/rendering_server.h" + +class RendererTextureStorage { +public: + virtual bool can_create_resources_async() const = 0; + + virtual ~RendererTextureStorage(){}; + + virtual RID texture_allocate() = 0; + virtual void texture_free(RID p_rid) = 0; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; + virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) = 0; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0; + virtual void texture_3d_placeholder_initialize(RID p_texture) = 0; + + virtual Ref<Image> texture_2d_get(RID p_texture) const = 0; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0; + + virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; + + 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_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; + + virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; +}; + +#endif // !TEXTURE_STORAGE_H |