瀏覽代碼

Merge pull request #59862 from bruvzg/font_delay_texture_update

Delay font texture update, until `draw` is called. Rasterize glyphs during shaping.
Rémi Verschelde 3 年之前
父節點
當前提交
5d55846715

+ 50 - 45
modules/text_server_adv/text_server_adv.cpp

@@ -768,12 +768,6 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_
 	for (int i = 0; i < p_data->textures.size(); i++) {
 		const FontTexture &ct = p_data->textures[i];
 
-		if (RenderingServer::get_singleton() != nullptr) {
-			if (ct.texture->get_format() != p_image_format) {
-				continue;
-			}
-		}
-
 		if (mw > ct.texture_w || mh > ct.texture_h) { // Too big for this texture.
 			continue;
 		}
@@ -815,12 +809,6 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_
 		ret.y = 0;
 
 		int texsize = MAX(p_data->size.x * p_data->oversampling * 8, 256);
-		if (mw > texsize) {
-			texsize = mw; // Special case, adapt to it?
-		}
-		if (mh > texsize) {
-			texsize = mh; // Special case, adapt to it?
-		}
 
 #ifdef GDEXTENSION
 		texsize = Math::next_power_of_2(texsize);
@@ -832,6 +820,20 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_
 		} else {
 			texsize = MIN(texsize, 1024);
 		}
+		if (mw > texsize) { // Special case, adapt to it?
+#ifdef GDEXTENSION
+			texsize = Math::next_power_of_2(mw);
+#else
+			texsize = next_power_of_2(mw);
+#endif
+		}
+		if (mh > texsize) { // Special case, adapt to it?
+#ifdef GDEXTENSION
+			texsize = Math::next_power_of_2(mh);
+#else
+			texsize = next_power_of_2(mh);
+#endif
+		}
 
 		FontTexture tex;
 		tex.texture_w = texsize;
@@ -997,8 +999,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
 		int mw = w + p_rect_margin * 2;
 		int mh = h + p_rect_margin * 2;
 
-		ERR_FAIL_COND_V(mw > 1024, FontGlyph());
-		ERR_FAIL_COND_V(mh > 1024, FontGlyph());
+		ERR_FAIL_COND_V(mw > 4096, FontGlyph());
+		ERR_FAIL_COND_V(mh > 4096, FontGlyph());
 
 		FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh, true);
 		ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
@@ -1039,20 +1041,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
 			}
 		}
 
-		// Blit to image and texture.
-		{
-			if (RenderingServer::get_singleton() != nullptr) {
-				Ref<Image> img;
-				img.instantiate();
-				img->create_from_data(tex.texture_w, tex.texture_h, false, Image::FORMAT_RGBA8, tex.imgdata);
-				if (tex.texture.is_null()) {
-					tex.texture.instantiate();
-					tex.texture->create_from_image(img);
-				} else {
-					tex.texture->update(img);
-				}
-			}
-		}
+		tex.dirty = true;
 
 		// Update height array.
 		int32_t *offw = tex.offsets.ptrw();
@@ -1078,8 +1067,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
 	int mw = w + p_rect_margin * 2;
 	int mh = h + p_rect_margin * 2;
 
-	ERR_FAIL_COND_V(mw > 1024, FontGlyph());
-	ERR_FAIL_COND_V(mh > 1024, FontGlyph());
+	ERR_FAIL_COND_V(mw > 4096, FontGlyph());
+	ERR_FAIL_COND_V(mh > 4096, FontGlyph());
 
 	int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
 	Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
@@ -1124,21 +1113,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
 		}
 	}
 
-	// Blit to image and texture.
-	{
-		if (RenderingServer::get_singleton() != nullptr) {
-			Ref<Image> img;
-			img.instantiate();
-			img->create_from_data(tex.texture_w, tex.texture_h, false, require_format, tex.imgdata);
-
-			if (tex.texture.is_null()) {
-				tex.texture.instantiate();
-				tex.texture->create_from_image(img);
-			} else {
-				tex.texture->update(img);
-			}
-		}
-	}
+	tex.dirty = true;
 
 	// Update height array.
 	int32_t *offw = tex.offsets.ptrw();
@@ -2311,6 +2286,7 @@ void TextServerAdvanced::font_set_texture_image(const RID &p_font_rid, const Vec
 	tex.texture = Ref<ImageTexture>();
 	tex.texture.instantiate();
 	tex.texture->create_from_image(img);
+	tex.dirty = false;
 }
 
 Ref<Image> TextServerAdvanced::font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
