How to create an OpenGL context on an NodeJS native addon on MacOS?

2.5k Views Asked by At

Follow-up for this question.

I'm trying to create a NodeJS native addon that uses OpenGL.

I'm not able to use OpenGL functions because CGLGetCurrentContext() always returns NULL.

When trying to create a new context to draw into, CGLChoosePixelFormat always returns the error kCGLBadConnection invalid CoreGraphics connection.

What is bugging me out is that when I isolate the code that creates the OpenGL context into a standalone CPP project, it works! It just gives an error when I run it inside the NodeJS addon!

I created this NodeJS native addon project to exemplify my error: https://github.com/Psidium/node-opengl-context-error-example

This is the code that works when executed on a standalone project and errors out when running inside NodeJS:

//
//  main.cpp
//  test_cli
//
//  Created by Borges, Gabriel on 4/3/20.
//  Copyright © 2020 Psidium. All rights reserved.
//

#include <iostream>
#include <OpenGL/OpenGL.h>

int main(int argc, const char * argv[]) {
    std::cout << "Context before creating it: " << CGLGetCurrentContext() << "\n";
       CGLContextObj context;
    CGLPixelFormatAttribute attributes[2] = {
            kCGLPFAAccelerated,   // no software rendering
            (CGLPixelFormatAttribute) 0
    };
    CGLPixelFormatObj pix;
    CGLError errorCode;
    GLint num; // stores the number of possible pixel formats
    errorCode = CGLChoosePixelFormat( attributes, &pix, &num );
    if (errorCode > 0) {
      std::cout << ": Error returned by choosePixelFormat: " << errorCode << "\n";
        return 10;
    }

    errorCode = CGLCreateContext( pix, NULL, &context );
    if (errorCode > 0) {
      std::cout << ": Error returned by CGLCreateContext: " << errorCode << "\n";
      return 10 ;
    }

    CGLDestroyPixelFormat( pix );

    errorCode = CGLSetCurrentContext( context );
    if (errorCode > 0) {
      std::cout << "Error returned by CGLSetCurrentContext: " << errorCode << "\n";
      return 10;
    }
    std::cout << "Context after being created is: " << CGLGetCurrentContext() << "\n";
    return 0;
}

I already tried:

  • Using fork() to create a context in a subprocess (didn't work);
  • Changing the pixelformat attributes to something that will create my context (didn't work);

I have a hunch that it may have something to do with the fact that a Node native addon is a dynamically linked library, or maybe my OpenGL createContext function may not be executing on the main thread (but if this was the case, the fork() would have solved it, right?).

1

There are 1 best solutions below

0
On

Accessing graphics hardware requires extra permissions - Windows and macOS (don't know for others) restrict creation of hardware-accelerated OpenGL context to interactive user session (I may be wrong with the terms here). From one of articles on the web:

In case the user is not logged in, the CGLChoosePixelFormat will return kCGLBadConnection

Interactive session is easier to feel than to understand; e.g. when you interactively login and launch application - it is interactive session; when process is started as service - it is non-interactive. How this is actually managed by system requires deeper reading. As far as I know, there is no easy way "escaping" non-interactive process flag.

NodeJS can be used as part of a web-server, so that I may expect that it can be exactly the problem - it is started as a service, by another non-interactive user or has other special conditions making it non-interactive. So maybe more details on how you use / start NodeJS itself might clarify why the code doesn't work. But I may expect that using OpenGL on server part might be not a good idea anyway (if this is a target); although it might be possible that software OpenGL implementation (without kCGLPFAAccelerated flag might work).

By the way, there are at least two OpenGL / WebGL extensions to NodeJS - have you tried their samples to see if they behave in the same or different way in your environment? https://github.com/google/node-gles https://github.com/mikeseven/node-webgl