|
237 | 237 | } |
238 | 238 | last_valid = true; |
239 | 239 |
|
| 240 | + if (display_link_running) { |
| 241 | + dispatch_semaphore_wait(display_semaphore, DISPATCH_TIME_FOREVER); |
| 242 | + } |
| 243 | + |
240 | 244 | [CATransaction begin]; |
241 | 245 | [CATransaction setDisableActions:YES]; |
242 | 246 | win.layer.contents = (__bridge id)win.framebuffers[win.current_fb].surface; |
|
249 | 253 | return framework_loaded ? OK : ERR_CANT_CREATE; |
250 | 254 | } |
251 | 255 |
|
| 256 | +void GLManagerEmbedded::create_display_link() { |
| 257 | + DEV_ASSERT(display_link == nullptr); |
| 258 | + |
| 259 | + CVReturn err = CVDisplayLinkCreateWithCGDisplay(CGMainDisplayID(), &display_link); |
| 260 | + ERR_FAIL_COND_MSG(err != kCVReturnSuccess, "Failed to create display link."); |
| 261 | + |
| 262 | + __block dispatch_semaphore_t local_semaphore = display_semaphore; |
| 263 | + |
| 264 | + CVDisplayLinkSetOutputHandler(display_link, ^CVReturn(CVDisplayLinkRef p_display_link, const CVTimeStamp *p_now, const CVTimeStamp *p_output_time, CVOptionFlags p_flags, CVOptionFlags *p_flags_out) { |
| 265 | + dispatch_semaphore_signal(local_semaphore); |
| 266 | + return kCVReturnSuccess; |
| 267 | + }); |
| 268 | +} |
| 269 | + |
| 270 | +void GLManagerEmbedded::release_display_link() { |
| 271 | + DEV_ASSERT(display_link != nullptr); |
| 272 | + if (CVDisplayLinkIsRunning(display_link)) { |
| 273 | + CVDisplayLinkStop(display_link); |
| 274 | + } |
| 275 | + CVDisplayLinkRelease(display_link); |
| 276 | + display_link = nullptr; |
| 277 | +} |
| 278 | + |
| 279 | +void GLManagerEmbedded::set_display_id(uint32_t p_display_id) { |
| 280 | + if (display_id == p_display_id) { |
| 281 | + return; |
| 282 | + } |
| 283 | + |
| 284 | + CVReturn err = CVDisplayLinkSetCurrentCGDisplay(display_link, static_cast<CGDirectDisplayID>(p_display_id)); |
| 285 | + ERR_FAIL_COND_MSG(err != kCVReturnSuccess, "Failed to set display ID for display link."); |
| 286 | +} |
| 287 | + |
| 288 | +void GLManagerEmbedded::set_vsync_enabled(bool p_enabled) { |
| 289 | + if (p_enabled == vsync_enabled) { |
| 290 | + return; |
| 291 | + } |
| 292 | + |
| 293 | + vsync_enabled = p_enabled; |
| 294 | + |
| 295 | + if (vsync_enabled) { |
| 296 | + if (!CVDisplayLinkIsRunning(display_link)) { |
| 297 | + CVReturn err = CVDisplayLinkStart(display_link); |
| 298 | + ERR_FAIL_COND_MSG(err != kCVReturnSuccess, "Failed to start display link."); |
| 299 | + display_link_running = true; |
| 300 | + } |
| 301 | + } else { |
| 302 | + if (CVDisplayLinkIsRunning(display_link)) { |
| 303 | + CVReturn err = CVDisplayLinkStop(display_link); |
| 304 | + ERR_FAIL_COND_MSG(err != kCVReturnSuccess, "Failed to stop display link."); |
| 305 | + display_link_running = false; |
| 306 | + } |
| 307 | + } |
| 308 | +} |
| 309 | + |
252 | 310 | GLManagerEmbedded::GLManagerEmbedded() { |
| 311 | + display_semaphore = dispatch_semaphore_create(BUFFER_COUNT); |
| 312 | + |
| 313 | + create_display_link(); |
| 314 | + |
253 | 315 | NSBundle *framework = [NSBundle bundleWithIdentifier:@"com.apple.opengl"]; |
254 | 316 | if ([framework load]) { |
255 | 317 | void *library_handle = dlopen([framework.executablePath UTF8String], RTLD_NOW); |
|
263 | 325 | } |
264 | 326 |
|
265 | 327 | GLManagerEmbedded::~GLManagerEmbedded() { |
| 328 | + release_display_link(); |
266 | 329 | release_current(); |
267 | 330 | } |
268 | 331 |
|
|
0 commit comments