@@ -2890,6 +2866,19 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can
 			}
 #endif
 			if (RenderingServer::get_singleton() != nullptr) {
+				if (fd->cache[size]->textures[gl.texture_idx].dirty) {
+					FontTexture &tex = fd->cache[size]->textures.write[gl.texture_idx];
+					Ref<Image> img;
+					img.instantiate();
+					img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+					if (tex.texture.is_null()) {
+						tex.texture.instantiate();
+						tex.texture->create_from_image(img);
+					} else {
+						tex.texture->update(img);
+					}
+					tex.dirty = false;
+				}
 				RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid();
 				if (fd->msdf) {
 					Point2 cpos = p_pos;
@@ -2953,6 +2942,19 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI
 			}
 #endif
 			if (RenderingServer::get_singleton() != nullptr) {
+				if (fd->cache[size]->textures[gl.texture_idx].dirty) {
+					FontTexture &tex = fd->cache[size]->textures.write[gl.texture_idx];
+					Ref<Image> img;
+					img.instantiate();
+					img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+					if (tex.texture.is_null()) {
+						tex.texture.instantiate();
+						tex.texture->create_from_image(img);
+					} else {
+						tex.texture->update(img);
+					}
+					tex.dirty = false;
+				}
 				RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid();
 				if (fd->msdf) {
 					Point2 cpos = p_pos;
@@ -4638,6 +4640,8 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
 	}
 
 	RID f = p_fonts[p_fb_index];
+	FontDataAdvanced *fd = font_owner.get_or_null(f);
+	Vector2i fss = _get_size(fd, fs);
 	hb_font_t *hb_font = _font_get_hb_handle(f, fs);
 	double scale = font_get_scale(f, fs);
 	double sp_sp = font_get_spacing(f, fs, SPACING_SPACE);
@@ -4719,6 +4723,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
 
 			gl.index = glyph_info[i].codepoint;
 			if (gl.index != 0) {
+				_ensure_glyph(fd, fss, gl.index);
 				if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
 					if (subpos) {
 						gl.advance = glyph_pos[i].x_advance / (64.0 / scale) + ea;

+ 1 - 0
modules/text_server_adv/text_server_adv.h

@@ -159,6 +159,7 @@ class TextServerAdvanced : public TextServerExtension {
 		int texture_h = 0;
 		PackedInt32Array offsets;
 		Ref<ImageTexture> texture;
+		bool dirty = true;
 	};
 
 	struct FontTexturePosition {

+ 47 - 45
modules/text_server_fb/text_server_fb.cpp

@@ -209,12 +209,6 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_
 	for (int i = 0; i < p_data->textures.size(); i++) {
 		const FontTexture &ct = p_data->textures[i];
 
-		if (RenderingServer::get_singleton() != nullptr) {
-			if (ct.texture->get_format() != p_image_format) {
-				continue;
-			}
-		}
-
 		if (mw > ct.texture_w || mh > ct.texture_h) { // Too big for this texture.
 			continue;
 		}
@@ -256,12 +250,6 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_
 		ret.y = 0;
 
 		int texsize = MAX(p_data->size.x * p_data->oversampling * 8, 256);
-		if (mw > texsize) {
-			texsize = mw; // Special case, adapt to it?
-		}
-		if (mh > texsize) {
-			texsize = mh; // Special case, adapt to it?
-		}
 
 #ifdef GDEXTENSION
 		texsize = Math::next_power_of_2(texsize);
@@ -274,6 +262,20 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_
 		} else {
 			texsize = MIN(texsize, 1024);
 		}
+		if (mw > texsize) { // Special case, adapt to it?
+#ifdef GDEXTENSION
+			texsize = Math::next_power_of_2(mw);
+#else
+			texsize = next_power_of_2(mw);
+#endif
+		}
+		if (mh > texsize) { // Special case, adapt to it?
+#ifdef GDEXTENSION
+			texsize = Math::next_power_of_2(mh);
+#else
+			texsize = next_power_of_2(mh);
+#endif
+		}
 
 		FontTexture tex;
 		tex.texture_w = texsize;
@@ -439,8 +441,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
 		int mw = w + p_rect_margin * 2;
 		int mh = h + p_rect_margin * 2;
 
-		ERR_FAIL_COND_V(mw > 1024, FontGlyph());
-		ERR_FAIL_COND_V(mh > 1024, FontGlyph());
+		ERR_FAIL_COND_V(mw > 4096, FontGlyph());
+		ERR_FAIL_COND_V(mh > 4096, FontGlyph());
 
 		FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh, true);
 		ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
@@ -481,20 +483,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
 			}
 		}
 
-		// Blit to image and texture.
-		{
-			if (RenderingServer::get_singleton() != nullptr) {
-				Ref<Image> img;
-				img.instantiate();
-				img->create_from_data(tex.texture_w, tex.texture_h, false, Image::FORMAT_RGBA8, tex.imgdata);
-				if (tex.texture.is_null()) {
-					tex.texture.instantiate();
-					tex.texture->create_from_image(img);
-				} else {
-					tex.texture->update(img);
-				}
-			}
-		}
+		tex.dirty = true;
 
 		// Update height array.
 		int32_t *offw = tex.offsets.ptrw();
@@ -520,8 +509,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
 	int mw = w + p_rect_margin * 2;
 	int mh = h + p_rect_margin * 2;
 
-	ERR_FAIL_COND_V(mw > 1024, FontGlyph());
-	ERR_FAIL_COND_V(mh > 1024, FontGlyph());
+	ERR_FAIL_COND_V(mw > 4096, FontGlyph());
+	ERR_FAIL_COND_V(mh > 4096, FontGlyph());
 
 	int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
 	Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
@@ -566,21 +555,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
 		}
 	}
 
