Merge pull request #88589 from RandomShaper/gl_preview_liveunlock
Rework viewport capture in preview generation
This commit is contained in:
commit
63bde2feff
|
@ -95,8 +95,35 @@ void EditorResourcePreviewGenerator::_bind_methods() {
|
||||||
EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() {
|
EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorResourcePreviewGenerator::DrawRequester::request_and_wait(RID p_viewport) const {
|
||||||
|
if (EditorResourcePreview::get_singleton()->is_threaded()) {
|
||||||
|
Callable request_vp_update_once = callable_mp(RS::get_singleton(), &RS::viewport_set_update_mode).bind(p_viewport, RS::VIEWPORT_UPDATE_ONCE);
|
||||||
|
RS::get_singleton()->connect(SNAME("frame_pre_draw"), request_vp_update_once, Object::CONNECT_ONE_SHOT);
|
||||||
|
RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorResourcePreviewGenerator::DrawRequester *>(this), &EditorResourcePreviewGenerator::DrawRequester::_post_semaphore));
|
||||||
|
|
||||||
|
semaphore.wait();
|
||||||
|
} else {
|
||||||
|
RS::get_singleton()->draw(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorResourcePreviewGenerator::DrawRequester::abort() const {
|
||||||
|
if (EditorResourcePreview::get_singleton()->is_threaded()) {
|
||||||
|
semaphore.post();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant EditorResourcePreviewGenerator::DrawRequester::_post_semaphore() const {
|
||||||
|
semaphore.post();
|
||||||
|
return Variant(); // Needed because of how the callback is used.
|
||||||
|
}
|
||||||
|
|
||||||
EditorResourcePreview *EditorResourcePreview::singleton = nullptr;
|
EditorResourcePreview *EditorResourcePreview::singleton = nullptr;
|
||||||
|
|
||||||
|
bool EditorResourcePreview::is_threaded() const {
|
||||||
|
return RSG::texture_storage->can_create_resources_async();
|
||||||
|
}
|
||||||
|
|
||||||
void EditorResourcePreview::_thread_func(void *ud) {
|
void EditorResourcePreview::_thread_func(void *ud) {
|
||||||
EditorResourcePreview *erp = (EditorResourcePreview *)ud;
|
EditorResourcePreview *erp = (EditorResourcePreview *)ud;
|
||||||
erp->_thread();
|
erp->_thread();
|
||||||
|
@ -470,7 +497,7 @@ void EditorResourcePreview::start() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RSG::texture_storage->can_create_resources_async()) {
|
if (is_threaded()) {
|
||||||
ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started.");
|
ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started.");
|
||||||
thread.start(_thread_func, this);
|
thread.start(_thread_func, this);
|
||||||
} else {
|
} else {
|
||||||
|
@ -481,7 +508,7 @@ void EditorResourcePreview::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorResourcePreview::stop() {
|
void EditorResourcePreview::stop() {
|
||||||
if (RSG::texture_storage->can_create_resources_async()) {
|
if (is_threaded()) {
|
||||||
if (thread.is_started()) {
|
if (thread.is_started()) {
|
||||||
exiting.set();
|
exiting.set();
|
||||||
preview_sem.post();
|
preview_sem.post();
|
||||||
|
|
|
@ -51,6 +51,16 @@ protected:
|
||||||
GDVIRTUAL0RC(bool, _generate_small_preview_automatically)
|
GDVIRTUAL0RC(bool, _generate_small_preview_automatically)
|
||||||
GDVIRTUAL0RC(bool, _can_generate_small_preview)
|
GDVIRTUAL0RC(bool, _can_generate_small_preview)
|
||||||
|
|
||||||
|
class DrawRequester : public Object {
|
||||||
|
Semaphore semaphore;
|
||||||
|
|
||||||
|
Variant _post_semaphore() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void request_and_wait(RID p_viewport) const;
|
||||||
|
void abort() const;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool handles(const String &p_type) const;
|
virtual bool handles(const String &p_type) const;
|
||||||
virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size, Dictionary &p_metadata) const;
|
virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size, Dictionary &p_metadata) const;
|
||||||
|
@ -132,6 +142,7 @@ public:
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
bool is_threaded() const;
|
||||||
|
|
||||||
EditorResourcePreview();
|
EditorResourcePreview();
|
||||||
~EditorResourcePreview();
|
~EditorResourcePreview();
|
||||||
|
|
|
@ -285,18 +285,8 @@ EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() {
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void EditorMaterialPreviewPlugin::_generate_frame_started() {
|
|
||||||
RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture
|
|
||||||
|
|
||||||
RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_preview_done));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorMaterialPreviewPlugin::_preview_done() {
|
|
||||||
preview_done.post();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorMaterialPreviewPlugin::abort() {
|
void EditorMaterialPreviewPlugin::abort() {
|
||||||
preview_done.post();
|
draw_requester.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorMaterialPreviewPlugin::handles(const String &p_type) const {
|
bool EditorMaterialPreviewPlugin::handles(const String &p_type) const {
|
||||||
|
@ -314,9 +304,7 @@ Ref<Texture2D> EditorMaterialPreviewPlugin::generate(const Ref<Resource> &p_from
|
||||||
if (material->get_shader_mode() == Shader::MODE_SPATIAL) {
|
if (material->get_shader_mode() == Shader::MODE_SPATIAL) {
|
||||||
RS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid());
|
RS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid());
|
||||||
|
|
||||||
RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT);
|
draw_requester.request_and_wait(viewport);
|
||||||
|
|
||||||
preview_done.wait();
|
|
||||||
|
|
||||||
Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
|
Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
|
||||||
RS::get_singleton()->mesh_surface_set_material(sphere, 0, RID());
|
RS::get_singleton()->mesh_surface_set_material(sphere, 0, RID());
|
||||||
|
@ -701,18 +689,8 @@ EditorAudioStreamPreviewPlugin::EditorAudioStreamPreviewPlugin() {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void EditorMeshPreviewPlugin::_generate_frame_started() {
|
|
||||||
RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture
|
|
||||||
|
|
||||||
RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_preview_done));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorMeshPreviewPlugin::_preview_done() {
|
|
||||||
preview_done.post();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorMeshPreviewPlugin::abort() {
|
void EditorMeshPreviewPlugin::abort() {
|
||||||
preview_done.post();
|
draw_requester.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorMeshPreviewPlugin::handles(const String &p_type) const {
|
bool EditorMeshPreviewPlugin::handles(const String &p_type) const {
|
||||||
|
@ -743,9 +721,7 @@ Ref<Texture2D> EditorMeshPreviewPlugin::generate(const Ref<Resource> &p_from, co
|
||||||
xform.origin.z -= rot_aabb.size.z * 2;
|
xform.origin.z -= rot_aabb.size.z * 2;
|
||||||
RS::get_singleton()->instance_set_transform(mesh_instance, xform);
|
RS::get_singleton()->instance_set_transform(mesh_instance, xform);
|
||||||
|
|
||||||
RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT);
|
draw_requester.request_and_wait(viewport);
|
||||||
|
|
||||||
preview_done.wait();
|
|
||||||
|
|
||||||
Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
|
Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
|
||||||
ERR_FAIL_COND_V(img.is_null(), Ref<ImageTexture>());
|
ERR_FAIL_COND_V(img.is_null(), Ref<ImageTexture>());
|
||||||
|
@ -822,18 +798,8 @@ EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void EditorFontPreviewPlugin::_generate_frame_started() {
|
|
||||||
RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture
|
|
||||||
|
|
||||||
RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_preview_done));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorFontPreviewPlugin::_preview_done() {
|
|
||||||
preview_done.post();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorFontPreviewPlugin::abort() {
|
void EditorFontPreviewPlugin::abort() {
|
||||||
preview_done.post();
|
draw_requester.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorFontPreviewPlugin::handles(const String &p_type) const {
|
bool EditorFontPreviewPlugin::handles(const String &p_type) const {
|
||||||
|
@ -865,9 +831,7 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path,
|
||||||
const float fg = c.get_luminance() < 0.5 ? 1.0 : 0.0;
|
const float fg = c.get_luminance() < 0.5 ? 1.0 : 0.0;
|
||||||
sampled_font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg));
|
sampled_font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg));
|
||||||
|
|
||||||
RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT);
|
draw_requester.request_and_wait(viewport);
|
||||||
|
|
||||||
preview_done.wait();
|
|
||||||
|
|
||||||
RS::get_singleton()->canvas_item_clear(canvas_item);
|
RS::get_singleton()->canvas_item_clear(canvas_item);
|
||||||
|
|
||||||
|
|
|
@ -96,10 +96,7 @@ class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator {
|
||||||
RID light_instance2;
|
RID light_instance2;
|
||||||
RID camera;
|
RID camera;
|
||||||
RID camera_attributes;
|
RID camera_attributes;
|
||||||
Semaphore preview_done;
|
DrawRequester draw_requester;
|
||||||
|
|
||||||
void _generate_frame_started();
|
|
||||||
void _preview_done();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool handles(const String &p_type) const override;
|
virtual bool handles(const String &p_type) const override;
|
||||||
|
@ -147,10 +144,7 @@ class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator {
|
||||||
RID light_instance2;
|
RID light_instance2;
|
||||||
RID camera;
|
RID camera;
|
||||||
RID camera_attributes;
|
RID camera_attributes;
|
||||||
Semaphore preview_done;
|
DrawRequester draw_requester;
|
||||||
|
|
||||||
void _generate_frame_started();
|
|
||||||
void _preview_done();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool handles(const String &p_type) const override;
|
virtual bool handles(const String &p_type) const override;
|
||||||
|
@ -168,10 +162,7 @@ class EditorFontPreviewPlugin : public EditorResourcePreviewGenerator {
|
||||||
RID viewport_texture;
|
RID viewport_texture;
|
||||||
RID canvas;
|
RID canvas;
|
||||||
RID canvas_item;
|
RID canvas_item;
|
||||||
Semaphore preview_done;
|
DrawRequester draw_requester;
|
||||||
|
|
||||||
void _generate_frame_started();
|
|
||||||
void _preview_done();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool handles(const String &p_type) const override;
|
virtual bool handles(const String &p_type) const override;
|
||||||
|
|
Loading…
Reference in New Issue