summaryrefslogtreecommitdiff
path: root/servers/visual/rasterizer/rasterizer_storage_rd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual/rasterizer/rasterizer_storage_rd.cpp')
-rw-r--r--servers/visual/rasterizer/rasterizer_storage_rd.cpp229
1 files changed, 172 insertions, 57 deletions
diff --git a/servers/visual/rasterizer/rasterizer_storage_rd.cpp b/servers/visual/rasterizer/rasterizer_storage_rd.cpp
index e120b86ba3..d38d0c62c8 100644
--- a/servers/visual/rasterizer/rasterizer_storage_rd.cpp
+++ b/servers/visual/rasterizer/rasterizer_storage_rd.cpp
@@ -486,6 +486,7 @@ RID RasterizerStorageRD::texture_2d_create(const Ref<Image> &p_image) {
texture.layers = 1;
texture.mipmaps = p_image->get_mipmap_count() + 1;
texture.depth = 1;
+ texture.format = p_image->get_format();
texture.rd_type = RD::TEXTURE_TYPE_2D;
texture.rd_format = ret_format.format;
@@ -532,6 +533,8 @@ RID RasterizerStorageRD::texture_2d_create(const Ref<Image> &p_image) {
texture.width_2d = texture.width;
texture.height_2d = texture.height;
texture.is_render_target = false;
+ texture.rd_view = rd_view;
+ texture.is_proxy = false;
#warning TODO this is temporary to get things to work
texture.image_cache_2d = p_image;
@@ -549,6 +552,28 @@ RID RasterizerStorageRD::texture_3d_create(const Vector<Ref<Image> > &p_slices)
return RID();
}
+RID RasterizerStorageRD::texture_proxy_create(RID p_base) {
+ Texture *tex = texture_owner.getornull(p_base);
+ ERR_FAIL_COND_V(!tex, RID());
+ 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();
+
+ RID rid = texture_owner.make_rid(proxy_tex);
+
+ tex->proxies.push_back(rid);
+ return rid;
+}
+
void RasterizerStorageRD::_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->empty());
@@ -581,6 +606,46 @@ void RasterizerStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_i
void RasterizerStorageRD::texture_3d_update(RID p_texture, const Ref<Image> &p_image, int p_depth, int p_mipmap) {
}
+void RasterizerStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) {
+
+ Texture *tex = texture_owner.getornull(p_texture);
+ ERR_FAIL_COND(!tex);
+ ERR_FAIL_COND(!tex->is_proxy);
+ Texture *proxy_to = texture_owner.getornull(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.getornull(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.
RID RasterizerStorageRD::texture_2d_placeholder_create() {
@@ -629,20 +694,34 @@ void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) {
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
+ ERR_FAIL_COND(tex->proxy_to.is_valid()); //cant replace proxy
Texture *by_tex = texture_owner.getornull(p_by_texture);
ERR_FAIL_COND(!by_tex);
+ ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //cant replace proxy
if (tex == by_tex) {
return;
}
- RD::get_singleton()->free(tex->rd_texture);
if (tex->rd_texture_srgb.is_valid()) {
RD::get_singleton()->free(tex->rd_texture_srgb);
}
+ RD::get_singleton()->free(tex->rd_texture);
+
+ 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
+
+ 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);
}
void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) {
@@ -650,7 +729,7 @@ void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width,
ERR_FAIL_COND(!tex);
ERR_FAIL_COND(tex->type != Texture::TYPE_2D);
tex->width_2d = p_width;
- tex->height_2d = p_width;
+ tex->height_2d = p_height;
}
void RasterizerStorageRD::texture_set_path(RID p_texture, const String &p_path) {
@@ -673,8 +752,8 @@ void RasterizerStorageRD::texture_set_proxy(RID p_proxy, RID p_base) {
void RasterizerStorageRD::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
}
-Size2 RasterizerStorageRD::texture_size_with_proxy(RID p_proxy) const {
- return Size2();
+Size2 RasterizerStorageRD::texture_size_with_proxy(RID p_proxy) {
+ return texture_2d_get_size(p_proxy);
}
/* RENDER TARGET API */
@@ -685,9 +764,6 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
if (rt->framebuffer.is_valid()) {
RD::get_singleton()->free(rt->framebuffer);
}
- if (rt->color_srgb.is_valid()) {
- RD::get_singleton()->free(rt->color_srgb);
- }
if (rt->color.is_valid()) {
RD::get_singleton()->free(rt->color);
@@ -695,14 +771,19 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
rt->framebuffer = RID();
rt->color = RID();
- rt->color_srgb = RID();
rt->dirty = true;
- rt->texture_dirty = true;
}
void RasterizerStorageRD::_update_render_target(RenderTarget *rt) {
+ if (rt->texture.is_null()) {
+ //create a placeholder until updated
+ rt->texture = texture_2d_placeholder_create();
+ Texture *tex = texture_owner.getornull(rt->texture);
+ tex->is_render_target = true;
+ }
+
_clear_render_target(rt);
if (rt->size.width == 0 || rt->size.height == 0) {
@@ -732,14 +813,6 @@ void RasterizerStorageRD::_update_render_target(RenderTarget *rt) {
rt->color = RD::get_singleton()->texture_create(rd_format, rd_view);
ERR_FAIL_COND(rt->color.is_null());
- if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
- rd_view.format_override = rt->color_format_srgb;
- rt->color_srgb = RD::get_singleton()->texture_create_shared(rd_view, rt->color);
- if (rt->color_srgb.is_null()) {
- _clear_render_target(rt);
- ERR_FAIL_COND(rt->color_srgb.is_null());
- }
- }
Vector<RID> fb_textures;
fb_textures.push_back(rt->color);
@@ -749,14 +822,55 @@ void RasterizerStorageRD::_update_render_target(RenderTarget *rt) {
ERR_FAIL_COND(rt->framebuffer.is_null());
}
+ { //update texture
+
+ Texture *tex = texture_owner.getornull(rt->texture);
+
+ //free existing textures
+ if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
+ RD::get_singleton()->free(tex->rd_texture);
+ }
+ if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
+ RD::get_singleton()->free(tex->rd_texture_srgb);
+ }
+
+ tex->rd_texture = RID();
+ tex->rd_texture_srgb = RID();
+
+ //create shared textures to the color buffer,
+ //so transparent can be supported
+ RD::TextureView view;
+ view.format_override = rt->color_format;
+ if (!rt->flags[RENDER_TARGET_TRANSPARENT]) {
+ view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ }
+ tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color);
+ if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
+ view.format_override = rt->color_format_srgb;
+ tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color);
+ }
+ tex->rd_view = view;
+ tex->width = rt->size.width;
+ tex->height = rt->size.height;
+ tex->width_2d = rt->size.width;
+ tex->height_2d = rt->size.height;
+ tex->rd_format = rt->color_format;
+ tex->rd_format_srgb = rt->color_format_srgb;
+ tex->format = rt->image_format;
+
+ 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);
+ }
+ }
rt->dirty = false;
}
RID RasterizerStorageRD::render_target_create() {
RenderTarget render_target;
render_target.dirty = true;
- render_target.texture_dirty = true;
render_target.was_used = false;
+ render_target.clear_requested = false;
for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
render_target.flags[i] = false;
@@ -774,48 +888,14 @@ void RasterizerStorageRD::render_target_set_size(RID p_render_target, int p_widt
rt->size.x = p_width;
rt->size.y = p_height;
rt->dirty = true;
- rt->texture_dirty = true;
}
RID RasterizerStorageRD::render_target_get_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
- if (rt->texture_dirty) {
- if (rt->dirty) {
- _update_render_target(rt);
- }
-
- if (rt->texture.is_null()) {
- //kinda hacky, but not terrible
- rt->texture = texture_2d_placeholder_create();
- }
-
- Texture *tex = texture_owner.getornull(rt->texture);
-
- if (!tex->is_render_target) {
- //first allocation, fix it up
- RD::get_singleton()->free(tex->rd_texture);
- if (tex->rd_texture_srgb.is_null()) {
- RD::get_singleton()->free(tex->rd_texture_srgb);
- }
- tex->is_render_target = true;
- }
-
- if (!rt->color.is_null()) {
- //there is a color buffer, update to it
- tex->rd_texture = rt->color;
- tex->rd_texture_srgb = rt->color_srgb;
- tex->width = rt->size.width;
- tex->height = rt->size.height;
- tex->width_2d = rt->size.width;
- tex->height_2d = rt->size.height;
- tex->rd_format = rt->color_format;
- tex->rd_format_srgb = rt->color_format_srgb;
- tex->format = rt->image_format;
- }
-
- rt->texture_dirty = false;
+ if (rt->dirty) {
+ _update_render_target(rt);
}
return rt->texture;
@@ -829,7 +909,6 @@ void RasterizerStorageRD::render_target_set_flag(RID p_render_target, RenderTarg
ERR_FAIL_COND(!rt);
rt->flags[p_flag] = p_value;
rt->dirty = true;
- rt->texture_dirty = true;
}
bool RasterizerStorageRD::render_target_was_used(RID p_render_target) {
@@ -839,7 +918,7 @@ bool RasterizerStorageRD::render_target_was_used(RID p_render_target) {
return rt->was_used;
}
-void RasterizerStorageRD::render_target_clear_used_flag(RID p_render_target) {
+void RasterizerStorageRD::render_target_set_as_unused(RID p_render_target) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
@@ -864,6 +943,33 @@ RID RasterizerStorageRD::render_target_get_rd_framebuffer(RID p_render_target) {
return rt->framebuffer;
}
+void RasterizerStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->clear_requested = true;
+ rt->clear_color = p_clear_color;
+}
+
+bool RasterizerStorageRD::render_target_is_clear_requested(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+ return rt->clear_requested;
+}
+
+Color RasterizerStorageRD::render_target_get_clear_request_color(RID p_render_target) {
+
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND_V(!rt, Color());
+ return rt->clear_color;
+}
+
+void RasterizerStorageRD::render_target_disable_clear_request(RID p_render_target) {
+
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->clear_requested = false;
+}
+
bool RasterizerStorageRD::free(RID p_rid) {
if (texture_owner.owns(p_rid)) {
@@ -871,10 +977,19 @@ bool RasterizerStorageRD::free(RID p_rid) {
ERR_FAIL_COND_V(t->is_render_target, false);
- RD::get_singleton()->free(t->rd_texture);
if (t->rd_texture_srgb.is_valid()) {
+ //erase this first, as it's a dependency of the one below
RD::get_singleton()->free(t->rd_texture_srgb);
}
+ RD::get_singleton()->free(t->rd_texture);
+
+ for (int i = 0; i < t->proxies.size(); i++) {
+ Texture *p = texture_owner.getornull(t->proxies[i]);
+ ERR_CONTINUE(!p);
+ p->proxy_to = RID();
+ p->rd_texture = RID();
+ p->rd_texture_srgb = RID();
+ }
texture_owner.free(p_rid);
} else if (render_target_owner.owns(p_rid)) {