summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastiaan Olij <mux213@gmail.com>2022-03-12 22:19:59 +1100
committerBastiaan Olij <mux213@gmail.com>2022-03-16 17:43:10 +1100
commit57e5a33623130ead5aeb5369c7a40410a1afc79b (patch)
tree8fce4bd039eb7dea19bc334e4cc0feb158a6a6ef
parentcfd21adf64087c750dde89191bcfcf4d166adc85 (diff)
Split dummy renderer classes into separate files
Split canvas_texture_storage and texture_storage from render_storage class
-rw-r--r--drivers/gles3/SCsub1
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp38
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h6
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp18
-rw-r--r--drivers/gles3/rasterizer_gles3.h9
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp1478
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h476
-rw-r--r--drivers/gles3/storage/SCsub5
-rw-r--r--drivers/gles3/storage/canvas_texture_storage.cpp96
-rw-r--r--drivers/gles3/storage/canvas_texture_storage.h87
-rw-r--r--drivers/gles3/storage/config.cpp156
-rw-r--r--drivers/gles3/storage/config.h113
-rw-r--r--drivers/gles3/storage/render_target_storage.h132
-rw-r--r--drivers/gles3/storage/texture_storage.cpp1211
-rw-r--r--drivers/gles3/storage/texture_storage.h389
-rw-r--r--platform/javascript/display_server_javascript.cpp2
-rw-r--r--scene/resources/texture.cpp2
-rw-r--r--servers/display_server_headless.h2
-rw-r--r--servers/rendering/SCsub1
-rw-r--r--servers/rendering/dummy/rasterizer_canvas_dummy.h63
-rw-r--r--servers/rendering/dummy/rasterizer_dummy.h99
-rw-r--r--servers/rendering/dummy/rasterizer_scene_dummy.h217
-rw-r--r--servers/rendering/dummy/rasterizer_storage_dummy.h (renamed from servers/rendering/rasterizer_dummy.h)350
-rw-r--r--servers/rendering/dummy/storage/canvas_texture_storage.h53
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h116
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp13
-rw-r--r--servers/rendering/renderer_compositor.h4
-rw-r--r--servers/rendering/renderer_rd/SCsub1
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp48
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp18
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp12
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp14
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp45
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h1
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp35
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp22
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp1606
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h218
-rw-r--r--servers/rendering/renderer_rd/storage_rd/SCsub5
-rw-r--r--servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp235
-rw-r--r--servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h90
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp1420
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h230
-rw-r--r--servers/rendering/renderer_storage.h56
-rw-r--r--servers/rendering/renderer_viewport.cpp2
-rw-r--r--servers/rendering/rendering_server_default.cpp2
-rw-r--r--servers/rendering/rendering_server_default.h90
-rw-r--r--servers/rendering/rendering_server_globals.cpp2
-rw-r--r--servers/rendering/rendering_server_globals.h4
-rw-r--r--servers/rendering/storage/SCsub5
-rw-r--r--servers/rendering/storage/canvas_texture_storage.h51
-rw-r--r--servers/rendering/storage/texture_storage.h80
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