Commit: e12f5b699d5a2eea045b584ebc7264bddcfb994d
Author: Mike Erwin
Date:   Mon Sep 19 20:26:55 2016 +0200
Branches: master
https://developer.blender.org/rBe12f5b699d5a2eea045b584ebc7264bddcfb994d

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.

===================================================================

M       intern/ghost/intern/GHOST_ContextCGL.h
M       intern/ghost/intern/GHOST_ContextCGL.mm
M       intern/ghost/intern/GHOST_SystemCocoa.mm
M       intern/ghost/intern/GHOST_WindowCocoa.h
M       intern/ghost/intern/GHOST_WindowCocoa.mm

===================================================================

diff --git a/intern/ghost/intern/GHOST_ContextCGL.h 
b/intern/ghost/intern/GHOST_ContextCGL.h
index 9532356..dd49b81 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.h
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -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;
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm 
b/intern/ghost/intern/GHOST_ContextCGL.mm
index e09de4b..03c45f9 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -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];
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm 
b/intern/ghost/intern/GHOST_SystemCocoa.mm
index b0d5ab3..f31cba4 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -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
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h 
b/intern/ghost/intern/GHOST_WindowCocoa.h
index 3ed8808..b234291 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -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__
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm 
b/intern/ghost/intern/GHOST_WindowCocoa.mm
index e23cf9c..97615dc 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -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

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to