2013-11-14 18:18:25 +01:00
|
|
|
/******************************************************************************
|
|
|
|
Copyright (C) 2013 by Ruwen Hahn <palana@stunned.de>
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2013-12-02 22:24:38 -07:00
|
|
|
the Free Software Foundation, either version 2 of the License, or
|
2013-11-14 18:18:25 +01:00
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#include "gl-subsystem.h"
|
|
|
|
#include <OpenGL/OpenGL.h>
|
|
|
|
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
|
|
#import <AppKit/AppKit.h>
|
|
|
|
|
|
|
|
//#include "util/darray.h"
|
|
|
|
|
|
|
|
struct gl_windowinfo {
|
|
|
|
NSView *view;
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
NSOpenGLContext *context;
|
|
|
|
gs_texture_t *texture;
|
|
|
|
GLuint fbo;
|
2013-11-14 18:18:25 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct gl_platform {
|
|
|
|
NSOpenGLContext *context;
|
|
|
|
};
|
|
|
|
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
static NSOpenGLContext *gl_context_create(NSOpenGLContext *share)
|
2013-11-14 18:18:25 +01:00
|
|
|
{
|
|
|
|
unsigned attrib_count = 0;
|
|
|
|
|
2019-07-09 13:29:39 -05:00
|
|
|
#define ADD_ATTR(x) \
|
|
|
|
{ \
|
|
|
|
attributes[attrib_count++] = (NSOpenGLPixelFormatAttribute)x; \
|
|
|
|
}
|
|
|
|
#define ADD_ATTR2(x, y) \
|
|
|
|
{ \
|
|
|
|
ADD_ATTR(x); \
|
|
|
|
ADD_ATTR(y); \
|
|
|
|
}
|
2013-11-14 18:18:25 +01:00
|
|
|
|
|
|
|
NSOpenGLPixelFormatAttribute attributes[40];
|
|
|
|
|
2015-08-01 18:45:39 -07:00
|
|
|
ADD_ATTR(NSOpenGLPFADoubleBuffer);
|
2013-11-14 18:18:25 +01:00
|
|
|
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
|
|
|
ADD_ATTR(0);
|
|
|
|
|
|
|
|
#undef ADD_ATTR2
|
|
|
|
#undef ADD_ATTR
|
|
|
|
|
2013-11-14 10:48:48 -07:00
|
|
|
NSOpenGLPixelFormat *pf;
|
|
|
|
pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
2019-07-09 13:29:39 -05:00
|
|
|
if (!pf) {
|
2013-11-14 18:18:25 +01:00
|
|
|
blog(LOG_ERROR, "Failed to create pixel format");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-11-14 10:48:48 -07:00
|
|
|
NSOpenGLContext *context;
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
context = [[NSOpenGLContext alloc] initWithFormat:pf
|
|
|
|
shareContext:share];
|
2013-11-14 18:18:25 +01:00
|
|
|
[pf release];
|
2019-07-09 13:29:39 -05:00
|
|
|
if (!context) {
|
2013-11-14 18:18:25 +01:00
|
|
|
blog(LOG_ERROR, "Failed to create context");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-08-01 18:45:39 -07:00
|
|
|
[context clearDrawable];
|
2013-11-14 18:18:25 +01:00
|
|
|
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
2015-08-01 18:45:39 -07:00
|
|
|
struct gl_platform *gl_platform_create(gs_device_t *device, uint32_t adapter)
|
2013-11-14 18:18:25 +01:00
|
|
|
{
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
UNUSED_PARAMETER(device);
|
|
|
|
UNUSED_PARAMETER(adapter);
|
2013-11-14 18:18:25 +01:00
|
|
|
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
NSOpenGLContext *context = gl_context_create(nil);
|
|
|
|
if (!context) {
|
|
|
|
blog(LOG_ERROR, "gl_context_create failed");
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-11-14 18:18:25 +01:00
|
|
|
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
[context makeCurrentContext];
|
|
|
|
GLint interval = 0;
|
|
|
|
[context setValues:&interval forParameter:NSOpenGLCPSwapInterval];
|
|
|
|
const bool success = gladLoadGL() != 0;
|
2013-11-14 18:18:25 +01:00
|
|
|
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
if (!success) {
|
|
|
|
blog(LOG_ERROR, "gladLoadGL failed");
|
|
|
|
[context release];
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-11-14 18:18:25 +01:00
|
|
|
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
struct gl_platform *plat = bzalloc(sizeof(struct gl_platform));
|
|
|
|
plat->context = context;
|
2013-11-14 18:18:25 +01:00
|
|
|
return plat;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gl_platform_destroy(struct gl_platform *platform)
|
|
|
|
{
|
2019-07-09 13:29:39 -05:00
|
|
|
if (!platform)
|
2013-11-14 18:18:25 +01:00
|
|
|
return;
|
|
|
|
|
2014-04-04 01:41:35 +02:00
|
|
|
[platform->context release];
|
|
|
|
platform->context = nil;
|
2013-11-14 18:18:25 +01:00
|
|
|
|
|
|
|
bfree(platform);
|
|
|
|
}
|
|
|
|
|
2014-04-12 13:33:47 +02:00
|
|
|
bool gl_platform_init_swapchain(struct gs_swap_chain *swap)
|
|
|
|
{
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
NSOpenGLContext *parent = swap->device->plat->context;
|
|
|
|
NSOpenGLContext *context = gl_context_create(parent);
|
|
|
|
bool success = context != nil;
|
|
|
|
if (success) {
|
|
|
|
CGLContextObj parent_obj = [parent CGLContextObj];
|
|
|
|
CGLLockContext(parent_obj);
|
|
|
|
|
|
|
|
[parent makeCurrentContext];
|
|
|
|
struct gs_init_data *init_data = &swap->info;
|
|
|
|
swap->wi->texture = device_texture_create(
|
|
|
|
swap->device, init_data->cx, init_data->cy,
|
|
|
|
init_data->format, 1, NULL, GS_RENDER_TARGET);
|
|
|
|
glFlush();
|
|
|
|
[NSOpenGLContext clearCurrentContext];
|
|
|
|
|
|
|
|
CGLContextObj context_obj = [context CGLContextObj];
|
|
|
|
CGLLockContext(context_obj);
|
|
|
|
|
|
|
|
[context makeCurrentContext];
|
|
|
|
[context setView:swap->wi->view];
|
|
|
|
GLint interval = 0;
|
|
|
|
[context setValues:&interval
|
|
|
|
forParameter:NSOpenGLCPSwapInterval];
|
|
|
|
gl_gen_framebuffers(1, &swap->wi->fbo);
|
|
|
|
gl_bind_framebuffer(GL_FRAMEBUFFER, swap->wi->fbo);
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
|
|
|
GL_TEXTURE_2D,
|
|
|
|
swap->wi->texture->texture, 0);
|
|
|
|
gl_success("glFrameBufferTexture2D");
|
|
|
|
glFlush();
|
|
|
|
[NSOpenGLContext clearCurrentContext];
|
|
|
|
|
|
|
|
CGLUnlockContext(context_obj);
|
|
|
|
|
|
|
|
CGLUnlockContext(parent_obj);
|
|
|
|
|
|
|
|
swap->wi->context = context;
|
|
|
|
}
|
2014-04-12 13:33:47 +02:00
|
|
|
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
return success;
|
2014-04-12 13:33:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void gl_platform_cleanup_swapchain(struct gs_swap_chain *swap)
|
|
|
|
{
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
NSOpenGLContext *parent = swap->device->plat->context;
|
|
|
|
CGLContextObj parent_obj = [parent CGLContextObj];
|
|
|
|
CGLLockContext(parent_obj);
|
|
|
|
|
|
|
|
NSOpenGLContext *context = swap->wi->context;
|
|
|
|
CGLContextObj context_obj = [context CGLContextObj];
|
|
|
|
CGLLockContext(context_obj);
|
|
|
|
|
|
|
|
[context makeCurrentContext];
|
|
|
|
gl_delete_framebuffers(1, &swap->wi->fbo);
|
|
|
|
glFlush();
|
|
|
|
[NSOpenGLContext clearCurrentContext];
|
|
|
|
|
|
|
|
CGLUnlockContext(context_obj);
|
|
|
|
|
|
|
|
[parent makeCurrentContext];
|
|
|
|
gs_texture_destroy(swap->wi->texture);
|
|
|
|
glFlush();
|
|
|
|
[NSOpenGLContext clearCurrentContext];
|
|
|
|
swap->wi->context = nil;
|
|
|
|
|
|
|
|
CGLUnlockContext(parent_obj);
|
2014-04-12 13:33:47 +02:00
|
|
|
}
|
|
|
|
|
2014-09-26 15:25:59 -07:00
|
|
|
struct gl_windowinfo *gl_windowinfo_create(const struct gs_init_data *info)
|
2013-11-14 18:18:25 +01:00
|
|
|
{
|
2019-07-09 13:29:39 -05:00
|
|
|
if (!info)
|
2013-11-14 18:18:25 +01:00
|
|
|
return NULL;
|
|
|
|
|
2019-07-09 13:29:39 -05:00
|
|
|
if (!info->window.view)
|
2013-11-14 18:18:25 +01:00
|
|
|
return NULL;
|
|
|
|
|
2014-03-24 17:41:28 +01:00
|
|
|
struct gl_windowinfo *wi = bzalloc(sizeof(struct gl_windowinfo));
|
2013-11-14 18:18:25 +01:00
|
|
|
|
2013-11-20 15:00:16 -07:00
|
|
|
wi->view = info->window.view;
|
2014-04-16 22:30:50 +02:00
|
|
|
[info->window.view setWantsBestResolutionOpenGLSurface:YES];
|
2013-11-14 18:18:25 +01:00
|
|
|
|
|
|
|
return wi;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gl_windowinfo_destroy(struct gl_windowinfo *wi)
|
|
|
|
{
|
2019-07-09 13:29:39 -05:00
|
|
|
if (!wi)
|
2013-11-14 18:18:25 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
wi->view = nil;
|
|
|
|
bfree(wi);
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void gl_update(gs_device_t *device)
|
2013-12-31 03:09:28 -07:00
|
|
|
{
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
gs_swapchain_t *swap = device->cur_swap;
|
|
|
|
NSOpenGLContext *parent = device->plat->context;
|
|
|
|
NSOpenGLContext *context = swap->wi->context;
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^() {
|
|
|
|
CGLContextObj parent_obj = [parent CGLContextObj];
|
|
|
|
CGLLockContext(parent_obj);
|
|
|
|
|
|
|
|
CGLContextObj context_obj = [context CGLContextObj];
|
|
|
|
CGLLockContext(context_obj);
|
|
|
|
|
|
|
|
[context makeCurrentContext];
|
|
|
|
[context update];
|
|
|
|
struct gs_init_data *info = &swap->info;
|
|
|
|
gs_texture_t *previous = swap->wi->texture;
|
|
|
|
swap->wi->texture = device_texture_create(device, info->cx,
|
|
|
|
info->cy,
|
|
|
|
info->format, 1, NULL,
|
|
|
|
GS_RENDER_TARGET);
|
|
|
|
gl_bind_framebuffer(GL_FRAMEBUFFER, swap->wi->fbo);
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
|
|
|
GL_TEXTURE_2D,
|
|
|
|
swap->wi->texture->texture, 0);
|
|
|
|
gl_success("glFrameBufferTexture2D");
|
|
|
|
gs_texture_destroy(previous);
|
|
|
|
glFlush();
|
|
|
|
[NSOpenGLContext clearCurrentContext];
|
|
|
|
|
|
|
|
CGLUnlockContext(context_obj);
|
|
|
|
|
|
|
|
CGLUnlockContext(parent_obj);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void gl_clear_context(gs_device_t *device)
|
|
|
|
{
|
|
|
|
UNUSED_PARAMETER(device);
|
|
|
|
[NSOpenGLContext clearCurrentContext];
|
2013-12-31 03:09:28 -07:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void device_enter_context(gs_device_t *device)
|
2013-11-14 18:18:25 +01:00
|
|
|
{
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
CGLLockContext([device->plat->context CGLContextObj]);
|
|
|
|
|
2014-04-04 01:41:35 +02:00
|
|
|
[device->plat->context makeCurrentContext];
|
2013-11-14 18:18:25 +01:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void device_leave_context(gs_device_t *device)
|
2013-11-14 18:18:25 +01:00
|
|
|
{
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
glFlush();
|
2013-11-14 18:18:25 +01:00
|
|
|
[NSOpenGLContext clearCurrentContext];
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
device->cur_render_target = NULL;
|
|
|
|
device->cur_zstencil_buffer = NULL;
|
|
|
|
device->cur_swap = NULL;
|
|
|
|
device->cur_fbo = NULL;
|
|
|
|
|
|
|
|
CGLUnlockContext([device->plat->context CGLContextObj]);
|
2013-11-14 18:18:25 +01:00
|
|
|
}
|
|
|
|
|
2019-08-29 12:43:10 -07:00
|
|
|
void *device_get_device_obj(gs_device_t *device)
|
|
|
|
{
|
|
|
|
return device->plat->context;
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void device_load_swapchain(gs_device_t *device, gs_swapchain_t *swap)
|
2013-11-14 18:18:25 +01:00
|
|
|
{
|
2019-07-09 13:29:39 -05:00
|
|
|
if (device->cur_swap == swap)
|
2013-11-14 18:18:25 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
device->cur_swap = swap;
|
2015-08-01 18:45:39 -07:00
|
|
|
if (swap) {
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
device_set_render_target(device, swap->wi->texture, NULL);
|
2015-08-01 18:45:39 -07:00
|
|
|
}
|
2013-11-14 18:18:25 +01:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void device_present(gs_device_t *device)
|
2013-11-14 18:18:25 +01:00
|
|
|
{
|
libobs-opengl: OpenGL thread-safety on Mac
Attempt to fix threading issues that cause OBS to force-crash when
compiled with latest Xcode. There are two places where the new SDK
introduces a force-crash because operations are not happening on the
main thread: when we modify the context view to switch swap chains, and
when we resize a swap chain.
Instead of using just one context for all rendering, we create an
additional context for each swap chain, set each view once on
initialization, and switch contexts only in present to blit the final
framebuffer. This is an extra copy, but it's pretty hairy to optimize
away, and it's not worth potential regressions just to speed up Mac.
For resizing, we schedule the update code to run on the main thread from
the render thread. Ideally, we wouldn't have to round trip the logic
from main thread to graphics thread and back, but I don't think we want
to hack up the interface for this, especially since OpenGL will give way
to Metal soon enough.
2019-12-25 22:25:38 -08:00
|
|
|
glFlush();
|
|
|
|
[NSOpenGLContext clearCurrentContext];
|
|
|
|
|
|
|
|
CGLLockContext([device->cur_swap->wi->context CGLContextObj]);
|
|
|
|
|
|
|
|
[device->cur_swap->wi->context makeCurrentContext];
|
|
|
|
gl_bind_framebuffer(GL_READ_FRAMEBUFFER, device->cur_swap->wi->fbo);
|
|
|
|
gl_bind_framebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
|
const uint32_t width = device->cur_swap->info.cx;
|
|
|
|
const uint32_t height = device->cur_swap->info.cy;
|
|
|
|
glBlitFramebuffer(0, 0, width, height, 0, height, width, 0,
|
|
|
|
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
|
|
|
[device->cur_swap->wi->context flushBuffer];
|
|
|
|
glFlush();
|
|
|
|
[NSOpenGLContext clearCurrentContext];
|
|
|
|
|
|
|
|
CGLUnlockContext([device->cur_swap->wi->context CGLContextObj]);
|
|
|
|
|
|
|
|
[device->plat->context makeCurrentContext];
|
2013-11-14 18:18:25 +01:00
|
|
|
}
|
|
|
|
|
2022-03-09 21:41:23 -08:00
|
|
|
bool device_is_monitor_hdr(gs_device_t *device, void *monitor)
|
|
|
|
{
|
2022-04-19 20:45:27 +02:00
|
|
|
UNUSED_PARAMETER(device);
|
|
|
|
UNUSED_PARAMETER(monitor);
|
|
|
|
|
2022-03-09 21:41:23 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-09-26 15:25:59 -07:00
|
|
|
void gl_getclientsize(const struct gs_swap_chain *swap, uint32_t *width,
|
2019-07-09 13:29:39 -05:00
|
|
|
uint32_t *height)
|
2013-11-14 18:18:25 +01:00
|
|
|
{
|
2019-07-09 13:29:39 -05:00
|
|
|
if (width)
|
|
|
|
*width = swap->info.cx;
|
|
|
|
if (height)
|
|
|
|
*height = swap->info.cy;
|
2013-11-14 18:18:25 +01:00
|
|
|
}
|
2013-12-23 16:34:56 +01:00
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
gs_texture_t *device_texture_create_from_iosurface(gs_device_t *device,
|
2019-07-09 13:29:39 -05:00
|
|
|
void *iosurf)
|
2013-12-23 16:34:56 +01:00
|
|
|
{
|
|
|
|
IOSurfaceRef ref = (IOSurfaceRef)iosurf;
|
2014-04-04 01:54:50 +02:00
|
|
|
struct gs_texture_2d *tex = bzalloc(sizeof(struct gs_texture_2d));
|
2013-12-23 16:34:56 +01:00
|
|
|
|
2013-12-24 17:07:58 +01:00
|
|
|
OSType pf = IOSurfaceGetPixelFormat(ref);
|
|
|
|
if (pf != 'BGRA')
|
|
|
|
blog(LOG_ERROR, "Unexpected pixel format: %d (%c%c%c%c)", pf,
|
2019-07-09 13:29:39 -05:00
|
|
|
pf >> 24, pf >> 16, pf >> 8, pf);
|
2013-12-24 17:07:58 +01:00
|
|
|
|
2013-12-23 16:34:56 +01:00
|
|
|
const enum gs_color_format color_format = GS_BGRA;
|
|
|
|
|
2019-07-09 13:29:39 -05:00
|
|
|
tex->base.device = device;
|
|
|
|
tex->base.type = GS_TEXTURE_2D;
|
|
|
|
tex->base.format = GS_BGRA;
|
|
|
|
tex->base.levels = 1;
|
|
|
|
tex->base.gl_format = convert_gs_format(color_format);
|
2013-12-23 16:34:56 +01:00
|
|
|
tex->base.gl_internal_format = convert_gs_internal_format(color_format);
|
2019-07-09 13:29:39 -05:00
|
|
|
tex->base.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
2020-11-30 21:59:01 +01:00
|
|
|
tex->base.gl_target = GL_TEXTURE_RECTANGLE_ARB;
|
2019-07-09 13:29:39 -05:00
|
|
|
tex->base.is_dynamic = false;
|
|
|
|
tex->base.is_render_target = false;
|
|
|
|
tex->base.gen_mipmaps = false;
|
|
|
|
tex->width = IOSurfaceGetWidth(ref);
|
|
|
|
tex->height = IOSurfaceGetHeight(ref);
|
2013-12-23 16:34:56 +01:00
|
|
|
|
|
|
|
if (!gl_gen_textures(1, &tex->base.texture))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (!gl_bind_texture(tex->base.gl_target, tex->base.texture))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
CGLError err = CGLTexImageIOSurface2D(
|
2019-07-09 13:29:39 -05:00
|
|
|
[[NSOpenGLContext currentContext] CGLContextObj],
|
|
|
|
tex->base.gl_target, tex->base.gl_internal_format, tex->width,
|
|
|
|
tex->height, tex->base.gl_format, tex->base.gl_type, ref, 0);
|
|
|
|
|
|
|
|
if (err != kCGLNoError) {
|
|
|
|
blog(LOG_ERROR,
|
|
|
|
"CGLTexImageIOSurface2D: %u, %s"
|
|
|
|
" (device_texture_create_from_iosurface)",
|
|
|
|
err, CGLErrorString(err));
|
2013-12-23 16:34:56 +01:00
|
|
|
|
|
|
|
gl_success("CGLTexImageIOSurface2D");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2019-07-09 13:29:39 -05:00
|
|
|
if (!gl_tex_param_i(tex->base.gl_target, GL_TEXTURE_MAX_LEVEL, 0))
|
2013-12-23 16:34:56 +01:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (!gl_bind_texture(tex->base.gl_target, 0))
|
|
|
|
goto fail;
|
|
|
|
|
2019-07-09 13:29:39 -05:00
|
|
|
return (gs_texture_t *)tex;
|
2013-12-23 16:34:56 +01:00
|
|
|
|
|
|
|
fail:
|
2019-07-09 13:29:39 -05:00
|
|
|
gs_texture_destroy((gs_texture_t *)tex);
|
2014-08-07 23:42:07 -07:00
|
|
|
blog(LOG_ERROR, "device_texture_create_from_iosurface (GL) failed");
|
2013-12-23 16:34:56 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-11-30 21:59:01 +01:00
|
|
|
gs_texture_t *device_texture_open_shared(gs_device_t *device, uint32_t handle)
|
|
|
|
{
|
|
|
|
gs_texture_t *texture = NULL;
|
|
|
|
IOSurfaceRef ref = IOSurfaceLookupFromMachPort((mach_port_t)handle);
|
|
|
|
texture = device_texture_create_from_iosurface(device, ref);
|
|
|
|
CFRelease(ref);
|
|
|
|
return texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool device_shared_texture_available(void)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
bool gs_texture_rebind_iosurface(gs_texture_t *texture, void *iosurf)
|
2013-12-23 16:34:56 +01:00
|
|
|
{
|
|
|
|
if (!texture)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!iosurf)
|
|
|
|
return false;
|
|
|
|
|
2019-07-09 13:29:39 -05:00
|
|
|
struct gs_texture_2d *tex = (struct gs_texture_2d *)texture;
|
2013-12-23 16:34:56 +01:00
|
|
|
IOSurfaceRef ref = (IOSurfaceRef)iosurf;
|
|
|
|
|
2013-12-24 17:07:58 +01:00
|
|
|
OSType pf = IOSurfaceGetPixelFormat(ref);
|
|
|
|
if (pf != 'BGRA')
|
|
|
|
blog(LOG_ERROR, "Unexpected pixel format: %d (%c%c%c%c)", pf,
|
2019-07-09 13:29:39 -05:00
|
|
|
pf >> 24, pf >> 16, pf >> 8, pf);
|
2013-12-24 17:07:58 +01:00
|
|
|
|
2022-06-04 20:35:15 -07:00
|
|
|
tex->width = IOSurfaceGetWidth(ref);
|
|
|
|
tex->height = IOSurfaceGetHeight(ref);
|
2013-12-23 16:34:56 +01:00
|
|
|
|
|
|
|
if (!gl_bind_texture(tex->base.gl_target, tex->base.texture))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CGLError err = CGLTexImageIOSurface2D(
|
2019-07-09 13:29:39 -05:00
|
|
|
[[NSOpenGLContext currentContext] CGLContextObj],
|
|
|
|
tex->base.gl_target, tex->base.gl_internal_format, tex->width,
|
|
|
|
tex->height, tex->base.gl_format, tex->base.gl_type, ref, 0);
|
|
|
|
|
|
|
|
if (err != kCGLNoError) {
|
|
|
|
blog(LOG_ERROR,
|
|
|
|
"CGLTexImageIOSurface2D: %u, %s"
|
|
|
|
" (gs_texture_rebind_iosurface)",
|
|
|
|
err, CGLErrorString(err));
|
2013-12-23 16:34:56 +01:00
|
|
|
|
|
|
|
gl_success("CGLTexImageIOSurface2D");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!gl_bind_texture(tex->base.gl_target, 0))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|