forked from bartvdbraak/blender
GHOST: Delete Mac OpenGL support
The maximum OpenGL versions supported on mac doesn't meet the minimum required version (>=4.3) anymore. This removes all the OpenGL paths in GHOST Cocoa backend and from the drop down menu in the user preferences. Pull Request: https://projects.blender.org/blender/blender/pulls/110185
This commit is contained in:
parent
940558f9ac
commit
cdb8a8929c
@ -650,8 +650,12 @@ mark_as_advanced(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# OpenGL
|
# OpenGL
|
||||||
option(WITH_OPENGL_BACKEND "Enable OpenGL support as graphic backend" ON)
|
if(NOT APPLE)
|
||||||
mark_as_advanced(WITH_OPENGL_BACKEND)
|
option(WITH_OPENGL_BACKEND "Enable OpenGL support as graphic backend" ON)
|
||||||
|
mark_as_advanced(WITH_OPENGL_BACKEND)
|
||||||
|
else()
|
||||||
|
set(WITH_OPENGL_BACKEND OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Vulkan
|
# Vulkan
|
||||||
option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (only for development)" OFF)
|
option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (only for development)" OFF)
|
||||||
|
@ -44,11 +44,7 @@ class GHOST_ContextCGL : public GHOST_Context {
|
|||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
GHOST_ContextCGL(bool stereoVisual,
|
GHOST_ContextCGL(bool stereoVisual, NSView *metalView, CAMetalLayer *metalLayer, int debug);
|
||||||
NSView *metalView,
|
|
||||||
CAMetalLayer *metalLayer,
|
|
||||||
NSOpenGLView *openglView,
|
|
||||||
GHOST_TDrawingContextType type);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor.
|
* Destructor.
|
||||||
@ -134,23 +130,11 @@ class GHOST_ContextCGL : public GHOST_Context {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/** Metal state */
|
/** Metal state */
|
||||||
/* Set this flag to `true` when rendering with Metal API for Viewport.
|
|
||||||
* TODO(Metal): This should be assigned to externally. */
|
|
||||||
bool m_useMetalForRendering = false;
|
|
||||||
NSView *m_metalView;
|
NSView *m_metalView;
|
||||||
CAMetalLayer *m_metalLayer;
|
CAMetalLayer *m_metalLayer;
|
||||||
MTLRenderPipelineState *m_metalRenderPipeline;
|
MTLRenderPipelineState *m_metalRenderPipeline;
|
||||||
bool m_ownsMetalDevice;
|
bool m_ownsMetalDevice;
|
||||||
|
|
||||||
/** OpenGL state, for GPUs that don't support Metal */
|
|
||||||
NSOpenGLView *m_openGLView;
|
|
||||||
|
|
||||||
/** The OpenGL drawing context */
|
|
||||||
NSOpenGLContext *m_openGLContext;
|
|
||||||
|
|
||||||
/** The virtualized default frame-buffer. */
|
|
||||||
unsigned int m_defaultFramebuffer;
|
|
||||||
|
|
||||||
/** The virtualized default frame-buffer's texture. */
|
/** The virtualized default frame-buffer's texture. */
|
||||||
/**
|
/**
|
||||||
* Texture that you can render into with Metal. The texture will be
|
* Texture that you can render into with Metal. The texture will be
|
||||||
@ -191,5 +175,5 @@ class GHOST_ContextCGL : public GHOST_Context {
|
|||||||
void metalInitFramebuffer();
|
void metalInitFramebuffer();
|
||||||
void metalUpdateFramebuffer();
|
void metalUpdateFramebuffer();
|
||||||
void metalSwapBuffers();
|
void metalSwapBuffers();
|
||||||
void initClear();
|
void initClear(){};
|
||||||
};
|
};
|
||||||
|
@ -27,9 +27,7 @@
|
|||||||
|
|
||||||
static void ghost_fatal_error_dialog(const char *msg)
|
static void ghost_fatal_error_dialog(const char *msg)
|
||||||
{
|
{
|
||||||
/* clang-format off */
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
/* clang-format on */
|
|
||||||
NSString *message = [NSString stringWithFormat:@"Error opening window:\n%s", msg];
|
NSString *message = [NSString stringWithFormat:@"Error opening window:\n%s", msg];
|
||||||
|
|
||||||
NSAlert *alert = [[NSAlert alloc] init];
|
NSAlert *alert = [[NSAlert alloc] init];
|
||||||
@ -50,17 +48,12 @@ int GHOST_ContextCGL::s_sharedCount = 0;
|
|||||||
GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual,
|
GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual,
|
||||||
NSView *metalView,
|
NSView *metalView,
|
||||||
CAMetalLayer *metalLayer,
|
CAMetalLayer *metalLayer,
|
||||||
NSOpenGLView *openGLView,
|
int debug)
|
||||||
GHOST_TDrawingContextType type)
|
|
||||||
: GHOST_Context(stereoVisual),
|
: GHOST_Context(stereoVisual),
|
||||||
m_useMetalForRendering(type == GHOST_kDrawingContextTypeMetal),
|
|
||||||
m_metalView(metalView),
|
m_metalView(metalView),
|
||||||
m_metalLayer(metalLayer),
|
m_metalLayer(metalLayer),
|
||||||
m_metalRenderPipeline(nil),
|
m_metalRenderPipeline(nil),
|
||||||
m_openGLView(openGLView),
|
m_debug(debug)
|
||||||
m_openGLContext(nil),
|
|
||||||
m_defaultFramebuffer(0),
|
|
||||||
m_debug(false)
|
|
||||||
{
|
{
|
||||||
/* Initialize Metal Swap-chain. */
|
/* Initialize Metal Swap-chain. */
|
||||||
current_swapchain_index = 0;
|
current_swapchain_index = 0;
|
||||||
@ -68,6 +61,7 @@ GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual,
|
|||||||
m_defaultFramebufferMetalTexture[i].texture = nil;
|
m_defaultFramebufferMetalTexture[i].texture = nil;
|
||||||
m_defaultFramebufferMetalTexture[i].index = i;
|
m_defaultFramebufferMetalTexture[i].index = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_metalView) {
|
if (m_metalView) {
|
||||||
m_ownsMetalDevice = false;
|
m_ownsMetalDevice = false;
|
||||||
metalInit();
|
metalInit();
|
||||||
@ -107,31 +101,6 @@ GHOST_ContextCGL::~GHOST_ContextCGL()
|
|||||||
{
|
{
|
||||||
metalFree();
|
metalFree();
|
||||||
|
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
if (m_openGLContext != nil) {
|
|
||||||
if (m_openGLContext == [NSOpenGLContext currentContext]) {
|
|
||||||
[NSOpenGLContext clearCurrentContext];
|
|
||||||
|
|
||||||
if (m_openGLView) {
|
|
||||||
[m_openGLView clearGLContext];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) {
|
|
||||||
assert(s_sharedCount > 0);
|
|
||||||
|
|
||||||
s_sharedCount--;
|
|
||||||
|
|
||||||
if (s_sharedCount == 0)
|
|
||||||
s_sharedOpenGLContext = nil;
|
|
||||||
|
|
||||||
[m_openGLContext release];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ownsMetalDevice) {
|
if (m_ownsMetalDevice) {
|
||||||
if (m_metalLayer) {
|
if (m_metalLayer) {
|
||||||
[m_metalLayer release];
|
[m_metalLayer release];
|
||||||
@ -142,165 +111,45 @@ GHOST_ContextCGL::~GHOST_ContextCGL()
|
|||||||
|
|
||||||
GHOST_TSuccess GHOST_ContextCGL::swapBuffers()
|
GHOST_TSuccess GHOST_ContextCGL::swapBuffers()
|
||||||
{
|
{
|
||||||
GHOST_TSuccess return_value = GHOST_kFailure;
|
if (m_metalView) {
|
||||||
|
metalSwapBuffers();
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
if (m_openGLContext != nil) {
|
|
||||||
if (m_metalView) {
|
|
||||||
metalSwapBuffers();
|
|
||||||
}
|
|
||||||
else if (m_openGLView) {
|
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
[m_openGLContext flushBuffer];
|
|
||||||
[pool drain];
|
|
||||||
}
|
|
||||||
return_value = GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return_value = GHOST_kFailure;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else {
|
return GHOST_kSuccess;
|
||||||
if (m_metalView) {
|
|
||||||
metalSwapBuffers();
|
|
||||||
}
|
|
||||||
return_value = GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_ContextCGL::setSwapInterval(int interval)
|
GHOST_TSuccess GHOST_ContextCGL::setSwapInterval(int interval)
|
||||||
{
|
{
|
||||||
|
mtl_SwapInterval = interval;
|
||||||
if (!m_useMetalForRendering) {
|
return GHOST_kSuccess;
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
if (m_openGLContext != nil) {
|
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
[m_openGLContext setValues:&interval forParameter:NSOpenGLCPSwapInterval];
|
|
||||||
[pool drain];
|
|
||||||
return GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GHOST_kFailure;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mtl_SwapInterval = interval;
|
|
||||||
return GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_ContextCGL::getSwapInterval(int &intervalOut)
|
GHOST_TSuccess GHOST_ContextCGL::getSwapInterval(int &intervalOut)
|
||||||
{
|
{
|
||||||
|
intervalOut = mtl_SwapInterval;
|
||||||
if (!m_useMetalForRendering) {
|
return GHOST_kSuccess;
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
if (m_openGLContext != nil) {
|
|
||||||
GLint interval;
|
|
||||||
|
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
|
|
||||||
[m_openGLContext getValues:&interval forParameter:NSOpenGLCPSwapInterval];
|
|
||||||
|
|
||||||
[pool drain];
|
|
||||||
|
|
||||||
intervalOut = static_cast<int>(interval);
|
|
||||||
|
|
||||||
return GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GHOST_kFailure;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
intervalOut = mtl_SwapInterval;
|
|
||||||
return GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_ContextCGL::activateDrawingContext()
|
GHOST_TSuccess GHOST_ContextCGL::activateDrawingContext()
|
||||||
{
|
{
|
||||||
|
return GHOST_kSuccess;
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
if (m_openGLContext != nil) {
|
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
[m_openGLContext makeCurrentContext];
|
|
||||||
[pool drain];
|
|
||||||
return GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GHOST_kFailure;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_ContextCGL::releaseDrawingContext()
|
GHOST_TSuccess GHOST_ContextCGL::releaseDrawingContext()
|
||||||
{
|
{
|
||||||
|
return GHOST_kSuccess;
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
if (m_openGLContext != nil) {
|
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
[NSOpenGLContext clearCurrentContext];
|
|
||||||
[pool drain];
|
|
||||||
return GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GHOST_kFailure;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int GHOST_ContextCGL::getDefaultFramebuffer()
|
unsigned int GHOST_ContextCGL::getDefaultFramebuffer()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
return m_defaultFramebuffer;
|
|
||||||
}
|
|
||||||
/* NOTE(Metal): This is not valid. */
|
/* NOTE(Metal): This is not valid. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_ContextCGL::updateDrawingContext()
|
GHOST_TSuccess GHOST_ContextCGL::updateDrawingContext()
|
||||||
{
|
{
|
||||||
|
if (m_metalView) {
|
||||||
if (!m_useMetalForRendering) {
|
metalUpdateFramebuffer();
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
return GHOST_kSuccess;
|
||||||
if (m_openGLContext != nil) {
|
|
||||||
if (m_metalView) {
|
|
||||||
metalUpdateFramebuffer();
|
|
||||||
}
|
|
||||||
else if (m_openGLView) {
|
|
||||||
@autoreleasepool {
|
|
||||||
[m_openGLContext update];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GHOST_kFailure;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (m_metalView) {
|
|
||||||
metalUpdateFramebuffer();
|
|
||||||
return GHOST_kSuccess;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return GHOST_kFailure;
|
return GHOST_kFailure;
|
||||||
}
|
}
|
||||||
@ -333,174 +182,11 @@ void GHOST_ContextCGL::metalRegisterPresentCallback(void (*callback)(
|
|||||||
this->contextPresentCallback = callback;
|
this->contextPresentCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void makeAttribList(std::vector<NSOpenGLPixelFormatAttribute> &attribs,
|
|
||||||
bool stereoVisual,
|
|
||||||
bool needAlpha,
|
|
||||||
bool softwareGL,
|
|
||||||
bool increasedSamplerLimit)
|
|
||||||
{
|
|
||||||
attribs.clear();
|
|
||||||
|
|
||||||
attribs.push_back(NSOpenGLPFAOpenGLProfile);
|
|
||||||
attribs.push_back(NSOpenGLProfileVersion3_2Core);
|
|
||||||
|
|
||||||
/* Pixel Format Attributes for the windowed #NSOpenGLContext. */
|
|
||||||
attribs.push_back(NSOpenGLPFADoubleBuffer);
|
|
||||||
|
|
||||||
if (softwareGL) {
|
|
||||||
attribs.push_back(NSOpenGLPFARendererID);
|
|
||||||
attribs.push_back(kCGLRendererGenericFloatID);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
attribs.push_back(NSOpenGLPFAAccelerated);
|
|
||||||
attribs.push_back(NSOpenGLPFANoRecovery);
|
|
||||||
|
|
||||||
/* Attempt to initialize device with extended sampler limit.
|
|
||||||
* Resolves EEVEE purple rendering artifacts on macOS. */
|
|
||||||
if (increasedSamplerLimit) {
|
|
||||||
attribs.push_back((NSOpenGLPixelFormatAttribute)400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stereoVisual)
|
|
||||||
attribs.push_back(NSOpenGLPFAStereo);
|
|
||||||
|
|
||||||
if (needAlpha) {
|
|
||||||
attribs.push_back(NSOpenGLPFAAlphaSize);
|
|
||||||
attribs.push_back((NSOpenGLPixelFormatAttribute)8);
|
|
||||||
}
|
|
||||||
|
|
||||||
attribs.push_back((NSOpenGLPixelFormatAttribute)0);
|
|
||||||
}
|
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
|
GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
if (m_metalView) {
|
||||||
#ifdef GHOST_OPENGL_ALPHA
|
metalInitFramebuffer();
|
||||||
static const bool needAlpha = true;
|
|
||||||
#else
|
|
||||||
static const bool needAlpha = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Command-line argument would be better. */
|
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
/* Command-line argument would be better. */
|
|
||||||
static bool softwareGL = getenv("BLENDER_SOFTWAREGL");
|
|
||||||
|
|
||||||
NSOpenGLPixelFormat *pixelFormat = nil;
|
|
||||||
std::vector<NSOpenGLPixelFormatAttribute> attribs;
|
|
||||||
bool increasedSamplerLimit = false;
|
|
||||||
|
|
||||||
/* Attempt to initialize device with increased sampler limit.
|
|
||||||
* If this is unsupported and initialization fails, initialize GL Context as normal.
|
|
||||||
*
|
|
||||||
* NOTE: This is not available when using the SoftwareGL path, or for Intel-based
|
|
||||||
* platforms. */
|
|
||||||
if (!softwareGL) {
|
|
||||||
if (@available(macos 11.0, *)) {
|
|
||||||
increasedSamplerLimit = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const int max_ctx_attempts = increasedSamplerLimit ? 2 : 1;
|
|
||||||
for (int ctx_create_attempt = 0; ctx_create_attempt < max_ctx_attempts; ctx_create_attempt++)
|
|
||||||
{
|
|
||||||
|
|
||||||
attribs.clear();
|
|
||||||
attribs.reserve(40);
|
|
||||||
makeAttribList(attribs, m_stereoVisual, needAlpha, softwareGL, increasedSamplerLimit);
|
|
||||||
|
|
||||||
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
|
|
||||||
if (pixelFormat == nil) {
|
|
||||||
/* If pixel format creation fails when testing increased sampler limit,
|
|
||||||
* attempt initialization again with feature disabled, otherwise, fail. */
|
|
||||||
if (increasedSamplerLimit) {
|
|
||||||
increasedSamplerLimit = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return GHOST_kFailure;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attempt to create context. */
|
|
||||||
m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
|
|
||||||
shareContext:s_sharedOpenGLContext];
|
|
||||||
[pixelFormat release];
|
|
||||||
|
|
||||||
if (m_openGLContext == nil) {
|
|
||||||
/* If context creation fails when testing increased sampler limit,
|
|
||||||
* attempt re-creation with feature disabled. Otherwise, error. */
|
|
||||||
if (increasedSamplerLimit) {
|
|
||||||
increasedSamplerLimit = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Default context creation attempt failed. */
|
|
||||||
return GHOST_kFailure;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Created GL context successfully, activate. */
|
|
||||||
[m_openGLContext makeCurrentContext];
|
|
||||||
|
|
||||||
/* When increasing sampler limit, verify created context is a supported configuration. */
|
|
||||||
if (increasedSamplerLimit) {
|
|
||||||
const char *vendor = (const char *)glGetString(GL_VENDOR);
|
|
||||||
const char *renderer = (const char *)glGetString(GL_RENDERER);
|
|
||||||
|
|
||||||
/* If generated context type is unsupported, release existing context and
|
|
||||||
* fallback to creating a normal context below. */
|
|
||||||
if (strstr(vendor, "Intel") || strstr(renderer, "Software")) {
|
|
||||||
[m_openGLContext release];
|
|
||||||
m_openGLContext = nil;
|
|
||||||
increasedSamplerLimit = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_debug) {
|
|
||||||
GLint major = 0, minor = 0;
|
|
||||||
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
|
||||||
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
|
||||||
fprintf(stderr, "OpenGL version %d.%d%s\n", major, minor, softwareGL ? " (software)" : "");
|
|
||||||
fprintf(stderr, "Renderer: %s\n", glGetString(GL_RENDERER));
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef GHOST_WAIT_FOR_VSYNC
|
|
||||||
{
|
|
||||||
GLint swapInt = 1;
|
|
||||||
/* Wait for vertical-sync, to avoid tearing artifacts. */
|
|
||||||
[m_openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
if (m_metalView) {
|
|
||||||
if (m_defaultFramebuffer == 0) {
|
|
||||||
/* Create a virtual frame-buffer. */
|
|
||||||
[m_openGLContext makeCurrentContext];
|
|
||||||
metalInitFramebuffer();
|
|
||||||
initClearGL();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (m_openGLView) {
|
|
||||||
[m_openGLView setOpenGLContext:m_openGLContext];
|
|
||||||
[m_openGLContext setView:m_openGLView];
|
|
||||||
initClearGL();
|
|
||||||
}
|
|
||||||
|
|
||||||
[m_openGLContext flushBuffer];
|
|
||||||
|
|
||||||
if (s_sharedCount == 0)
|
|
||||||
s_sharedOpenGLContext = m_openGLContext;
|
|
||||||
|
|
||||||
s_sharedCount++;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* NOTE(Metal): Metal-only path. */
|
|
||||||
if (m_metalView) {
|
|
||||||
metalInitFramebuffer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return GHOST_kSuccess;
|
return GHOST_kSuccess;
|
||||||
@ -508,27 +194,16 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
|
|||||||
|
|
||||||
GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles()
|
GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles()
|
||||||
{
|
{
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
m_openGLContext = nil;
|
|
||||||
m_openGLView = nil;
|
|
||||||
#endif
|
|
||||||
m_metalView = nil;
|
m_metalView = nil;
|
||||||
|
|
||||||
return GHOST_kSuccess;
|
return GHOST_kSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OpenGL on Metal
|
|
||||||
*
|
|
||||||
* Use Metal layer to avoid Viewport lagging on macOS, see #60043. */
|
|
||||||
|
|
||||||
static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT = MTLPixelFormatBGRA8Unorm;
|
static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT = MTLPixelFormatBGRA8Unorm;
|
||||||
static const OSType METAL_CORE_VIDEO_PIXEL_FORMAT = kCVPixelFormatType_32BGRA;
|
|
||||||
|
|
||||||
void GHOST_ContextCGL::metalInit()
|
void GHOST_ContextCGL::metalInit()
|
||||||
{
|
{
|
||||||
/* clang-format off */
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
/* clang-format on */
|
|
||||||
id<MTLDevice> device = m_metalLayer.device;
|
id<MTLDevice> device = m_metalLayer.device;
|
||||||
|
|
||||||
/* Create a command queue for blit/present operation. Note: All context should share a single
|
/* Create a command queue for blit/present operation. Note: All context should share a single
|
||||||
@ -634,213 +309,75 @@ void GHOST_ContextCGL::metalFree()
|
|||||||
|
|
||||||
void GHOST_ContextCGL::metalInitFramebuffer()
|
void GHOST_ContextCGL::metalInitFramebuffer()
|
||||||
{
|
{
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
glGenFramebuffers(1, &m_defaultFramebuffer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
updateDrawingContext();
|
updateDrawingContext();
|
||||||
|
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_defaultFramebuffer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GHOST_ContextCGL::metalUpdateFramebuffer()
|
void GHOST_ContextCGL::metalUpdateFramebuffer()
|
||||||
{
|
{
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
assert(m_defaultFramebuffer != 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
NSRect bounds = [m_metalView bounds];
|
NSRect bounds = [m_metalView bounds];
|
||||||
NSSize backingSize = [m_metalView convertSizeToBacking:bounds.size];
|
NSSize backingSize = [m_metalView convertSizeToBacking:bounds.size];
|
||||||
size_t width = (size_t)backingSize.width;
|
size_t width = (size_t)backingSize.width;
|
||||||
size_t height = (size_t)backingSize.height;
|
size_t height = (size_t)backingSize.height;
|
||||||
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
if (m_defaultFramebufferMetalTexture[current_swapchain_index].texture &&
|
||||||
unsigned int glTex;
|
m_defaultFramebufferMetalTexture[current_swapchain_index].texture.width == width &&
|
||||||
CVPixelBufferRef cvPixelBuffer = nil;
|
m_defaultFramebufferMetalTexture[current_swapchain_index].texture.height == height)
|
||||||
CVOpenGLTextureCacheRef cvGLTexCache = nil;
|
{
|
||||||
CVOpenGLTextureRef cvGLTex = nil;
|
return;
|
||||||
CVMetalTextureCacheRef cvMetalTexCache = nil;
|
}
|
||||||
CVMetalTextureRef cvMetalTex = nil;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!m_useMetalForRendering) {
|
/* Free old texture */
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
[m_defaultFramebufferMetalTexture[current_swapchain_index].texture release];
|
||||||
/* OPENGL path */
|
|
||||||
{
|
|
||||||
/* Test if there is anything to update */
|
|
||||||
id<MTLTexture> tex = m_defaultFramebufferMetalTexture[current_swapchain_index].texture;
|
|
||||||
if (tex && tex.width == width && tex.height == height) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
activateDrawingContext();
|
id<MTLDevice> device = m_metalLayer.device;
|
||||||
|
MTLTextureDescriptor *overlayDesc = [MTLTextureDescriptor
|
||||||
|
texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA16Float
|
||||||
|
width:width
|
||||||
|
height:height
|
||||||
|
mipmapped:NO];
|
||||||
|
overlayDesc.storageMode = MTLStorageModePrivate;
|
||||||
|
overlayDesc.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
||||||
|
|
||||||
NSDictionary *cvPixelBufferProps = @{
|
id<MTLTexture> overlayTex = [device newTextureWithDescriptor:overlayDesc];
|
||||||
(__bridge NSString *)kCVPixelBufferOpenGLCompatibilityKey : @YES,
|
if (!overlayTex) {
|
||||||
(__bridge NSString *)kCVPixelBufferMetalCompatibilityKey : @YES,
|
ghost_fatal_error_dialog(
|
||||||
};
|
"GHOST_ContextCGL::metalUpdateFramebuffer: failed to create Metal overlay texture!");
|
||||||
CVReturn cvret = CVPixelBufferCreate(kCFAllocatorDefault,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
METAL_CORE_VIDEO_PIXEL_FORMAT,
|
|
||||||
(__bridge CFDictionaryRef)cvPixelBufferProps,
|
|
||||||
&cvPixelBuffer);
|
|
||||||
if (cvret != kCVReturnSuccess) {
|
|
||||||
ghost_fatal_error_dialog(
|
|
||||||
"GHOST_ContextCGL::metalUpdateFramebuffer: CVPixelBufferCreate failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create an OpenGL texture. */
|
|
||||||
cvret = CVOpenGLTextureCacheCreate(kCFAllocatorDefault,
|
|
||||||
nil,
|
|
||||||
m_openGLContext.CGLContextObj,
|
|
||||||
m_openGLContext.pixelFormat.CGLPixelFormatObj,
|
|
||||||
nil,
|
|
||||||
&cvGLTexCache);
|
|
||||||
if (cvret != kCVReturnSuccess) {
|
|
||||||
ghost_fatal_error_dialog(
|
|
||||||
"GHOST_ContextCGL::metalUpdateFramebuffer: CVOpenGLTextureCacheCreate failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
cvret = CVOpenGLTextureCacheCreateTextureFromImage(
|
|
||||||
kCFAllocatorDefault, cvGLTexCache, cvPixelBuffer, nil, &cvGLTex);
|
|
||||||
if (cvret != kCVReturnSuccess) {
|
|
||||||
ghost_fatal_error_dialog(
|
|
||||||
"GHOST_ContextCGL::metalUpdateFramebuffer: "
|
|
||||||
"CVOpenGLTextureCacheCreateTextureFromImage failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
glTex = CVOpenGLTextureGetName(cvGLTex);
|
|
||||||
|
|
||||||
/* Create a Metal texture. */
|
|
||||||
cvret = CVMetalTextureCacheCreate(
|
|
||||||
kCFAllocatorDefault, nil, m_metalLayer.device, nil, &cvMetalTexCache);
|
|
||||||
if (cvret != kCVReturnSuccess) {
|
|
||||||
ghost_fatal_error_dialog(
|
|
||||||
"GHOST_ContextCGL::metalUpdateFramebuffer: CVMetalTextureCacheCreate failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
cvret = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
|
|
||||||
cvMetalTexCache,
|
|
||||||
cvPixelBuffer,
|
|
||||||
nil,
|
|
||||||
METAL_FRAMEBUFFERPIXEL_FORMAT,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
0,
|
|
||||||
&cvMetalTex);
|
|
||||||
if (cvret != kCVReturnSuccess) {
|
|
||||||
ghost_fatal_error_dialog(
|
|
||||||
"GHOST_ContextCGL::metalUpdateFramebuffer: "
|
|
||||||
"CVMetalTextureCacheCreateTextureFromImage failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
id<MTLTexture> tex = CVMetalTextureGetTexture(cvMetalTex);
|
|
||||||
|
|
||||||
if (!tex) {
|
|
||||||
ghost_fatal_error_dialog(
|
|
||||||
"GHOST_ContextCGL::metalUpdateFramebuffer: CVMetalTextureGetTexture failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
[m_defaultFramebufferMetalTexture[current_swapchain_index].texture release];
|
|
||||||
m_defaultFramebufferMetalTexture[current_swapchain_index].texture = [tex retain];
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* NOTE(Metal): Metal API Path. */
|
overlayTex.label = [NSString
|
||||||
if (m_defaultFramebufferMetalTexture[current_swapchain_index].texture &&
|
stringWithFormat:@"Metal Overlay for GHOST Context %p", this]; //@"";
|
||||||
m_defaultFramebufferMetalTexture[current_swapchain_index].texture.width == width &&
|
|
||||||
m_defaultFramebufferMetalTexture[current_swapchain_index].texture.height == height)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free old texture */
|
// NSLog(@"Created new Metal Overlay (backbuffer) for context %p\n", this);
|
||||||
[m_defaultFramebufferMetalTexture[current_swapchain_index].texture release];
|
|
||||||
|
|
||||||
id<MTLDevice> device = m_metalLayer.device;
|
|
||||||
MTLTextureDescriptor *overlayDesc = [MTLTextureDescriptor
|
|
||||||
texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA16Float
|
|
||||||
width:width
|
|
||||||
height:height
|
|
||||||
mipmapped:NO];
|
|
||||||
overlayDesc.storageMode = MTLStorageModePrivate;
|
|
||||||
overlayDesc.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
|
||||||
|
|
||||||
id<MTLTexture> overlayTex = [device newTextureWithDescriptor:overlayDesc];
|
|
||||||
if (!overlayTex) {
|
|
||||||
ghost_fatal_error_dialog(
|
|
||||||
"GHOST_ContextCGL::metalUpdateFramebuffer: failed to create Metal overlay texture!");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
overlayTex.label = [NSString
|
|
||||||
stringWithFormat:@"Metal Overlay for GHOST Context %p", this]; //@"";
|
|
||||||
|
|
||||||
// NSLog(@"Created new Metal Overlay (backbuffer) for context %p\n", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_defaultFramebufferMetalTexture[current_swapchain_index].texture =
|
|
||||||
overlayTex; //[(MTLTexture *)overlayTex retain];
|
|
||||||
|
|
||||||
/* Clear texture on create */
|
|
||||||
id<MTLCommandBuffer> cmdBuffer = [s_sharedMetalCommandQueue commandBuffer];
|
|
||||||
MTLRenderPassDescriptor *passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
|
||||||
{
|
|
||||||
auto attachment = [passDescriptor.colorAttachments objectAtIndexedSubscript:0];
|
|
||||||
attachment.texture = m_defaultFramebufferMetalTexture[current_swapchain_index].texture;
|
|
||||||
attachment.loadAction = MTLLoadActionClear;
|
|
||||||
attachment.clearColor = MTLClearColorMake(0.294, 0.294, 0.294, 1.000);
|
|
||||||
attachment.storeAction = MTLStoreActionStore;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
id<MTLRenderCommandEncoder> enc = [cmdBuffer
|
|
||||||
renderCommandEncoderWithDescriptor:passDescriptor];
|
|
||||||
[enc endEncoding];
|
|
||||||
}
|
|
||||||
[cmdBuffer commit];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_useMetalForRendering) {
|
m_defaultFramebufferMetalTexture[current_swapchain_index].texture =
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
overlayTex; //[(MTLTexture *)overlayTex retain];
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_defaultFramebuffer);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, glTex, 0);
|
/* Clear texture on create */
|
||||||
#endif
|
id<MTLCommandBuffer> cmdBuffer = [s_sharedMetalCommandQueue commandBuffer];
|
||||||
|
MTLRenderPassDescriptor *passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
|
{
|
||||||
|
auto attachment = [passDescriptor.colorAttachments objectAtIndexedSubscript:0];
|
||||||
|
attachment.texture = m_defaultFramebufferMetalTexture[current_swapchain_index].texture;
|
||||||
|
attachment.loadAction = MTLLoadActionClear;
|
||||||
|
attachment.clearColor = MTLClearColorMake(0.294, 0.294, 0.294, 1.000);
|
||||||
|
attachment.storeAction = MTLStoreActionStore;
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
id<MTLRenderCommandEncoder> enc = [cmdBuffer
|
||||||
|
renderCommandEncoderWithDescriptor:passDescriptor];
|
||||||
|
[enc endEncoding];
|
||||||
|
}
|
||||||
|
[cmdBuffer commit];
|
||||||
|
|
||||||
[m_metalLayer setDrawableSize:CGSizeMake((CGFloat)width, (CGFloat)height)];
|
[m_metalLayer setDrawableSize:CGSizeMake((CGFloat)width, (CGFloat)height)];
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
CVPixelBufferRelease(cvPixelBuffer);
|
|
||||||
CVOpenGLTextureCacheRelease(cvGLTexCache);
|
|
||||||
CVOpenGLTextureRelease(cvGLTex);
|
|
||||||
CFRelease(cvMetalTexCache);
|
|
||||||
CFRelease(cvMetalTex);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GHOST_ContextCGL::metalSwapBuffers()
|
void GHOST_ContextCGL::metalSwapBuffers()
|
||||||
{
|
{
|
||||||
/* clang-format off */
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
/* clang-format on */
|
|
||||||
updateDrawingContext();
|
updateDrawingContext();
|
||||||
|
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
glFlush();
|
|
||||||
assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
id<CAMetalDrawable> drawable = [m_metalLayer nextDrawable];
|
id<CAMetalDrawable> drawable = [m_metalLayer nextDrawable];
|
||||||
if (!drawable) {
|
if (!drawable) {
|
||||||
return;
|
return;
|
||||||
@ -855,43 +392,11 @@ void GHOST_ContextCGL::metalSwapBuffers()
|
|||||||
attachment.storeAction = MTLStoreActionStore;
|
attachment.storeAction = MTLStoreActionStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_useMetalForRendering) {
|
assert(contextPresentCallback);
|
||||||
id<MTLCommandBuffer> cmdBuffer = [s_sharedMetalCommandQueue commandBuffer];
|
assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil);
|
||||||
{
|
(*contextPresentCallback)(passDescriptor,
|
||||||
assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil);
|
(id<MTLRenderPipelineState>)m_metalRenderPipeline,
|
||||||
id<MTLRenderCommandEncoder> enc = [cmdBuffer
|
m_defaultFramebufferMetalTexture[current_swapchain_index].texture,
|
||||||
renderCommandEncoderWithDescriptor:passDescriptor];
|
drawable);
|
||||||
[enc setRenderPipelineState:(id<MTLRenderPipelineState>)m_metalRenderPipeline];
|
|
||||||
[enc setFragmentTexture:m_defaultFramebufferMetalTexture[current_swapchain_index].texture
|
|
||||||
atIndex:0];
|
|
||||||
[enc drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3];
|
|
||||||
[enc endEncoding];
|
|
||||||
}
|
|
||||||
|
|
||||||
[cmdBuffer presentDrawable:drawable];
|
|
||||||
|
|
||||||
/* Submit command buffer */
|
|
||||||
[cmdBuffer commit];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert(contextPresentCallback);
|
|
||||||
assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil);
|
|
||||||
(*contextPresentCallback)(passDescriptor,
|
|
||||||
(id<MTLRenderPipelineState>)m_metalRenderPipeline,
|
|
||||||
m_defaultFramebufferMetalTexture[current_swapchain_index].texture,
|
|
||||||
drawable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GHOST_ContextCGL::initClear()
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!m_useMetalForRendering) {
|
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
glClearColor(0.294, 0.294, 0.294, 0.000);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
glClearColor(0.000, 0.000, 0.000, 0.000);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(WITH_OPENGL_BACKEND) || defined(WITH_METAL_BACKEND)
|
#ifdef WITH_METAL_BACKEND
|
||||||
# include "GHOST_ContextCGL.hh"
|
# include "GHOST_ContextCGL.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -763,10 +763,11 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
|
|||||||
*/
|
*/
|
||||||
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuSettings)
|
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuSettings)
|
||||||
{
|
{
|
||||||
|
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
|
||||||
|
|
||||||
switch (gpuSettings.context_type) {
|
switch (gpuSettings.context_type) {
|
||||||
#ifdef WITH_VULKAN_BACKEND
|
#ifdef WITH_VULKAN_BACKEND
|
||||||
case GHOST_kDrawingContextTypeVulkan: {
|
case GHOST_kDrawingContextTypeVulkan: {
|
||||||
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
|
|
||||||
GHOST_Context *context = new GHOST_ContextVK(false, NULL, 1, 2, debug_context);
|
GHOST_Context *context = new GHOST_ContextVK(false, NULL, 1, 2, debug_context);
|
||||||
if (context->initializeDrawingContext()) {
|
if (context->initializeDrawingContext()) {
|
||||||
return context;
|
return context;
|
||||||
@ -775,17 +776,11 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuS
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_OPENGL_BACKEND
|
|
||||||
case GHOST_kDrawingContextTypeOpenGL:
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_METAL_BACKEND
|
#ifdef WITH_METAL_BACKEND
|
||||||
case GHOST_kDrawingContextTypeMetal:
|
case GHOST_kDrawingContextTypeMetal: {
|
||||||
#endif
|
|
||||||
#if defined(WITH_OPENGL_BACKEND) || defined(WITH_METAL_BACKEND)
|
|
||||||
{
|
|
||||||
/* TODO(fclem): Remove OpenGL support and rename context to ContextMTL */
|
/* TODO(fclem): Remove OpenGL support and rename context to ContextMTL */
|
||||||
GHOST_Context *context = new GHOST_ContextCGL(
|
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, debug_context);
|
||||||
false, NULL, NULL, NULL, gpuSettings.context_type);
|
|
||||||
if (context->initializeDrawingContext()) {
|
if (context->initializeDrawingContext()) {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,9 @@
|
|||||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "GHOST_ContextCGL.hh"
|
#ifdef WITH_METAL_BACKEND
|
||||||
|
# include "GHOST_ContextCGL.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_VULKAN_BACKEND
|
#ifdef WITH_VULKAN_BACKEND
|
||||||
# include "GHOST_ContextVK.hh"
|
# include "GHOST_ContextVK.hh"
|
||||||
@ -816,37 +818,34 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
|
|||||||
|
|
||||||
GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type)
|
GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type)
|
||||||
{
|
{
|
||||||
|
switch (type) {
|
||||||
#ifdef WITH_VULKAN_BACKEND
|
#ifdef WITH_VULKAN_BACKEND
|
||||||
if (type == GHOST_kDrawingContextTypeVulkan) {
|
case GHOST_kDrawingContextTypeVulkan: {
|
||||||
GHOST_Context *context = new GHOST_ContextVK(m_wantStereoVisual, m_metalLayer, 1, 2, true);
|
GHOST_Context *context = new GHOST_ContextVK(m_wantStereoVisual, m_metalLayer, 1, 2, true);
|
||||||
|
if (context->initializeDrawingContext()) {
|
||||||
if (!context->initializeDrawingContext()) {
|
return context;
|
||||||
|
}
|
||||||
delete context;
|
delete context;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (true
|
#ifdef WITH_METAL_BACKEND
|
||||||
#if defined(WITH_OPENGL_BACKEND)
|
case GHOST_kDrawingContextTypeMetal: {
|
||||||
|| type == GHOST_kDrawingContextTypeOpenGL
|
GHOST_Context *context = new GHOST_ContextCGL(
|
||||||
#elif defined(WITH_METAL_BACKEND)
|
m_wantStereoVisual, m_metalView, m_metalLayer, false);
|
||||||
|| type == GHOST_kDrawingContextTypeMetal
|
if (context->initializeDrawingContext()) {
|
||||||
#endif
|
return context;
|
||||||
)
|
}
|
||||||
{
|
|
||||||
GHOST_Context *context = new GHOST_ContextCGL(
|
|
||||||
m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView, type);
|
|
||||||
|
|
||||||
if (context->initializeDrawingContext())
|
|
||||||
return context;
|
|
||||||
else
|
|
||||||
delete context;
|
delete context;
|
||||||
}
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return NULL;
|
default:
|
||||||
|
/* Unsupported backend. */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark invalidate
|
#pragma mark invalidate
|
||||||
|
@ -611,27 +611,6 @@ class USERPREF_PT_system_cycles_devices(SystemPanel, CenterAlignMixIn, Panel):
|
|||||||
del addon
|
del addon
|
||||||
|
|
||||||
|
|
||||||
class USERPREF_PT_system_gpu_backend(SystemPanel, CenterAlignMixIn, Panel):
|
|
||||||
bl_label = "GPU Backend"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, _context):
|
|
||||||
# Only for Apple so far
|
|
||||||
import sys
|
|
||||||
return sys.platform == "darwin"
|
|
||||||
|
|
||||||
def draw_centered(self, context, layout):
|
|
||||||
import gpu
|
|
||||||
prefs = context.preferences
|
|
||||||
system = prefs.system
|
|
||||||
|
|
||||||
col = layout.column()
|
|
||||||
col.prop(system, "gpu_backend")
|
|
||||||
|
|
||||||
if system.gpu_backend != gpu.platform.backend_type_get():
|
|
||||||
layout.label(text="Requires a restart of Blender to take effect", icon='INFO')
|
|
||||||
|
|
||||||
|
|
||||||
class USERPREF_PT_system_os_settings(SystemPanel, CenterAlignMixIn, Panel):
|
class USERPREF_PT_system_os_settings(SystemPanel, CenterAlignMixIn, Panel):
|
||||||
bl_label = "Operating System Settings"
|
bl_label = "Operating System Settings"
|
||||||
|
|
||||||
@ -2525,7 +2504,6 @@ classes = (
|
|||||||
USERPREF_PT_animation_fcurves,
|
USERPREF_PT_animation_fcurves,
|
||||||
|
|
||||||
USERPREF_PT_system_cycles_devices,
|
USERPREF_PT_system_cycles_devices,
|
||||||
USERPREF_PT_system_gpu_backend,
|
|
||||||
USERPREF_PT_system_os_settings,
|
USERPREF_PT_system_os_settings,
|
||||||
USERPREF_PT_system_memory,
|
USERPREF_PT_system_memory,
|
||||||
USERPREF_PT_system_video_sequencer,
|
USERPREF_PT_system_video_sequencer,
|
||||||
|
@ -845,6 +845,13 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Keep this block, even when empty. */
|
/* Keep this block, even when empty. */
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
/* Drop OpenGL support on MAC devices as they don't support OpenGL 4.3. */
|
||||||
|
if (userdef->gpu_backend == GPU_BACKEND_OPENGL) {
|
||||||
|
userdef->gpu_backend = GPU_BACKEND_METAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) {
|
LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) {
|
||||||
|
@ -219,9 +219,6 @@ void GPU_render_step()
|
|||||||
/** \name Backend selection
|
/** \name Backend selection
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
/* NOTE: To enable Metal API, we need to temporarily change this to `GPU_BACKEND_METAL`.
|
|
||||||
* Until a global switch is added, Metal also needs to be enabled in GHOST_ContextCGL:
|
|
||||||
* `m_useMetalForRendering = true`. */
|
|
||||||
static eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL;
|
static eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL;
|
||||||
static std::optional<eGPUBackendType> g_backend_type_override = std::nullopt;
|
static std::optional<eGPUBackendType> g_backend_type_override = std::nullopt;
|
||||||
static std::optional<bool> g_backend_type_supported = std::nullopt;
|
static std::optional<bool> g_backend_type_supported = std::nullopt;
|
||||||
@ -255,13 +252,11 @@ bool GPU_backend_type_selection_detect()
|
|||||||
backends_to_check.append(*g_backend_type_override);
|
backends_to_check.append(*g_backend_type_override);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#if defined(WITH_OPENGL_BACKEND)
|
||||||
backends_to_check.append(GPU_BACKEND_OPENGL);
|
backends_to_check.append(GPU_BACKEND_OPENGL);
|
||||||
}
|
#elif defined(WITH_METAL_BACKEND)
|
||||||
|
backends_to_check.append(GPU_BACKEND_METAL);
|
||||||
/* Add fallback to OpenGL when Metal backend is requested on a platform that doesn't support
|
#endif
|
||||||
* metal. */
|
|
||||||
if (backends_to_check[0] == GPU_BACKEND_METAL) {
|
|
||||||
backends_to_check.append(GPU_BACKEND_OPENGL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const eGPUBackendType backend_type : backends_to_check) {
|
for (const eGPUBackendType backend_type : backends_to_check) {
|
||||||
|
Loading…
Reference in New Issue
Block a user