Fix a rare crash when running simulate on macOS.

The bug was introduced in 2f0fb1e4ef. The glfwSwapBuffers call should occur on the main UI thread, not the CoreVideo DisplayLink thread.

PiperOrigin-RevId: 517172202
Change-Id: I2491f2194765019748198cd0cc61ca9263331b01
This commit is contained in:
Saran Tunyasuvunakool
2023-03-16 11:05:38 -07:00
committed by Copybara-Service
parent 230e2780de
commit 81ba9ec54a
3 changed files with 11 additions and 21 deletions
+2 -6
View File
@@ -175,14 +175,10 @@ bool GlfwAdapter::ShouldCloseWindow() const {
void GlfwAdapter::SwapBuffers() { void GlfwAdapter::SwapBuffers() {
#ifdef __APPLE__ #ifdef __APPLE__
if (core_video_.has_value()) { if (core_video_.has_value()) {
core_video_->EnqueueSwap(); core_video_->WaitForDisplayRefresh();
core_video_->WaitForSwap();
} else {
Glfw().glfwSwapBuffers(window_);
} }
#else
Glfw().glfwSwapBuffers(window_);
#endif #endif
Glfw().glfwSwapBuffers(window_);
} }
void GlfwAdapter::ToggleFullscreen() { void GlfwAdapter::ToggleFullscreen() {
+4 -3
View File
@@ -19,6 +19,7 @@
#error "This header only works on macOS." #error "This header only works on macOS."
#endif #endif
#include <atomic>
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>
@@ -37,8 +38,8 @@ class GlfwCoreVideo {
public: public:
GlfwCoreVideo(GLFWwindow* window); GlfwCoreVideo(GLFWwindow* window);
~GlfwCoreVideo(); ~GlfwCoreVideo();
void EnqueueSwap();
void WaitForSwap(); void WaitForDisplayRefresh();
int DisplayLinkCallback(); int DisplayLinkCallback();
void UpdateDisplayLink(); void UpdateDisplayLink();
@@ -46,7 +47,7 @@ class GlfwCoreVideo {
GLFWwindow* window_; GLFWwindow* window_;
CVDisplayLinkRef display_link_; CVDisplayLinkRef display_link_;
bool second_buffer_has_content_; std::atomic_bool waiting_;
std::mutex mu_; std::mutex mu_;
std::condition_variable cond_; std::condition_variable cond_;
}; };
+5 -12
View File
@@ -45,23 +45,16 @@ GlfwCoreVideo::~GlfwCoreVideo() {
CVDisplayLinkRelease(display_link_); CVDisplayLinkRelease(display_link_);
} }
void GlfwCoreVideo::EnqueueSwap() { void GlfwCoreVideo::WaitForDisplayRefresh() {
std::unique_lock lock(mu_); std::unique_lock lock(mu_);
second_buffer_has_content_ = true; waiting_.store(true);
} cond_.wait(lock, [this]() { return !this->waiting_; });
void GlfwCoreVideo::WaitForSwap() {
if (second_buffer_has_content_) {
std::unique_lock lock(mu_);
cond_.wait(lock, [this]() { return !this->second_buffer_has_content_; });
}
} }
int GlfwCoreVideo::DisplayLinkCallback() { int GlfwCoreVideo::DisplayLinkCallback() {
if (second_buffer_has_content_) { if (waiting_.load()) {
std::unique_lock lock(mu_); std::unique_lock lock(mu_);
Glfw().glfwSwapBuffers(window_); waiting_.store(false);
second_buffer_has_content_ = false;
cond_.notify_one(); cond_.notify_one();
} }
return kCVReturnSuccess; return kCVReturnSuccess;