-	// Blit to image and texture.
-	{
-		if (RenderingServer::get_singleton() != nullptr) {
-			Ref<Image> img;
-			img.instantiate();
-			img->create_from_data(tex.texture_w, tex.texture_h, false, require_format, tex.imgdata);
-
-			if (tex.texture.is_null()) {
-				tex.texture.instantiate();
-				tex.texture->create_from_image(img);
-			} else {
-				tex.texture->update(img);
-			}
-		}
-	}
+	tex.dirty = true;
 
 	// Update height array.
 	int32_t *offw = tex.offsets.ptrw();
@@ -1472,6 +1447,7 @@ void TextServerFallback::font_set_texture_image(const RID &p_font_rid, const Vec
 	tex.texture = Ref<ImageTexture>();
 	tex.texture.instantiate();
 	tex.texture->create_from_image(img);
+	tex.dirty = false;
 }
 
 Ref<Image> TextServerFallback::font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
@@ -2019,6 +1995,19 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can
 			}
 #endif
 			if (RenderingServer::get_singleton() != nullptr) {
+				if (fd->cache[size]->textures[gl.texture_idx].dirty) {
+					FontTexture &tex = fd->cache[size]->textures.write[gl.texture_idx];
+					Ref<Image> img;
+					img.instantiate();
+					img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+					if (tex.texture.is_null()) {
+						tex.texture.instantiate();
+						tex.texture->create_from_image(img);
+					} else {
+						tex.texture->update(img);
+					}
+					tex.dirty = false;
+				}
 				RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid();
 				if (fd->msdf) {
 					Point2 cpos = p_pos;
@@ -2082,6 +2071,19 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI
 			}
 #endif
 			if (RenderingServer::get_singleton() != nullptr) {
+				if (fd->cache[size]->textures[gl.texture_idx].dirty) {
+					FontTexture &tex = fd->cache[size]->textures.write[gl.texture_idx];
+					Ref<Image> img;
+					img.instantiate();
+					img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+					if (tex.texture.is_null()) {
+						tex.texture.instantiate();
+						tex.texture->create_from_image(img);
+					} else {
+						tex.texture->update(img);
+					}
+					tex.dirty = false;
+				}
 				RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid();
 				if (fd->msdf) {
 					Point2 cpos = p_pos;

+ 7 - 2
modules/text_server_fb/text_server_fb.h

@@ -127,6 +127,7 @@ class TextServerFallback : public TextServerExtension {
 		int texture_h = 0;
 		PackedInt32Array offsets;
 		Ref<ImageTexture> texture;
+		bool dirty = true;
 	};
 
 	struct FontTexturePosition {
@@ -343,8 +344,12 @@ public:
 	virtual bool has(const RID &p_rid) override;
 	virtual bool load_support_data(const String &p_filename) override;
 
-	virtual String get_support_data_filename() const override { return ""; };
-	virtual String get_support_data_info() const override { return "Not supported"; };
+	virtual String get_support_data_filename() const override {
+		return "";
+	};
+	virtual String get_support_data_info() const override {
+		return "Not supported";
+	};
 	virtual bool save_support_data(const String &p_filename) const override;
 
 	virtual bool is_locale_right_to_left(const String &p_locale) const override;