Răsfoiți Sursa

Add per window GL context for Cocoa libobs-opengl implementation

This fixes some problems with multiple swap chains (e.g. flickering
between the render views)
Palana 11 ani în urmă
părinte
comite
f8b90a5c8f
1 a modificat fișierele cu 33 adăugiri și 13 ștergeri
  1. 33 13
      libobs-opengl/gl-cocoa.m

+ 33 - 13
libobs-opengl/gl-cocoa.m

@@ -26,6 +26,7 @@
 
 
 struct gl_windowinfo {
+	NSOpenGLContext *context;
 	NSView *view;
 };
 
@@ -34,6 +35,8 @@ struct gl_platform {
 	struct gs_swap_chain swap;
 };
 
+static NSOpenGLContext *plat_context;
+
 static NSOpenGLContext *gl_context_create(struct gs_init_data *info)
 {
 	unsigned attrib_count = 0;
@@ -84,7 +87,8 @@ static NSOpenGLContext *gl_context_create(struct gs_init_data *info)
 	}
 
 	NSOpenGLContext *context;
-	context = [[NSOpenGLContext alloc] initWithFormat:pf shareContext:nil];
+	context = [[NSOpenGLContext alloc] initWithFormat:pf
+					     shareContext:plat_context];
 	[pf release];
 	if(!context) {
 		blog(LOG_ERROR, "Failed to create context");
@@ -99,14 +103,22 @@ static NSOpenGLContext *gl_context_create(struct gs_init_data *info)
 static bool gl_init_default_swap(struct gl_platform *plat, device_t dev,
 		struct gs_init_data *info)
 {
-	if(!(plat->context = gl_context_create(info)))
+	plat_context = nil;
+
+	struct gl_windowinfo *wi = gl_windowinfo_create(info);
+
+	if (!wi)
 		return false;
 
 	plat->swap.device = dev;
 	plat->swap.info	  = *info;
-	plat->swap.wi     = gl_windowinfo_create(info);
+	plat->swap.wi     = wi;
+
+	plat->context     = wi->context;
+
+	plat_context = plat->context;
 
-	return plat->swap.wi != NULL;
+	return true;
 }
 
 struct gl_platform *gl_platform_create(device_t device,
@@ -143,8 +155,6 @@ void gl_platform_destroy(struct gl_platform *platform)
 	if(!platform)
 		return;
 
-	[platform->context release];
-	platform->context = nil;
 	gl_windowinfo_destroy(platform->swap.wi);
 
 	bfree(platform);
@@ -158,9 +168,9 @@ struct gl_windowinfo *gl_windowinfo_create(struct gs_init_data *info)
 	if(!info->window.view)
 		return NULL;
 
-	struct gl_windowinfo *wi = bmalloc(sizeof(struct gl_windowinfo));
-	memset(wi, 0, sizeof(struct gl_windowinfo));
+	struct gl_windowinfo *wi = bzalloc(sizeof(struct gl_windowinfo));
 
+	wi->context = gl_context_create(info);
 	wi->view = info->window.view;
 
 	return wi;
@@ -171,25 +181,34 @@ void gl_windowinfo_destroy(struct gl_windowinfo *wi)
 	if(!wi)
 		return;
 
+	[wi->context release];
+	wi->context = nil;
 	wi->view = nil;
 	bfree(wi);
 }
 
+static inline NSOpenGLContext *current_context(device_t device)
+{
+	if (device->cur_swap)
+		return device->cur_swap->wi->context;
+	return device->plat->context;
+}
+
 void gl_update(device_t device)
 {
-	[device->plat->context update];
+	[current_context(device) update];
 }
 
 void device_entercontext(device_t device)
 {
-	CGLLockContext([device->plat->context CGLContextObj]);
-	[device->plat->context makeCurrentContext];
+	[current_context(device) makeCurrentContext];
 }
 
 void device_leavecontext(device_t device)
 {
+	UNUSED_PARAMETER(device);
+
 	[NSOpenGLContext clearCurrentContext];
-	CGLUnlockContext([device->plat->context CGLContextObj]);
 }
 
 void device_load_swapchain(device_t device, swapchain_t swap)
@@ -201,11 +220,12 @@ void device_load_swapchain(device_t device, swapchain_t swap)
 		return;
 
 	device->cur_swap = swap;
+	[current_context(device) makeCurrentContext];
 }
 
 void device_present(device_t device)
 {
-	[device->plat->context flushBuffer];
+	[current_context(device) flushBuffer];
 }
 
 void gl_getclientsize(struct gs_swap_chain *swap, uint32_t *width,