void apple_glx_context_update(Display * dpy, void *ptr) { struct apple_glx_context *ac = ptr; if (NULL == ac->drawable && None != ac->last_surface_window) { bool failed; /* Attempt to recreate the surface for a destroyed drawable. */ failed = apple_glx_make_current_context(dpy, ac, ac, ac->last_surface_window); apple_glx_diagnostic("%s: surface recreation failed? %s\n", __func__, failed ? "YES" : "NO"); } if (ac->need_update) { xp_update_gl_context(ac->context_obj); ac->need_update = false; apple_glx_diagnostic("%s: updating context %p\n", __func__, ptr); } if (ac->drawable && APPLE_GLX_DRAWABLE_SURFACE == ac->drawable->type && ac->drawable->types.surface.pending_destroy) { apple_glx_diagnostic("%s: clearing drawable %p\n", __func__, ptr); apple_cgl.clear_drawable(ac->context_obj); if (ac->drawable) { struct apple_glx_drawable *d; apple_glx_diagnostic("%s: attempting to destroy drawable %p\n", __func__, ptr); apple_glx_diagnostic("%s: ac->drawable->drawable is 0x%lx\n", __func__, ac->drawable->drawable); d = ac->drawable; ac->last_surface_window = d->drawable; ac->drawable = NULL; /* * This will destroy the surface drawable if there are * no references to it. * It also subtracts 1 from the reference_count. * If there are references to it, then it's probably made * current in another context. */ d->destroy(d); } } }
/** * Make a particular context current. * * \note This is in this file so that it can access dummyContext. */ static Bool MakeContextCurrent(Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext gc) { const GLXContext oldGC = __glXGetCurrentContext(); #ifdef GLX_USE_APPLEGL bool error = apple_glx_make_current_context(dpy, (oldGC && oldGC != &dummyContext) ? oldGC->apple : NULL, gc ? gc->apple : NULL, draw); apple_glx_diagnostic("%s: error %s\n", __func__, error ? "YES" : "NO"); if(error) return GL_FALSE; #else xGLXMakeCurrentReply reply; const CARD8 opcode = __glXSetupForCommand(dpy); const CARD8 oldOpcode = ((gc == oldGC) || (oldGC == &dummyContext)) ? opcode : __glXSetupForCommand(oldGC->currentDpy); Bool bindReturnValue; __GLXattribute *state; if (!opcode || !oldOpcode) { return GL_FALSE; } /* Make sure that the new context has a nonzero ID. In the request, * a zero context ID is used only to mean that we bind to no current * context. */ if ((gc != NULL) && (gc->xid == None)) { return GL_FALSE; } if (gc == NULL && (draw != None || read != None)) { __glXGenerateError(dpy, gc, (draw != None) ? draw : read, BadMatch, X_GLXMakeContextCurrent); return False; } if (gc != NULL && (draw == None || read == None)) { __glXGenerateError(dpy, gc, None, BadMatch, X_GLXMakeContextCurrent); return False; } _glapi_check_multithread(); if (gc != NULL && gc->thread_id != 0 && gc->thread_id != _glthread_GetID()) { __glXGenerateError(dpy, gc, gc->xid, BadAccess, X_GLXMakeContextCurrent); return False; } #ifdef GLX_DIRECT_RENDERING /* Bind the direct rendering context to the drawable */ if (gc && gc->driContext) { __GLXDRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc); __GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc); if ((pdraw == NULL) || (pread == NULL)) { __glXGenerateError(dpy, gc, (pdraw == NULL) ? draw : read, GLXBadDrawable, X_GLXMakeContextCurrent); return False; } bindReturnValue = (gc->driContext->bindContext) (gc->driContext, pdraw, pread); } else if (!gc && oldGC && oldGC->driContext) { bindReturnValue = True; } else #endif { /* Send a glXMakeCurrent request to bind the new context. */ bindReturnValue = SendMakeCurrentRequest(dpy, opcode, gc ? gc->xid : None, ((dpy != oldGC->currentDpy) || oldGC->isDirect) ? None : oldGC->currentContextTag, draw, read, &reply); } if (!bindReturnValue) { return False; } #ifdef GLX_DIRECT_RENDERING if ((dpy != oldGC->currentDpy || (gc && gc->driContext)) && !oldGC->isDirect && oldGC != &dummyContext) { #else if ((dpy != oldGC->currentDpy) && oldGC != &dummyContext) { #endif xGLXMakeCurrentReply dummy_reply; /* We are either switching from one dpy to another and have to * send a request to the previous dpy to unbind the previous * context, or we are switching away from a indirect context to * a direct context and have to send a request to the dpy to * unbind the previous context. */ (void) SendMakeCurrentRequest(oldGC->currentDpy, oldOpcode, None, oldGC->currentContextTag, None, None, &dummy_reply); } #ifdef GLX_DIRECT_RENDERING else if (oldGC->driContext && oldGC != gc) { oldGC->driContext->unbindContext(oldGC->driContext); } #endif #endif /* GLX_USE_APPLEGL */ /* Update our notion of what is current */ __glXLock(); if (gc == oldGC) { /* Even though the contexts are the same the drawable might have * changed. Note that gc cannot be the dummy, and that oldGC * cannot be NULL, therefore if they are the same, gc is not * NULL and not the dummy. */ if(gc) { gc->currentDrawable = draw; gc->currentReadable = read; } } else { if (oldGC != &dummyContext) { /* Old current context is no longer current to anybody */ oldGC->currentDpy = 0; oldGC->currentDrawable = None; oldGC->currentReadable = None; oldGC->currentContextTag = 0; oldGC->thread_id = 0; #ifdef GLX_USE_APPLEGL /* * At this point we should check if the context has been * through glXDestroyContext, and redestroy it if so. */ if(oldGC->do_destroy) { __glXUnlock(); /* glXDestroyContext uses the same global lock. */ glXDestroyContext(dpy, oldGC); __glXLock(); #else if (oldGC->xid == None) { /* We are switching away from a context that was * previously destroyed, so we need to free the memory * for the old handle. */ #ifdef GLX_DIRECT_RENDERING /* Destroy the old direct rendering context */ if (oldGC->driContext) { oldGC->driContext->destroyContext(oldGC->driContext, oldGC->psc, oldGC->createDpy); oldGC->driContext = NULL; } #endif __glXFreeContext(oldGC); #endif /* GLX_USE_APPLEGL */ } } if (gc) { __glXSetCurrentContext(gc); gc->currentDpy = dpy; gc->currentDrawable = draw; gc->currentReadable = read; #ifndef GLX_USE_APPLEGL gc->thread_id = _glthread_GetID(); #ifdef GLX_DIRECT_RENDERING if (!gc->driContext) { #endif if (!IndirectAPI) IndirectAPI = __glXNewIndirectAPI(); _glapi_set_dispatch(IndirectAPI); #ifdef GLX_USE_APPLEGL do { extern void XAppleDRIUseIndirectDispatch(void); XAppleDRIUseIndirectDispatch(); } while (0); #endif state = (__GLXattribute *) (gc->client_state_private); gc->currentContextTag = reply.contextTag; if (state->array_state == NULL) { (void) glGetString(GL_EXTENSIONS); (void) glGetString(GL_VERSION); __glXInitVertexArrayState(gc); } #ifdef GLX_DIRECT_RENDERING } else { gc->currentContextTag = -1; } #endif #endif /* GLX_USE_APPLEGL */ } else { __glXSetCurrentContextNull(); } } __glXUnlock(); return GL_TRUE; } PUBLIC Bool glXMakeCurrent(Display * dpy, GLXDrawable draw, GLXContext gc) { return MakeContextCurrent(dpy, draw, draw, gc); } PUBLIC GLX_ALIAS(Bool, glXMakeCurrentReadSGI, (Display * dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx), (dpy, d, r, ctx), MakeContextCurrent) PUBLIC GLX_ALIAS(Bool, glXMakeContextCurrent, (Display * dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx), (dpy, d, r, ctx), MakeContextCurrent)