// Perform OS specific processing of Window events: void PsychOSProcessEvents(PsychWindowRecordType *windowRecord, int flags) { Rect globalBounds; // Trigger event queue dispatch processing for GUI windows: if (windowRecord == NULL) { // No op, so far... return; } // GUI windows need to behave GUIyee: if ((windowRecord->specialflags & kPsychGUIWindow) && PsychIsOnscreenWindow(windowRecord)) { // Update windows rect and globalrect, based on current size and location: PsychCocoaGetWindowBounds(windowRecord->targetSpecific.windowHandle, windowRecord->globalrect, windowRecord->rect); PsychSetupClientRect(windowRecord); PsychSetupView(windowRecord, FALSE); } }
PsychError SCREENBeginOpenGL(void) { static char useString[] = "Screen('BeginOpenGL', windowPtr [, sharecontext=0]);"; static char synopsisString[] = "Prepare window 'windowPtr' for OpenGL rendering by external OpenGL code. " "This allows to use OpenGL drawing routines other than the ones implemented " "in Screen() to draw to a Psychtoolbox onscreen- or offscreen window via execution of " "OpenGL commands. Typical clients of this function are mogl (Richard F. Murrays OpenGL for Matlab wrapper), " "the new Eyelink-Toolbox and third party Matlab Mex-Files which contain OpenGL rendering routines. " "You *have to* call this command once before using any of those external drawing commands for the window. " "After drawing, you *must* switch back to PTB's rendering via the Screen('EndOpenGL', windowPtr); command. " "Normally, you won't provide the optional flag 'sharecontext', so PTB will automatically isolate the OpenGL " "state of your code from its internal state. However, if you provide sharecontext=1, then PTB will allow " "your code to use and affect PTBs internal context. Only do this if you really know what you're doing! " "If you provide sharecontext=2 then PTB will give you your own private context, but it will synchronize " "the state of that context with its internal state - Seldomly needed, but here for your convenience. " "The context state isolation is as strict as possible without seriously affecting performance and functionality: " "All OpenGL context state is separated, with two exceptions: The framebuffer binding (if any) is always synchronized " "with PTB (and reset to zero when calling 'EndOpenGL' or another Screen command) to allow external code to transparently " "render into PTBs internal framebuffers - Needed for the imaging pipeline to work. Ressources like textures, display lists, " "FBOs, VBOs, PBOs and GLSL shaders are shared between PTB and your code as well for efficiency reasons. Both types of " "ressource sharing shouldn't be a problem, because either you are a beginner or advanced OpenGL programmer and won't use " "those facilities anyway, or you are an expert user - in which case you'll know how to prevent any conflicts easily."; static char seeAlsoString[] = "EndOpenGL SetOpenGLTexture GetOpenGLTexture moglcore"; PsychWindowRecordType *windowRecord; GLint fboid, coltexid, ztexid, stexid; //all sub functions should have these two lines PsychPushHelp(useString, synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //check for superfluous arguments PsychErrorExit(PsychCapNumInputArgs(2)); // The maximum number of inputs PsychErrorExit(PsychRequireNumInputArgs(1)); // Number of required inputs. PsychErrorExit(PsychCapNumOutputArgs(0)); // The maximum number of outputs //get the window record from the window record argument and get info from the window record PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); // Already in userspace mode? if (PsychIsUserspaceRendering()) PsychErrorExitMsg(PsychError_user, "Tried to call Screen('BeginOpenGL'), but userspace rendering is already active! Missing or mismatched Screen('EndOpenGL')? Check your code."); // (Optional) context sharing flag provided? sharecontext = 0; PsychCopyInIntegerArg(2, FALSE, &sharecontext); if (sharecontext<0 || sharecontext>2) PsychErrorExitMsg(PsychError_user, "Invalid value for 'sharecontext' provided. Not in range 0 to 2."); // Master override: If context isolation is disabled then we use the PTB internal context... if (PsychPrefStateGet_ConserveVRAM() & kPsychDisableContextIsolation) sharecontext = 1; // Set it as drawing target: This will set up the proper FBO bindings as well: PsychSetDrawingTarget(windowRecord); // Store it as a reference for later 'EndOpenGL' call: preswitchWindowRecord = windowRecord; // Userspace wants its own private rendering context, optionally updated to match PTBs internal state? if (sharecontext == 0 || sharecontext == 2) { // Yes. This is the normal case for 3D rendering. MOGLs and PTBs contexts are separated to // increase robustness, only ressources like textures, display lists, PBO's, VBO's, FBO's // and GLSL shaders are shared, but not the current renderstate. // Make sure 3D rendering is globally enabled, otherwise this is considered a userspace bug: if (PsychPrefStateGet_3DGfx()==0) PsychErrorExitMsg(PsychError_user, "Tried to call 'BeginOpenGL' for external rendering, but 3D rendering not globally enabled! Call 'InitializeMatlabOpenGL' at the beginning of your script!!"); // Query current FBO binding. We need to manually transfer this to the userspace context, so // it can render into our window: if (glBindFramebufferEXT) { fboid = 0; glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fboid); if (fboid>0) { // Query attachments of FBO: glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, &coltexid); glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, &ztexid); glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, &stexid); } } // Flush our context before context switch: glFlush(); // Unbind possible FBOs, so system FB is active in our context: if (glBindFramebufferEXT && (fboid > 0)) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glFlush(); } // Switch to userspace context for this window, optionally sync state with PTBs context: PsychOSSetUserGLContext(windowRecord, (sharecontext==2) ? TRUE : FALSE); // All following ops apply to the usercontext, not our internal context: // Manually establish proper FBO binding for userspace. This will get reset automaticaly on back-transition // inside PsychSetGLContext on its first invocation. If we are in non-imaging mode then there's nothing to do. if (glBindFramebufferEXT && (fboid > 0)) { if (!glIsFramebufferEXT(fboid)) { // Special case: Need to bind a special FBO and the underlying OpenGL driver is faulty, // i.e. it doesn't share FBO names accross our OpenGL contexts as it should according to // spec.: We manually create a clone of our internal FBO - Create an FBO in the userspace // context with the same FBO handle, then manually reattach the proper attachments... if (PsychPrefStateGet_Verbosity()>1) printf("PTB-WARNING: Faulty graphics driver - FBO sharing doesn't work properly, trying work-around. Update your drivers as soon as possible!\n"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboid); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_EXT, coltexid, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_EXT, ztexid, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_EXT, stexid, 0); if (GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)) { // Game over :( PsychErrorExitMsg(PsychError_internal, "Graphics driver malfunction: Failed to clone PTBs internal FBO for userspace GLContext inside SCREENBeginOpenGL as part of workaround code! Upgrade your gfx-drivers!!"); } // If we reach this point, then the workaround for the worst OS in existence has worked. } else { // Need to bind a special FBO and the system works correctly - no workaround needed. Just bind it in new context: glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboid); } } // Is this the first time that the userspace rendering context of this // onscreen window is selected for real userspace rendering? if (windowRecord->needsViewportSetup && PsychIsOnscreenWindow(windowRecord)) { // Yes. Need to perform one-time setup actions for this context: windowRecord->needsViewportSetup = FALSE; // Need to setup glViewPort, scissor rectangle, projection and modelview // matrices to values that match the windows client rectangle. We need to // do this here because some imaging pipeline display modes, e.g, stereomodes // for top-bottom stereo or dualview stereo may have altered the useable client // rendering area after the context was initially created. OpenGL spec states that // at least the viewport and scissor rectangles are set to the full client window // area at first bind of a context to its drawable, so we emulate this here on first // 'BeginOpenGL' to avoid unpleasant surprises for unsuspecting users: PsychSetupView(windowRecord, FALSE); } // Running without imaging pipeline and a stereo mode is active? if ((windowRecord->stereomode) > 0 && !(windowRecord->imagingMode & kPsychNeedFastBackingStore)) { // Perform setup work for stereo drawbuffers in fixed function mode: PsychSwitchFixedFunctionStereoDrawbuffer(windowRecord); } } else { // Userspace shares context with PTB. Let's disable possibly bound GLSL shaders: PsychSetShader(windowRecord, 0); } // Check for GL errors: PsychTestForGLErrors(); // Set the userspace flag: PsychSetUserspaceGLFlag(TRUE); // Ready for userspace rendering: return(PsychError_none); }