OpenGL: software renderer for old Mac GPUs
We raised the minimum to GL 2.1 in Blender 2.77, and dropped support for older GPUs (pre-2012 Intel mostly). On Windows you get a popup message, but on Mac we simply crashed. Every Mac has a builtin software renderer for GL 2.1 so let's use that when the GPU is not capable! Run blender --debug-gpu to see version detection & software fallback.
This commit is contained in:
parent
16ed49b26e
commit
e12f5b699d
|
@ -136,6 +136,8 @@ private:
|
|||
|
||||
//static CGLEWContext *s_cglewContext;
|
||||
|
||||
const bool m_debug;
|
||||
|
||||
/** The first created OpenGL context (for sharing display lists) */
|
||||
static NSOpenGLContext *s_sharedOpenGLContext;
|
||||
static int s_sharedCount;
|
||||
|
|
|
@ -59,7 +59,8 @@ GHOST_ContextCGL::GHOST_ContextCGL(
|
|||
int contextResetNotificationStrategy)
|
||||
: GHOST_Context(stereoVisual, numOfAASamples),
|
||||
m_openGLView(openGLView),
|
||||
m_openGLContext(nil)
|
||||
m_openGLContext(nil),
|
||||
m_debug(contextFlags)
|
||||
{
|
||||
assert(openGLView != nil);
|
||||
}
|
||||
|
@ -172,20 +173,21 @@ static void makeAttribList(
|
|||
bool stereoVisual,
|
||||
int numOfAASamples,
|
||||
bool needAlpha,
|
||||
bool needStencil)
|
||||
bool needStencil,
|
||||
bool softwareGL)
|
||||
{
|
||||
attribs.clear();
|
||||
|
||||
// Pixel Format Attributes for the windowed NSOpenGLContext
|
||||
attribs.push_back(NSOpenGLPFADoubleBuffer);
|
||||
|
||||
// Force software OpenGL, for debugging
|
||||
/* XXX jwilkins: fixed this to work on Intel macs? useful feature for Windows and Linux too?
|
||||
* Maybe a command line flag is better... */
|
||||
if (getenv("BLENDER_SOFTWAREGL")) {
|
||||
if (softwareGL) {
|
||||
attribs.push_back(NSOpenGLPFARendererID);
|
||||
attribs.push_back(kCGLRendererGenericFloatID);
|
||||
}
|
||||
else {
|
||||
attribs.push_back(NSOpenGLPFAAccelerated);
|
||||
attribs.push_back(NSOpenGLPFANoRecovery);
|
||||
}
|
||||
|
||||
/* Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway */
|
||||
|
@ -219,13 +221,21 @@ static void makeAttribList(
|
|||
|
||||
attribs.push_back(NSOpenGLPFASamples);
|
||||
attribs.push_back((NSOpenGLPixelFormatAttribute) numOfAASamples);
|
||||
|
||||
attribs.push_back(NSOpenGLPFANoRecovery);
|
||||
}
|
||||
|
||||
attribs.push_back((NSOpenGLPixelFormatAttribute) 0);
|
||||
}
|
||||
|
||||
// TODO(merwin): make this available to all platforms
|
||||
static void getVersion(int *major, int *minor)
|
||||
{
|
||||
#if 1 // legacy GL
|
||||
sscanf((const char*)glGetString(GL_VERSION), "%d.%d", major, minor);
|
||||
#else // 3.0+
|
||||
glGetIntegerv(GL_MAJOR_VERSION, major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, minor);
|
||||
#endif
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
|
||||
{
|
||||
|
@ -248,9 +258,12 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
|
|||
static const bool needStencil = false;
|
||||
#endif
|
||||
|
||||
makeAttribList(attribs, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil);
|
||||
|
||||
static bool softwareGL = getenv("BLENDER_SOFTWAREGL"); // command-line argument would be better
|
||||
GLint major = 0, minor = 0;
|
||||
NSOpenGLPixelFormat *pixelFormat;
|
||||
// TODO: keep pixel format for subsequent windows/contexts instead of recreating each time
|
||||
|
||||
makeAttribList(attribs, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
|
||||
|
||||
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
|
||||
|
||||
|
@ -261,7 +274,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
|
|||
// (Now that I think about it, does WGL really require the code that it has for finding a lesser match?)
|
||||
|
||||
attribs.clear();
|
||||
makeAttribList(attribs, m_stereoVisual, 0, needAlpha, needStencil);
|
||||
makeAttribList(attribs, m_stereoVisual, 0, needAlpha, needStencil, softwareGL);
|
||||
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
|
||||
}
|
||||
|
||||
|
@ -282,25 +295,47 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
|
|||
}
|
||||
}
|
||||
|
||||
[m_openGLView setPixelFormat:pixelFormat];
|
||||
m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext];
|
||||
[pixelFormat release];
|
||||
|
||||
m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext]; // +1 refCount to pixelFormat
|
||||
[m_openGLContext makeCurrentContext];
|
||||
|
||||
if (m_openGLContext == nil)
|
||||
goto error;
|
||||
getVersion(&major, &minor);
|
||||
if (m_debug) {
|
||||
fprintf(stderr, "OpenGL version %d.%d%s\n", major, minor, softwareGL ? " (software)" : "");
|
||||
fprintf(stderr, "Renderer: %s\n", glGetString(GL_RENDERER));
|
||||
}
|
||||
|
||||
if (s_sharedCount == 0)
|
||||
s_sharedOpenGLContext = m_openGLContext;
|
||||
|
||||
[pixelFormat release]; // -1 refCount to pixelFormat
|
||||
|
||||
s_sharedCount++;
|
||||
if (major < 2 || (major == 2 && minor < 1)) {
|
||||
// fall back to software renderer if GL < 2.1
|
||||
fprintf(stderr, "OpenGL 2.1 is not supported on your hardware, falling back to software");
|
||||
softwareGL = true;
|
||||
|
||||
// discard hardware GL context
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
[m_openGLContext release];
|
||||
|
||||
// create software GL context
|
||||
makeAttribList(attribs, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
|
||||
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
|
||||
m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext];
|
||||
[pixelFormat release];
|
||||
|
||||
[m_openGLContext makeCurrentContext];
|
||||
|
||||
getVersion(&major, &minor);
|
||||
if (m_debug) {
|
||||
fprintf(stderr, "OpenGL version %d.%d%s\n", major, minor, softwareGL ? " (software)" : "");
|
||||
fprintf(stderr, "Renderer: %s\n", glGetString(GL_RENDERER));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GHOST_MULTITHREADED_OPENGL
|
||||
//Switch openGL to multhreaded mode
|
||||
CGLContextObj cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj];
|
||||
if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError)
|
||||
printf("\nSwitched openGL to multithreaded mode\n");
|
||||
if (m_debug)
|
||||
fprintf(stderr, "\nSwitched OpenGL to multithreaded mode\n");
|
||||
#endif
|
||||
|
||||
#ifdef GHOST_WAIT_FOR_VSYNC
|
||||
|
@ -311,10 +346,16 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
|
|||
}
|
||||
#endif
|
||||
|
||||
initContextGLEW();
|
||||
|
||||
[m_openGLView setOpenGLContext:m_openGLContext];
|
||||
[m_openGLContext setView:m_openGLView];
|
||||
|
||||
initContextGLEW();
|
||||
if (s_sharedCount == 0)
|
||||
s_sharedOpenGLContext = m_openGLContext;
|
||||
|
||||
s_sharedCount++;
|
||||
|
||||
|
||||
initClearGL();
|
||||
[m_openGLContext flushBuffer];
|
||||
|
|
|
@ -562,7 +562,7 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
|
|||
// Add contentRect.origin.y to respect docksize
|
||||
bottom = bottom > contentRect.origin.y ? bottom + contentRect.origin.y : contentRect.origin.y;
|
||||
|
||||
window = new GHOST_WindowCocoa (this, title, left, bottom, width, height, state, type, ((glSettings.flags & GHOST_glStereoVisual) != 0), glSettings.numOfAASamples);
|
||||
window = new GHOST_WindowCocoa(this, title, left, bottom, width, height, state, type, glSettings.flags & GHOST_glStereoVisual, glSettings.numOfAASamples, glSettings.flags & GHOST_glDebugContext);
|
||||
|
||||
if (window->getValid()) {
|
||||
// Store the pointer to the window
|
||||
|
|
|
@ -74,7 +74,8 @@ public:
|
|||
GHOST_TWindowState state,
|
||||
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
|
||||
const bool stereoVisual = false,
|
||||
const GHOST_TUns16 numOfAASamples = 0
|
||||
const GHOST_TUns16 numOfAASamples = 0,
|
||||
bool is_debug = false
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -305,6 +306,7 @@ protected:
|
|||
bool m_lionStyleFullScreen;
|
||||
|
||||
bool m_immediateDraw;
|
||||
bool m_debug_context; // for debug messages during context setup
|
||||
};
|
||||
|
||||
#endif // __GHOST_WINDOWCOCOA_H__
|
||||
|
|
|
@ -528,10 +528,11 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
|
|||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_TDrawingContextType type,
|
||||
const bool stereoVisual, const GHOST_TUns16 numOfAASamples
|
||||
const bool stereoVisual, const GHOST_TUns16 numOfAASamples, bool is_debug
|
||||
) :
|
||||
GHOST_Window(width, height, state, stereoVisual, false, numOfAASamples),
|
||||
m_customCursor(0)
|
||||
m_customCursor(0),
|
||||
m_debug_context(is_debug)
|
||||
{
|
||||
m_systemCocoa = systemCocoa;
|
||||
m_fullScreen = false;
|
||||
|
@ -1115,7 +1116,7 @@ GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType ty
|
|||
m_openGLView,
|
||||
0, // profile bit
|
||||
0, 0,
|
||||
GHOST_OPENGL_CGL_CONTEXT_FLAGS,
|
||||
m_debug_context,
|
||||
GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
|
||||
#else
|
||||
# error
|
||||
|
|
Loading…
Reference in New Issue