/* This is the main entry point for Matlab or Octave. It gets called by Matlab or Octave, handles first-time initialization, error handling and subfunction dispatching. */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // Start of dispatcher: int i; GLenum err; // see whether there's a string command if(nrhs<1 || !mxIsChar(prhs[0])) mogl_usageerr(); // get string command mxGetString(prhs[0],cmd,CMDLEN); // Special case. If we're called with the special command "PREINIT", then // we return immediately. moglcore('PREINIT') is called by ptbmoglinit.m // on M$-Windows in order to preload the moglcore Mex-file into Matlab while // the current working directory is set to ..MOGL/core/ . This way, the dynamic // linker can find our own local version of glut32.dll and link it against moglcore. // Without this trick, we would need to install glut32.dll into the Windows system // folder which requires admin privileges and makes installation of Psychtoolbox // more complicated on M$-Windows... if (strcmp(cmd, "PREINIT")==0) { glBeginLevel=0; goto moglreturn; } if (strcmp(cmd, "DUMMYMODE")==0) { if (nrhs<2 || mxGetScalar(prhs[1])<0) { mexErrMsgTxt("MOGL-ERROR: No dummy mode level or invalid level (<0) given for subcommand DUMMYMODE!"); } dummymode = (int) mxGetScalar(prhs[1]); if (dummymode>0) printf("MOGL-INFO: Switched to dummy mode level %i.\n", dummymode); goto moglreturn; } // Special command to set MOGL debug level: // debuglevel = 0 --> Shut up in any case, leave error-handling to higher-level code. // debuglevel > 0 --> Check for OpenGL error conditions. // debuglevel > 0 --> Output glError()'s in clear-text and abort. Output GLSL errors and abort. // debuglevel > 1 --> Output GLSL diagnostic messages as well. // debuglevel > 2 --> Be very verbose! if (strcmp(cmd, "DEBUGLEVEL")==0) { if (nrhs<2 || mxGetScalar(prhs[1])<0) { mexErrMsgTxt("MOGL-ERROR: No debuglevel or invalid debuglevel (<0) given for subcommand DEBUGLEVEL!"); } debuglevel = (int) mxGetScalar(prhs[1]); goto moglreturn; } // Special cleanup subcommand needed for GNU/Octave: See explanation below in firstTime init. if (strcmp(cmd, "JettisonModuleHelper")==0) { goto moglreturn; } // Abort here if dummymode >= 10: Input arg. processing run, but no real // command parsing and processing; if (dummymode >= 10) { printf("MOGL-INFO: Dummy call to %s() - Ignored in dummy mode %i ...\n", cmd, dummymode); goto moglreturn; } #ifdef BUILD_GLM // GLM module is included and supported in moglcore: This is necessary if // one wants to use MOGL independent from Psychtoolbox. GLM is only supported // on MacOS-X, not on Linux or Windows... // We execute glm-commands without performing GLEW first-time initialization, // because to execute glewinit() we need a valid OpenGL context. This context is // either created by Psychtoolbox or by glm. Therefore glm-commands must be able // to execute before glewinit() happened. // look for command in glm command map if( (i=binsearch(glm_map,glm_map_count,cmd))>=0 ) { glm_map[i].cmdfn(nlhs,plhs,nrhs-1,prhs+1); goto moglreturn; } #endif // Is this the first invocation of moglcore? if (firsttime) { // Yes. Initialize GLEW, the GL Extension Wrangler Library. This will // auto-detect and dynamically link/bind all core OpenGL functionality // as well as all possible OpenGL extensions on OS-X, Linux and Windows. err = glewInit(); if (GLEW_OK != err) { // Failed! Something is seriously wrong - We have to abort :( printf("MOGL: Failed to initialize! Probably you called an OpenGL command *before* opening an onscreen window?!?\n"); printf("GLEW reported the following error: %s\n", glewGetErrorString(err)); fflush(NULL); goto moglreturn; } // Success. Ready to go... if (debuglevel > 1) { printf("MOGL - OpenGL for Matlab & GNU/Octave initialized. MOGL is (c) 2006-2011 Richard F. Murray & Mario Kleiner, licensed to you under MIT license.\n"); printf("Some additional restrictions apply to redistribution of binary MEX files for Matlab due to the terms of the Mathworks Matlab license.\n"); printf("See file 'License.txt' in the Psychtoolbox root folder for the exact licensing conditions.\n"); } fflush(NULL); // Perform dynamic rebinding of ARB extensions to core functions, if necessary: mogl_rebindARBExtensionsToCore(); #ifdef FREEGLUT // FreeGlut must be initialized, otherwise it will emergency abort the whole application! int noargs = 1; char dummyarg[] = "ptbmoglcore"; char *dummyargp = &dummyarg[0]; glutInit( &noargs, &dummyargp); #endif // Register exit-handler: When flushing the mex-file, we free all allocated buffer memory: mexAtExit(&mexExitFunction); // Done with first time initialization: firsttime = 0; } // If glBeginLevel > 1 then most probably the script was aborted after execution of glBegin() but // before execution of glEnd(). In that case, we reset the level to zero. if (glBeginLevel > 1) glBeginLevel = 0; // Reset OpenGL error state so we can be sure that any of our error queries really // relate to errors caused by us: if (glBeginLevel == 0 && debuglevel > 0 && (strstr(cmd, "glGetError")==NULL)) glGetError(); // look for command in manual command map if( (i=binsearch(gl_manual_map,gl_manual_map_count,cmd))>=0 ) { gl_manual_map[i].cmdfn(nlhs,plhs,nrhs-1,(const mxArray**) prhs+1); if (debuglevel > 0) mogl_checkerrors(cmd, prhs); goto moglreturn; } // look for command in auto command map if( (i=binsearch(gl_auto_map,gl_auto_map_count,cmd))>=0 ) { gl_auto_map[i].cmdfn(nlhs,plhs,nrhs-1,(const mxArray**) prhs+1); if (debuglevel > 0) mogl_checkerrors(cmd, prhs); goto moglreturn; } // no match mogl_usageerr(); // moglreturn: Is the exit path of mogl. All execution ends at this point. moglreturn: return; }
/* This is the main entry point for Matlab or Octave. It gets called by Matlab or Octave, handles first-time initialization, error handling and subfunction dispatching. */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // Start of dispatcher: int i; GLenum err; // FreeGlut must be initialized, otherwise it will emergency abort the whole application. // These variables are needed for it: int noargs = 1; char dummyarg[] = "ptbmoglcore"; char *dummyargp = &dummyarg[0]; // see whether there's a string command if(nrhs<1 || !mxIsChar(prhs[0])) mogl_usageerr(); // get string command mxGetString(prhs[0],cmd,CMDLEN); // Special case. If we're called with the special command "PREINIT", then // we return immediately. moglcore('PREINIT') is called by ptbmoglinit.m // on M$-Windows in order to preload the moglcore Mex-file into Matlab while // the current working directory is set to ..MOGL/core/ . This way, the dynamic // linker can find our own local version of glut32.dll and link it against moglcore. // Without this trick, we would need to install glut32.dll into the Windows system // folder which requires admin privileges and makes installation of Psychtoolbox // more complicated on M$-Windows... if (strcmp(cmd, "PREINIT")==0) { glBeginLevel=0; goto moglreturn; } if (strcmp(cmd, "DUMMYMODE")==0) { if (nrhs<2 || mxGetScalar(prhs[1])<0) { mexErrMsgTxt("MOGL-ERROR: No dummy mode level or invalid level (<0) given for subcommand DUMMYMODE!"); } dummymode = (int) mxGetScalar(prhs[1]); if (dummymode>0) printf("MOGL-INFO: Switched to dummy mode level %i.\n", dummymode); goto moglreturn; } // Special command to set MOGL debug level: // debuglevel = 0 --> Shut up in any case, leave error-handling to higher-level code. // debuglevel > 0 --> Check for OpenGL error conditions. // debuglevel > 0 --> Output glError()'s in clear-text and abort. Output GLSL errors and abort. // debuglevel > 1 --> Output GLSL diagnostic messages as well. // debuglevel > 2 --> Be very verbose! if (strcmp(cmd, "DEBUGLEVEL")==0) { if (nrhs<2 || mxGetScalar(prhs[1])<0) { mexErrMsgTxt("MOGL-ERROR: No debuglevel or invalid debuglevel (<0) given for subcommand DEBUGLEVEL!"); } debuglevel = (int) mxGetScalar(prhs[1]); goto moglreturn; } // Special cleanup subcommand needed for GNU/Octave: See explanation below in firstTime init. if (strcmp(cmd, "JettisonModuleHelper")==0) { goto moglreturn; } // Abort here if dummymode >= 10: Input arg. processing run, but no real // command parsing and processing; if (dummymode >= 10) { printf("MOGL-INFO: Dummy call to %s() - Ignored in dummy mode %i ...\n", cmd, dummymode); goto moglreturn; } #ifdef BUILD_GLM // GLM module is included and supported in moglcore: This is necessary if // one wants to use MOGL independent from Psychtoolbox. GLM is only supported // on MacOS-X, not on Linux or Windows... // We execute glm-commands without performing GLEW first-time initialization, // because to execute glewinit() we need a valid OpenGL context. This context is // either created by Psychtoolbox or by glm. Therefore glm-commands must be able // to execute before glewinit() happened. // look for command in glm command map if( (i=binsearch(glm_map,glm_map_count,cmd))>=0 ) { glm_map[i].cmdfn(nlhs,plhs,nrhs-1,prhs+1); goto moglreturn; } #endif // Is this the first invocation of moglcore? if (firsttime) { // Yes. Initialize GLEW, the GL Extension Wrangler Library. This will // auto-detect and dynamically link/bind all core OpenGL functionality // as well as all possible OpenGL extensions on OS-X, Linux and Windows. err = GLEW_OK; #ifdef PTB_USE_WAFFLE // Linux is special: If we use the Waffle backend for display system binding, then our display backend // may be something else than GLX (e.g., X11/EGL, Wayland/EGL, GBM/EGL, ANDROID/EGL etc.), in which case // glewInit() would not work and would crash hard. Detect if we're on classic Linux or Linux with X11/GLX. // If so, execute glewInit(), otherwise call glewContextInit() - a routine which skips GLX specific setup, // therefore only initializes the non-GLX parts. We need a hacked glew.c for this function to be available, // as original upstream GLEW makes that function private (static): if (!getenv("PSYCH_USE_DISPLAY_BACKEND") || strstr(getenv("PSYCH_USE_DISPLAY_BACKEND"), "glx")) { // Classic backend or GLX backend: The full show. err = glewInit(); } else { // Non-GLX backend, probably EGL: Reduced show. err = glewContextInit(); } #else // Other os'es, or Linux without Waffle backend: Always init GLEW: err = glewInit(); #endif if (GLEW_OK != err) { // Failed! Something is seriously wrong - We have to abort :( printf("MOGL: Failed to initialize! Probably you called an OpenGL command *before* opening an onscreen window?!?\n"); printf("GLEW reported the following error: %s\n", glewGetErrorString(err)); fflush(NULL); goto moglreturn; } // Success. Ready to go... if (debuglevel > 1) { printf("MOGL - OpenGL for Matlab & GNU/Octave initialized. MOGL is (c) 2006-2013 Richard F. Murray & Mario Kleiner, licensed to you under MIT license.\n"); #ifdef WINDOWS printf("On MS-Windows, we make use of the freeglut library, which is Copyright (c) 1999-2000 Pawel W. Olszta, licensed under compatible MIT/X11 license.\n"); printf("The precompiled Windows binary DLL's have been kindly provided by http://www.transmissionzero.co.uk/software/freeglut-devel/ -- Thanks!\n"); #endif printf("See file 'License.txt' in the Psychtoolbox root folder for the exact licensing conditions.\n"); } fflush(NULL); // Perform dynamic rebinding of ARB extensions to core functions, if necessary: mogl_rebindARBExtensionsToCore(); #ifdef FREEGLUT // FreeGlut must be initialized, otherwise it will emergency abort the whole application. // However, we skip init if we're on a setup without GLX display backend, as this would // abort us due to lack of GLX. On non-GLX we simply can't use FreeGlut at all. if (!getenv("PSYCH_USE_DISPLAY_BACKEND") || strstr(getenv("PSYCH_USE_DISPLAY_BACKEND"), "glx")) { // GLX display backend - Init and use FreeGlut: glutInit( &noargs, &dummyargp); } #endif // Running on a OpenGL-ES rendering api under Linux? if (getenv("PSYCH_USE_GFX_BACKEND") && strstr(getenv("PSYCH_USE_GFX_BACKEND"), "gles")) { // Yes. We emulate some immediate mode rendering commands, which aren't available // in OpenGL Embedded Subset at all, via "our" own emulation code. This code emulates // immediate mode on top of client vertex arrays and batch submission. if (debuglevel > 1) { printf("OpenGL-ES rendering API active: Emulating immediate mode rendering via David Petrie's ftglesGlue emulation code.\n"); } } // Register exit-handler: When flushing the mex-file, we free all allocated buffer memory: mexAtExit(&mexExitFunction); // Done with first time initialization: firsttime = 0; } // If glBeginLevel > 1 then most probably the script was aborted after execution of glBegin() but // before execution of glEnd(). In that case, we reset the level to zero. if (glBeginLevel > 1) glBeginLevel = 0; // Reset OpenGL error state so we can be sure that any of our error queries really // relate to errors caused by us: if (glBeginLevel == 0 && debuglevel > 0 && (strstr(cmd, "glGetError")==NULL)) glGetError(); // look for command in manual command map if( (i=binsearch(gl_manual_map,gl_manual_map_count,cmd))>=0 ) { gl_manual_map[i].cmdfn(nlhs,plhs,nrhs-1,(const mxArray**) prhs+1); if (debuglevel > 0) mogl_checkerrors(cmd, prhs); goto moglreturn; } // look for command in auto command map if( (i=binsearch(gl_auto_map,gl_auto_map_count,cmd))>=0 ) { gl_auto_map[i].cmdfn(nlhs,plhs,nrhs-1,(const mxArray**) prhs+1); if (debuglevel > 0) mogl_checkerrors(cmd, prhs); goto moglreturn; } // no match mogl_usageerr(); // moglreturn: Is the exit path of mogl. All execution ends at this point. moglreturn: return; }