From bf326793ba564f02af8f8836431818eb68b5eeb2 Mon Sep 17 00:00:00 2001 From: DDarby-Lewis <37579938+DDarby-Lewis@users.noreply.github.com> Date: Mon, 23 Feb 2026 21:50:18 +0000 Subject: [PATCH] Editor additions for MipMaps and rd_textures --- doc/classes/DrawableTexture2D.xml | 34 +++++++ doc/classes/ImageTexture.xml | 6 -- doc/classes/PortableCompressedTexture2D.xml | 6 -- doc/classes/Texture2D.xml | 42 +++++++++ .../scene/texture/texture_editor_plugin.cpp | 90 ++++++++++++++----- editor/scene/texture/texture_editor_plugin.h | 6 +- .../4.6-stable/GH-109004.txt | 6 ++ scene/resources/compressed_texture.h | 2 +- scene/resources/drawable_texture_2d.cpp | 25 +++++- scene/resources/drawable_texture_2d.h | 5 +- scene/resources/image_texture.cpp | 1 - scene/resources/image_texture.h | 2 +- .../resources/portable_compressed_texture.cpp | 1 - scene/resources/portable_compressed_texture.h | 2 +- scene/resources/texture.cpp | 31 +++++++ scene/resources/texture.h | 9 +- .../storage_rd/texture_storage.cpp | 14 ++- servers/rendering/rendering_device.cpp | 8 ++ servers/rendering/rendering_device.h | 1 + 19 files changed, 244 insertions(+), 47 deletions(-) create mode 100644 misc/extension_api_validation/4.6-stable/GH-109004.txt diff --git a/doc/classes/DrawableTexture2D.xml b/doc/classes/DrawableTexture2D.xml index 638410a995..c07a294c9d 100644 --- a/doc/classes/DrawableTexture2D.xml +++ b/doc/classes/DrawableTexture2D.xml @@ -38,6 +38,40 @@ Re-calculates the mipmaps for this texture on demand. + + + + Returns [code]true[/code] if mipmaps are set to be used on this DrawableTexture. + + + + + + + Sets the format of this DrawableTexture. + + + + + + + Sets the height of this DrawableTexture. + + + + + + + Sets if mipmaps should be used on this DrawableTexture. + + + + + + + Sets the width of this DrawableTexture. + + diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml index e1ab84584b..9d55049497 100644 --- a/doc/classes/ImageTexture.xml +++ b/doc/classes/ImageTexture.xml @@ -36,12 +36,6 @@ Creates a new [ImageTexture] and initializes it by allocating and setting the data from an [Image]. - - - - Returns the format of the texture. - - diff --git a/doc/classes/PortableCompressedTexture2D.xml b/doc/classes/PortableCompressedTexture2D.xml index 37445bf4d9..db768ad520 100644 --- a/doc/classes/PortableCompressedTexture2D.xml +++ b/doc/classes/PortableCompressedTexture2D.xml @@ -31,12 +31,6 @@ Return the compression mode used (valid after initialized). - - - - Return the image format used (valid after initialized). - - diff --git a/doc/classes/Texture2D.xml b/doc/classes/Texture2D.xml index d8b32f2c1b..fe604939f9 100644 --- a/doc/classes/Texture2D.xml +++ b/doc/classes/Texture2D.xml @@ -48,12 +48,30 @@ [b]Note:[/b] This is only used in 2D rendering, not 3D. + + + + Called when [method get_format] is called. + + Called when the [Texture2D]'s height is queried. + + + + Called when [method get_image] is called. + + + + + + Called when [method get_mipmap_count] is called. + + @@ -66,6 +84,12 @@ Called when the presence of an alpha channel in the [Texture2D] is queried. + + + + Called when [method has_mipmaps] is called. + + @@ -113,6 +137,12 @@ Draws a part of the texture using a [CanvasItem] with the [RenderingServer] API. + + + + Returns the image format of the texture. + + @@ -127,6 +157,12 @@ [b]Note:[/b] This will fetch the texture data from the GPU, which might cause performance problems when overused. Avoid calling [method get_image] every frame, especially on large textures. + + + + Returns the number of mipmaps of the texture. + + @@ -145,5 +181,11 @@ Returns [code]true[/code] if this [Texture2D] has an alpha channel. + + + + Returns [code]true[/code] if the texture has mipmaps. + + diff --git a/editor/scene/texture/texture_editor_plugin.cpp b/editor/scene/texture/texture_editor_plugin.cpp index d8f96942ed..c64a4d3b84 100644 --- a/editor/scene/texture/texture_editor_plugin.cpp +++ b/editor/scene/texture/texture_editor_plugin.cpp @@ -36,20 +36,26 @@ #include "scene/gui/aspect_ratio_container.h" #include "scene/gui/color_rect.h" #include "scene/gui/label.h" +#include "scene/gui/spin_box.h" #include "scene/gui/texture_rect.h" #include "scene/resources/animated_texture.h" #include "scene/resources/atlas_texture.h" #include "scene/resources/compressed_texture.h" #include "scene/resources/dpi_texture.h" +#include "scene/resources/gradient_texture.h" #include "scene/resources/image_texture.h" #include "scene/resources/material.h" #include "scene/resources/portable_compressed_texture.h" +#include "scene/resources/style_box_flat.h" +#include "scene/resources/texture_rd.h" +#include "servers/rendering/rendering_device.h" constexpr const char *texture_2d_shader_code = R"( shader_type canvas_item; render_mode blend_mix; instance uniform vec4 u_channel_factors = vec4(1.0); +instance uniform float lod = 0.0; vec4 filter_preview_colors(vec4 input_color, vec4 factors) { // Filter RGB. @@ -70,7 +76,7 @@ vec4 filter_preview_colors(vec4 input_color, vec4 factors) { } void fragment() { - COLOR = filter_preview_colors(texture(TEXTURE, UV), u_channel_factors); + COLOR = filter_preview_colors(textureLod(TEXTURE, UV, lod), u_channel_factors); } )"; @@ -128,25 +134,12 @@ void TexturePreview::_update_texture_display_ratio() { } static Image::Format get_texture_2d_format(const Ref &p_texture) { - const Ref image_texture = p_texture; - if (image_texture.is_valid()) { - return image_texture->get_format(); + const Ref rd_texture = p_texture; + if (rd_texture.is_valid() && RD::get_singleton() && RD::get_singleton()->texture_is_valid(rd_texture->get_texture_rd_rid())) { + return rd_texture->get_image()->get_format(); } - const Ref compressed_texture = p_texture; - if (compressed_texture.is_valid()) { - return compressed_texture->get_format(); - } - - const Ref portable_compressed_texture = p_texture; - if (portable_compressed_texture.is_valid()) { - return portable_compressed_texture->get_format(); - } - - // AtlasTexture? - - // Unknown - return Image::FORMAT_MAX; + return p_texture->get_format(); } static int get_texture_mipmaps_count(const Ref &p_texture) { @@ -155,6 +148,8 @@ static int get_texture_mipmaps_count(const Ref &p_texture) { // We are having to download the image only to get its mipmaps count. It would be nice if we didn't have to. Ref image; Ref at = p_texture; + Ref rd_texture = p_texture; + if (at.is_valid()) { // The AtlasTexture tries to obtain the region from the atlas as an image, // which will fail if it is a compressed format. @@ -162,6 +157,11 @@ static int get_texture_mipmaps_count(const Ref &p_texture) { if (atlas.is_valid()) { image = atlas->get_image(); } + } else if (rd_texture.is_valid()) { + if (RD::get_singleton() && RD::get_singleton()->texture_is_valid(rd_texture->get_texture_rd_rid())) { + return -1; + } + image = p_texture->get_image(); } else { image = p_texture->get_image(); } @@ -176,12 +176,21 @@ void TexturePreview::_update_metadata_label_text() { const Ref texture = texture_display->get_texture(); ERR_FAIL_COND(texture.is_null()); - const Image::Format format = get_texture_2d_format(texture.ptr()); + Image::Format format; + int mipmaps; + + Ref image = texture->get_image(); + if (image.is_valid()) { + format = image->get_format(); + mipmaps = image->get_mipmap_count(); + } else { + format = get_texture_2d_format(texture.ptr()); + mipmaps = get_texture_mipmaps_count(texture); + } const String format_name = format != Image::FORMAT_MAX ? Image::get_format_name(format) : texture->get_class(); const Vector2i resolution = texture->get_size(); - const int mipmaps = get_texture_mipmaps_count(texture); if (format != Image::FORMAT_MAX) { // Avoid signed integer overflow that could occur with huge texture sizes by casting everything to uint64_t. @@ -230,6 +239,10 @@ void TexturePreview::on_selected_channels_changed() { texture_display->set_instance_shader_parameter("u_channel_factors", channel_selector->get_selected_channel_factors()); } +void TexturePreview::on_selected_mipmap_changed(double p_value) { + texture_display->set_instance_shader_parameter("lod", mipmap_spinbox->get_value()); +} + TexturePreview::TexturePreview(Ref p_texture, bool p_show_metadata) { set_custom_minimum_size(Size2(0.0, 256.0) * EDSCALE); @@ -277,6 +290,21 @@ TexturePreview::TexturePreview(Ref p_texture, bool p_show_metadata) { const Image::Format format = p_texture.is_valid() ? get_texture_2d_format(p_texture.ptr()) : Image::FORMAT_MAX; const uint32_t components_mask = format != Image::FORMAT_MAX ? Image::get_format_component_mask(format) : 0xf; + // Setup Mipmap selector. + const int mipmaps = get_texture_mipmaps_count(p_texture); + if (mipmaps > 0) { + mipmap_spinbox = memnew(SpinBox); + mipmap_spinbox->set_tooltip_text(TTRC("Mipmap level index selector.")); + mipmap_spinbox->set_max(mipmaps); + mipmap_spinbox->set_modulate(Color(1, 1, 1, 0.8)); + mipmap_spinbox->set_h_grow_direction(GROW_DIRECTION_BEGIN); + mipmap_spinbox->set_h_size_flags(Control::SIZE_SHRINK_END); + mipmap_spinbox->set_v_size_flags(Control::SIZE_SHRINK_BEGIN); + mipmap_spinbox->set_anchors_preset(Control::PRESET_TOP_RIGHT); + mipmap_spinbox->connect(SceneStringName(value_changed), callable_mp(this, &TexturePreview::on_selected_mipmap_changed)); + add_child(mipmap_spinbox); + } + // Add color channel selector at the bottom left if more than 1 channel is available. if (p_show_metadata && !Math::is_power_of_2(components_mask)) { channel_selector = memnew(ColorChannelSelector); @@ -312,7 +340,27 @@ TexturePreview::TexturePreview(Ref p_texture, bool p_show_metadata) { } bool EditorInspectorPluginTexture::can_handle(Object *p_object) { - return Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr; + if (Object::cast_to(p_object) || Object::cast_to(p_object)) { + return false; + } + + if (Object::cast_to(p_object) != nullptr || + Object::cast_to(p_object) != nullptr || + Object::cast_to(p_object) != nullptr || + Object::cast_to(p_object) != nullptr || + Object::cast_to(p_object) != nullptr || + Object::cast_to(p_object) != nullptr || + Object::cast_to(p_object) != nullptr || + Object::cast_to(p_object) != nullptr) { + return true; + } + + Ref texture_2d(Object::cast_to(p_object)); + if (texture_2d.is_valid()) { + this_image = texture_2d->get_image(); + return this_image.is_valid(); + } + return false; } void EditorInspectorPluginTexture::parse_begin(Object *p_object) { diff --git a/editor/scene/texture/texture_editor_plugin.h b/editor/scene/texture/texture_editor_plugin.h index d66aa46a70..c9f0cdc48d 100644 --- a/editor/scene/texture/texture_editor_plugin.h +++ b/editor/scene/texture/texture_editor_plugin.h @@ -40,6 +40,7 @@ class ColorRect; class TextureRect; class ShaderMaterial; class ColorChannelSelector; +class SpinBox; class TexturePreview : public MarginContainer { GDCLASS(TexturePreview, MarginContainer); @@ -61,6 +62,7 @@ private: static inline Ref texture_material; ColorChannelSelector *channel_selector = nullptr; + SpinBox *mipmap_spinbox = nullptr; void _draw_outline(); void _update_metadata_label_text(); @@ -68,8 +70,8 @@ private: protected: void _notification(int p_what); void _update_texture_display_ratio(); - void on_selected_channels_changed(); + void on_selected_mipmap_changed(double p_value); public: static void init_shaders(); @@ -82,6 +84,8 @@ public: class EditorInspectorPluginTexture : public EditorInspectorPlugin { GDCLASS(EditorInspectorPluginTexture, EditorInspectorPlugin); + Ref this_image; + public: virtual bool can_handle(Object *p_object) override; virtual void parse_begin(Object *p_object) override; diff --git a/misc/extension_api_validation/4.6-stable/GH-109004.txt b/misc/extension_api_validation/4.6-stable/GH-109004.txt new file mode 100644 index 0000000000..ef6853d08d --- /dev/null +++ b/misc/extension_api_validation/4.6-stable/GH-109004.txt @@ -0,0 +1,6 @@ +GH-109004 +--------- +Validate extension JSON: API was removed: classes/ImageTexture/methods/get_format +Validate extension JSON: API was removed: classes/PortableCompressedTexture2D/methods/get_format + +The above are now members of the base class Texture2D. diff --git a/scene/resources/compressed_texture.h b/scene/resources/compressed_texture.h index 3282096835..35f3677dcb 100644 --- a/scene/resources/compressed_texture.h +++ b/scene/resources/compressed_texture.h @@ -88,7 +88,7 @@ public: static TextureFormatRoughnessRequestCallback request_roughness_callback; static TextureFormatRequestCallback request_normal_callback; - Image::Format get_format() const; + virtual Image::Format get_format() const override; Error load(const String &p_path); String get_load_path() const; diff --git a/scene/resources/drawable_texture_2d.cpp b/scene/resources/drawable_texture_2d.cpp index 64dc034d84..28fd3166e4 100644 --- a/scene/resources/drawable_texture_2d.cpp +++ b/scene/resources/drawable_texture_2d.cpp @@ -96,7 +96,7 @@ int DrawableTexture2D::get_height() const { return height; } -void DrawableTexture2D::set_format(DrawableFormat p_format) { +void DrawableTexture2D::set_drawable_format(DrawableFormat p_format) { if (format == p_format) { return; } @@ -105,10 +105,25 @@ void DrawableTexture2D::set_format(DrawableFormat p_format) { emit_changed(); } -DrawableTexture2D::DrawableFormat DrawableTexture2D::get_format() const { +DrawableTexture2D::DrawableFormat DrawableTexture2D::get_drawable_format() const { return format; } +Image::Format DrawableTexture2D::get_format() const { + switch (format) { + case DRAWABLE_FORMAT_RGBA8: + return Image::FORMAT_RGBA8; + case DRAWABLE_FORMAT_RGBA8_SRGB: + return Image::FORMAT_RGBA8; + case DRAWABLE_FORMAT_RGBAH: + return Image::FORMAT_RGBAH; + case DRAWABLE_FORMAT_RGBAF: + return Image::FORMAT_RGBAF; + default: + return Image::FORMAT_RGBA8; + } +} + void DrawableTexture2D::set_use_mipmaps(bool p_mipmaps) { if (mipmaps == p_mipmaps) { return; @@ -232,6 +247,12 @@ void DrawableTexture2D::generate_mipmaps() { } void DrawableTexture2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_width", "width"), &DrawableTexture2D::set_width); + ClassDB::bind_method(D_METHOD("set_height", "height"), &DrawableTexture2D::set_height); + ClassDB::bind_method(D_METHOD("set_format", "format"), &DrawableTexture2D::set_drawable_format); + ClassDB::bind_method(D_METHOD("set_use_mipmaps", "mipmaps"), &DrawableTexture2D::set_use_mipmaps); + ClassDB::bind_method(D_METHOD("get_use_mipmaps"), &DrawableTexture2D::get_use_mipmaps); + ClassDB::bind_method(D_METHOD("setup", "width", "height", "format", "color", "use_mipmaps"), &DrawableTexture2D::setup, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("blit_rect", "rect", "source", "modulate", "mipmap", "material"), &DrawableTexture2D::blit_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0), DEFVAL(Ref())); ClassDB::bind_method(D_METHOD("blit_rect_multi", "rect", "sources", "extra_targets", "modulate", "mipmap", "material"), &DrawableTexture2D::blit_rect_multi, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0), DEFVAL(Ref())); diff --git a/scene/resources/drawable_texture_2d.h b/scene/resources/drawable_texture_2d.h index 38616f703c..c699892075 100644 --- a/scene/resources/drawable_texture_2d.h +++ b/scene/resources/drawable_texture_2d.h @@ -68,11 +68,12 @@ public: void set_height(int p_height); int get_height() const override; - void set_format(DrawableFormat p_format); - DrawableFormat get_format() const; + void set_drawable_format(DrawableFormat p_format); + DrawableFormat get_drawable_format() const; void set_use_mipmaps(bool p_mipmaps); bool get_use_mipmaps() const; + virtual Image::Format get_format() const override; virtual RID get_rid() const override; virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const override; diff --git a/scene/resources/image_texture.cpp b/scene/resources/image_texture.cpp index 198c15ce16..7f38a38955 100644 --- a/scene/resources/image_texture.cpp +++ b/scene/resources/image_texture.cpp @@ -229,7 +229,6 @@ void ImageTexture::set_path(const String &p_path, bool p_take_over) { void ImageTexture::_bind_methods() { ClassDB::bind_static_method("ImageTexture", D_METHOD("create_from_image", "image"), &ImageTexture::create_from_image); - ClassDB::bind_method(D_METHOD("get_format"), &ImageTexture::get_format); ClassDB::bind_method(D_METHOD("set_image", "image"), &ImageTexture::set_image); ClassDB::bind_method(D_METHOD("update", "image"), &ImageTexture::update); diff --git a/scene/resources/image_texture.h b/scene/resources/image_texture.h index 527d78ce8e..311f7182cf 100644 --- a/scene/resources/image_texture.h +++ b/scene/resources/image_texture.h @@ -55,7 +55,7 @@ public: void set_image(const Ref &p_image); static Ref create_from_image(const Ref &p_image); - Image::Format get_format() const; + virtual Image::Format get_format() const override; void update(const Ref &p_image); Ref get_image() const override; diff --git a/scene/resources/portable_compressed_texture.cpp b/scene/resources/portable_compressed_texture.cpp index bdc27b5337..04eee9a079 100644 --- a/scene/resources/portable_compressed_texture.cpp +++ b/scene/resources/portable_compressed_texture.cpp @@ -369,7 +369,6 @@ void PortableCompressedTexture2D::set_basisu_compressor_params(int p_uastc_level void PortableCompressedTexture2D::_bind_methods() { ClassDB::bind_method(D_METHOD("create_from_image", "image", "compression_mode", "normal_map", "lossy_quality"), &PortableCompressedTexture2D::create_from_image, DEFVAL(false), DEFVAL(0.8)); - ClassDB::bind_method(D_METHOD("get_format"), &PortableCompressedTexture2D::get_format); ClassDB::bind_method(D_METHOD("get_compression_mode"), &PortableCompressedTexture2D::get_compression_mode); ClassDB::bind_method(D_METHOD("set_size_override", "size"), &PortableCompressedTexture2D::set_size_override); diff --git a/scene/resources/portable_compressed_texture.h b/scene/resources/portable_compressed_texture.h index af4e192b8c..9f1d5c0871 100644 --- a/scene/resources/portable_compressed_texture.h +++ b/scene/resources/portable_compressed_texture.h @@ -83,7 +83,7 @@ public: CompressionMode get_compression_mode() const; void create_from_image(const Ref &p_image, CompressionMode p_compression_mode, bool p_normal_map = false, float p_lossy_quality = 0.8); - Image::Format get_format() const; + virtual Image::Format get_format() const override; void update(const Ref &p_image); Ref get_image() const override; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 0b33a1607c..10ba6a4fc1 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -34,6 +34,30 @@ #include "scene/resources/placeholder_textures.h" #include "servers/rendering/rendering_server.h" +Ref Texture2D::get_image() const { + Ref ret; + GDVIRTUAL_CALL(_get_image, ret); + return ret; +} + +Image::Format Texture2D::get_format() const { + Image::Format ret = Image::FORMAT_MAX; + GDVIRTUAL_CALL(_get_format, ret); + return ret; +} + +int Texture2D::get_mipmap_count() const { + int ret = 0; + GDVIRTUAL_CALL(_get_mipmap_count, ret); + return ret; +} + +bool Texture2D::has_mipmaps() const { + bool ret = false; + GDVIRTUAL_CALL(_has_mipmaps, ret); + return ret; +} + int Texture2D::get_width() const { int ret = 0; GDVIRTUAL_CALL(_get_width, ret); @@ -97,10 +121,13 @@ Ref Texture2D::create_placeholder() const { } void Texture2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_format"), &Texture2D::get_format); + ClassDB::bind_method(D_METHOD("get_mipmap_count"), &Texture2D::get_mipmap_count); ClassDB::bind_method(D_METHOD("get_width"), &Texture2D::get_width); ClassDB::bind_method(D_METHOD("get_height"), &Texture2D::get_height); ClassDB::bind_method(D_METHOD("get_size"), &Texture2D::get_size); ClassDB::bind_method(D_METHOD("has_alpha"), &Texture2D::has_alpha); + ClassDB::bind_method(D_METHOD("has_mipmaps"), &Texture2D::has_mipmaps); ClassDB::bind_method(D_METHOD("draw", "canvas_item", "position", "modulate", "transpose"), &Texture2D::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose"), &Texture2D::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &Texture2D::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true)); @@ -109,10 +136,14 @@ void Texture2D::_bind_methods() { ADD_GROUP("", ""); + GDVIRTUAL_BIND(_get_image); + GDVIRTUAL_BIND(_get_format); + GDVIRTUAL_BIND(_get_mipmap_count); GDVIRTUAL_BIND(_get_width); GDVIRTUAL_BIND(_get_height); GDVIRTUAL_BIND(_is_pixel_opaque, "x", "y"); GDVIRTUAL_BIND(_has_alpha); + GDVIRTUAL_BIND(_has_mipmaps); GDVIRTUAL_BIND(_draw, "to_canvas_item", "pos", "modulate", "transpose") GDVIRTUAL_BIND(_draw_rect, "to_canvas_item", "rect", "tile", "modulate", "transpose") diff --git a/scene/resources/texture.h b/scene/resources/texture.h index c648cd3ca4..f4bcea90cb 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -45,6 +45,10 @@ class Texture2D : public Texture { protected: static void _bind_methods(); + GDVIRTUAL0RC(Image::Format, _get_format) + GDVIRTUAL0RC(Ref, _get_image) + GDVIRTUAL0RC(int, _get_mipmap_count) + GDVIRTUAL0RC(bool, _has_mipmaps) GDVIRTUAL0RC_REQUIRED(int, _get_width) GDVIRTUAL0RC_REQUIRED(int, _get_height) GDVIRTUAL2RC(bool, _is_pixel_opaque, int, int) @@ -55,6 +59,8 @@ protected: GDVIRTUAL6C(_draw_rect_region, RID, Rect2, Rect2, Color, bool, bool) public: + virtual Image::Format get_format() const; + virtual int get_mipmap_count() const; virtual int get_width() const; virtual int get_height() const; virtual Size2 get_size() const; @@ -62,6 +68,7 @@ public: virtual bool is_pixel_opaque(int p_x, int p_y) const; virtual bool has_alpha() const; + virtual bool has_mipmaps() const; virtual RID get_scaled_rid() const { return get_rid(); } virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; @@ -69,7 +76,7 @@ public: virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; - virtual Ref get_image() const { return Ref(); } + virtual Ref get_image() const; virtual Ref create_placeholder() const; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index f53426419b..e0c9e88921 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -2154,14 +2154,22 @@ void TextureStorage::texture_rd_initialize(RID p_texture, const RID &p_rd_textur rd_view.swizzle_a = imfmt.swizzle_a; texture.rd_type = tf.texture_type; - texture.rd_view = rd_view; texture.rd_format = imfmt.rd_format; + texture.rd_format_srgb = imfmt.rd_format_srgb; + texture.rd_view = rd_view; + + if (imfmt.rd_format_srgb != RD::DATA_FORMAT_MAX) { + // Allow creating a shared sRGB texture even if users didn't explicitly add them. + RD::get_singleton()->_texture_ensure_shareable_format(p_rd_texture, texture.rd_format); + RD::get_singleton()->_texture_ensure_shareable_format(p_rd_texture, texture.rd_format_srgb); + } + // We create a shared texture here even if our view matches, so we don't obtain ownership. texture.rd_texture = RD::get_singleton()->texture_create_shared(rd_view, p_rd_texture); if (imfmt.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = imfmt.rd_format_srgb == tf.format ? RD::DATA_FORMAT_MAX : imfmt.rd_format; + // The texture supports sRGB override, create it for 3D usage. + rd_view.format_override = imfmt.rd_format_srgb == tf.format ? RD::DATA_FORMAT_MAX : imfmt.rd_format_srgb; texture.rd_format_srgb = imfmt.rd_format_srgb; - // We create a shared texture here even if our view matches, so we don't obtain ownership. texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, p_rd_texture); } diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 77fff88d86..ac624fc3fe 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -2204,6 +2204,14 @@ uint32_t RenderingDevice::_texture_vrs_method_to_usage_bits() const { } } +void RenderingDevice::_texture_ensure_shareable_format(RID p_texture, const DataFormat &p_shareable_format) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_NULL(texture); + if (!texture->allowed_shared_formats.has(p_shareable_format)) { + texture->allowed_shared_formats.push_back(p_shareable_format); + } +} + void RenderingDevice::_texture_check_pending_clear(RID p_texture_rid, Texture *p_texture) { DEV_ASSERT(p_texture != nullptr); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 39d68a9b01..9ec9803cb7 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -413,6 +413,7 @@ public: void _texture_clear_color(RID p_texture_rid, Texture *p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers); void _texture_clear_depth_stencil(RID p_texture_rid, Texture *p_texture, float p_depth, uint8_t p_stencil, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers); uint32_t _texture_vrs_method_to_usage_bits() const; + void _texture_ensure_shareable_format(RID p_texture, const DataFormat &p_shareable_format); struct TextureGetDataRequest { uint32_t frame_local_index = 0;