/** * We should call this periodically from a function such as glXMakeCurrent * in order to test if multiple threads are being used. */ void _glapi_check_multithread(void) { #if defined(THREADS) && !defined(GLX_USE_TLS) static unsigned long knownID; static GLboolean firstCall = GL_TRUE; if (ThreadSafe) return; CHECK_MULTITHREAD_LOCK(); if (firstCall) { /* initialize TSDs */ (void) _glthread_GetTSD(&ContextTSD); (void) _glthread_GetTSD(&_gl_DispatchTSD); knownID = _glthread_GetID(); firstCall = GL_FALSE; } else if (knownID != _glthread_GetID()) { ThreadSafe = GL_TRUE; _glapi_set_dispatch(NULL); _glapi_set_context(NULL); } CHECK_MULTITHREAD_UNLOCK(); #endif }
/** * Called via glBegin. */ static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) { GET_CURRENT_CONTEXT( ctx ); struct vbo_exec_context *exec = &vbo_context(ctx)->exec; int i; if (_mesa_inside_begin_end(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBegin"); return; } if (!_mesa_valid_prim_mode(ctx, mode, "glBegin")) { return; } vbo_draw_method(vbo_context(ctx), DRAW_BEGIN_END); if (ctx->NewState) { _mesa_update_state( ctx ); CALL_Begin(ctx->Exec, (mode)); return; } if (!_mesa_valid_to_render(ctx, "glBegin")) { return; } /* Heuristic: attempt to isolate attributes occurring outside * begin/end pairs. */ if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) vbo_exec_FlushVertices_internal(exec, GL_FALSE); i = exec->vtx.prim_count++; exec->vtx.prim[i].mode = mode; exec->vtx.prim[i].begin = 1; exec->vtx.prim[i].end = 0; exec->vtx.prim[i].indexed = 0; exec->vtx.prim[i].weak = 0; exec->vtx.prim[i].pad = 0; exec->vtx.prim[i].start = exec->vtx.vert_count; exec->vtx.prim[i].count = 0; exec->vtx.prim[i].num_instances = 1; exec->vtx.prim[i].base_instance = 0; exec->vtx.prim[i].is_indirect = 0; ctx->Driver.CurrentExecPrimitive = mode; ctx->Exec = ctx->BeginEnd; /* We may have been called from a display list, in which case we should * leave dlist.c's dispatch table in place. */ if (ctx->CurrentDispatch == ctx->OutsideBeginEnd) { ctx->CurrentDispatch = ctx->BeginEnd; _glapi_set_dispatch(ctx->CurrentDispatch); } else { assert(ctx->CurrentDispatch == ctx->Save); } }
static int indirect_bind_context(struct glx_context *gc, struct glx_context *old, GLXDrawable draw, GLXDrawable read) { GLXContextTag tag; __GLXattribute *state; Display *dpy = gc->psc->dpy; int opcode = __glXSetupForCommand(dpy); Bool sent; if (old != &dummyContext && !old->isDirect && old->psc->dpy == dpy) { tag = old->currentContextTag; old->currentContextTag = 0; } else { tag = 0; } sent = SendMakeCurrentRequest(dpy, opcode, gc->xid, tag, draw, read, &gc->currentContextTag); if (!IndirectAPI) IndirectAPI = __glXNewIndirectAPI(); _glapi_set_dispatch(IndirectAPI); state = gc->client_state_private; if (state->array_state == NULL) { glGetString(GL_EXTENSIONS); glGetString(GL_VERSION); __glXInitVertexArrayState(gc); } return !sent; }
/** * Called via glEnd. */ static void GLAPIENTRY vbo_exec_End(void) { GET_CURRENT_CONTEXT(ctx); struct vbo_exec_context *exec = &vbo_context(ctx)->exec; if (!_mesa_inside_begin_end(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd"); return; } ctx->Exec = ctx->OutsideBeginEnd; if (ctx->CurrentClientDispatch == ctx->BeginEnd) { ctx->CurrentClientDispatch = ctx->OutsideBeginEnd; _glapi_set_dispatch(ctx->CurrentClientDispatch); } if (exec->vtx.prim_count > 0) { /* close off current primitive */ struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1]; last_prim->end = 1; last_prim->count = exec->vtx.vert_count - last_prim->start; /* Special handling for GL_LINE_LOOP */ if (last_prim->mode == GL_LINE_LOOP && last_prim->begin == 0) { /* We're finishing drawing a line loop. Append 0th vertex onto * end of vertex buffer so we can draw it as a line strip. */ const fi_type *src = exec->vtx.buffer_map + last_prim->start * exec->vtx.vertex_size; fi_type *dst = exec->vtx.buffer_map + exec->vtx.vert_count * exec->vtx.vertex_size; /* copy 0th vertex to end of buffer */ memcpy(dst, src, exec->vtx.vertex_size * sizeof(fi_type)); last_prim->start++; /* skip vertex0 */ /* note that last_prim->count stays unchanged */ last_prim->mode = GL_LINE_STRIP; /* Increment the vertex count so the next primitive doesn't * overwrite the last vertex which we just added. */ exec->vtx.vert_count++; exec->vtx.buffer_ptr += exec->vtx.vertex_size; } try_vbo_merge(exec); } ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; if (exec->vtx.prim_count == VBO_MAX_PRIM) vbo_exec_vtx_flush(exec, GL_FALSE); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
_X_HIDDEN void __glXSetCurrentContextNull(void) { __glXSetCurrentContext(&dummyContext); #if defined(GLX_DIRECT_RENDERING) _glapi_set_dispatch(NULL); /* no-op functions */ _glapi_set_context(NULL); #endif }
_X_HIDDEN void __glXSetCurrentContextNull(void) { __glXSetCurrentContext(&dummyContext); #ifndef GLX_USE_APPLEGL #ifdef GLX_DIRECT_RENDERING _glapi_set_dispatch(NULL); /* no-op functions */ #endif #endif }
void apple_glapi_set_dispatch(void) { if(__applegl_api) { _glapi_set_dispatch(__applegl_api); return; } __ogl_framework_api = _glapi_create_table_from_handle(apple_cgl_get_dl_handle(), "gl"); assert(__ogl_framework_api); __applegl_api = malloc(sizeof(struct _glapi_table)); assert(__applegl_api); memcpy(__applegl_api, __ogl_framework_api, sizeof(struct _glapi_table)); SET_ReadPixels(__applegl_api, __applegl_glReadPixels); SET_CopyPixels(__applegl_api, __applegl_glCopyPixels); SET_CopyColorTable(__applegl_api, __applegl_glCopyColorTable); SET_DrawBuffer(__applegl_api, __applegl_glDrawBuffer); SET_DrawBuffersARB(__applegl_api, __applegl_glDrawBuffersARB); SET_Viewport(__applegl_api, __applegl_glViewport); _glapi_set_dispatch(__applegl_api); }
/** * We should call this periodically from a function such as glXMakeCurrent * in order to test if multiple threads are being used. */ void _glapi_check_multithread(void) { #if defined(THREADS) && !defined(GLX_USE_TLS) if (!ThreadSafe) { static unsigned long knownID; static GLboolean firstCall = GL_TRUE; if (firstCall) { knownID = _glthread_GetID(); firstCall = GL_FALSE; } else if (knownID != _glthread_GetID()) { ThreadSafe = GL_TRUE; _glapi_set_dispatch(NULL); _glapi_set_context(NULL); } } else if (!_glapi_get_dispatch()) { /* make sure that this thread's dispatch pointer isn't null */ _glapi_set_dispatch(NULL); } #endif }
static void vboxPatchMesaGLAPITable() { void *pGLTable; pGLTable = (void *)_glapi_get_dispatch(); vbox_glapi_table = crAlloc(_glapi_get_dispatch_table_size() * sizeof (void *)); if (!vbox_glapi_table) { crError("Not enough memory to allocate dispatch table"); } crMemcpy(vbox_glapi_table, pGLTable, _glapi_get_dispatch_table_size() * sizeof (void *)); #include "fakedri_glfuncsList.h" VBOX_SET_MESA_FUNC(vbox_glapi_table, "glBlendEquationSeparateEXT", cr_glBlendEquationSeparate); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glSampleMaskSGIS", cr_glSampleMaskEXT); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glSamplePatternSGIS", cr_glSamplePatternEXT); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2dMESA", cr_glWindowPos2d); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2dvMESA", cr_glWindowPos2dv); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2fMESA", cr_glWindowPos2f); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2fvMESA", cr_glWindowPos2fv); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2iMESA", cr_glWindowPos2i); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2ivMESA", cr_glWindowPos2iv); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2sMESA", cr_glWindowPos2s); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2svMESA", cr_glWindowPos2sv); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3dMESA", cr_glWindowPos3d); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3dvMESA", cr_glWindowPos3dv); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3fMESA", cr_glWindowPos3f); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3fvMESA", cr_glWindowPos3fv); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3iMESA", cr_glWindowPos3i); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3ivMESA", cr_glWindowPos3iv); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3sMESA", cr_glWindowPos3s); VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3svMESA", cr_glWindowPos3sv); _glapi_set_dispatch(vbox_glapi_table); };
static int indirect_bind_context(struct glx_context *gc, struct glx_context *old, GLXDrawable draw, GLXDrawable read) { GLXContextTag tag; Display *dpy = gc->psc->dpy; Bool sent; if (old != &dummyContext && !old->isDirect && old->psc->dpy == dpy) { tag = old->currentContextTag; old->currentContextTag = 0; } else { tag = 0; } sent = SendMakeCurrentRequest(dpy, gc->xid, tag, draw, read, &gc->currentContextTag); if (!IndirectAPI) IndirectAPI = __glXNewIndirectAPI(); _glapi_set_dispatch(IndirectAPI); return !sent; }
/** * Called via glEnd. */ static void GLAPIENTRY vbo_exec_End( void ) { GET_CURRENT_CONTEXT( ctx ); struct vbo_exec_context *exec = &vbo_context(ctx)->exec; if (!_mesa_inside_begin_end(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd"); return; } ctx->Exec = ctx->OutsideBeginEnd; if (ctx->CurrentDispatch == ctx->BeginEnd) { ctx->CurrentDispatch = ctx->OutsideBeginEnd; _glapi_set_dispatch(ctx->CurrentDispatch); } if (exec->vtx.prim_count > 0) { /* close off current primitive */ int idx = exec->vtx.vert_count; int i = exec->vtx.prim_count - 1; exec->vtx.prim[i].end = 1; exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start; try_vbo_merge(exec); } ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; if (exec->vtx.prim_count == VBO_MAX_PRIM) vbo_exec_vtx_flush( exec, GL_FALSE ); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
void apple_glapi_set_dispatch(void) { _apple_glapi_create_table(); _glapi_set_dispatch(__applegl_api); }
status_t BGLDispatcher::SetTable(struct _glapi_table* table) { _glapi_set_dispatch(table); return B_OK; }
/** * Insert the active immediate struct onto the display list currently * being built. */ static void _save_compile_vertex_list(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; struct vbo_save_vertex_list *node; /* Allocate space for this structure in the display list currently * being compiled. */ node = (struct vbo_save_vertex_list *) _mesa_dlist_alloc(ctx, save->opcode_vertex_list, sizeof(*node)); if (!node) return; /* Duplicate our template, increment refcounts to the storage structs: */ memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz)); node->vertex_size = save->vertex_size; node->buffer_offset = (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat); node->count = save->vert_count; node->wrap_count = save->copied.nr; node->dangling_attr_ref = save->dangling_attr_ref; node->prim = save->prim; node->prim_count = save->prim_count; node->vertex_store = save->vertex_store; node->prim_store = save->prim_store; node->vertex_store->refcount++; node->prim_store->refcount++; if (node->prim[0].no_current_update) { node->current_size = 0; node->current_data = NULL; } else { node->current_size = node->vertex_size - node->attrsz[0]; node->current_data = NULL; if (node->current_size) { /* If the malloc fails, we just pull the data out of the VBO * later instead. */ node->current_data = MALLOC(node->current_size * sizeof(GLfloat)); if (node->current_data) { const char *buffer = (const char *) save->vertex_store->buffer; unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat); unsigned vertex_offset = 0; if (node->count) vertex_offset = (node->count - 1) * node->vertex_size * sizeof(GLfloat); memcpy(node->current_data, buffer + node->buffer_offset + vertex_offset + attr_offset, node->current_size * sizeof(GLfloat)); } } } assert(node->attrsz[VBO_ATTRIB_POS] != 0 || node->count == 0); if (save->dangling_attr_ref) ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS; save->vertex_store->used += save->vertex_size * node->count; save->prim_store->used += node->prim_count; /* Copy duplicated vertices */ save->copied.nr = _save_copy_vertices(ctx, node, save->buffer); /* Deal with GL_COMPILE_AND_EXECUTE: */ if (ctx->ExecuteFlag) { struct _glapi_table *dispatch = GET_DISPATCH(); _glapi_set_dispatch(ctx->Exec); vbo_loopback_vertex_list(ctx, (const GLfloat *) ((const char *) save-> vertex_store->buffer + node->buffer_offset), node->attrsz, node->prim, node->prim_count, node->wrap_count, node->vertex_size); _glapi_set_dispatch(dispatch); } /* Decide whether the storage structs are full, or can be used for * the next vertex lists as well. */ if (save->vertex_store->used > VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) { /* Unmap old store: */ vbo_save_unmap_vertex_store(ctx, save->vertex_store); /* Release old reference: */ save->vertex_store->refcount--; assert(save->vertex_store->refcount != 0); save->vertex_store = NULL; /* Allocate and map new store: */ save->vertex_store = alloc_vertex_store(ctx); save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store); save->out_of_memory = save->buffer_ptr == NULL; } if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) { save->prim_store->refcount--; assert(save->prim_store->refcount != 0); save->prim_store = alloc_prim_store(ctx); } /* Reset our structures for the next run of vertices: */ _save_reset_counters(ctx); }
/** * Bind the given context to the given drawBuffer and readBuffer and * make it the current context for the calling thread. * We'll render into the drawBuffer and read pixels from the * readBuffer (i.e. glRead/CopyPixels, glCopyTexImage, etc). * * We check that the context's and framebuffer's visuals are compatible * and return immediately if they're not. * * \param newCtx the new GL context. If NULL then there will be no current GL * context. * \param drawBuffer the drawing framebuffer * \param readBuffer the reading framebuffer */ GLboolean _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, GLframebuffer *readBuffer ) { if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(newCtx, "_mesa_make_current()\n"); /* Check that the context's and framebuffer's visuals are compatible. */ if (newCtx && drawBuffer && newCtx->WinSysDrawBuffer != drawBuffer) { if (!check_compatible(newCtx, drawBuffer)) { _mesa_warning(newCtx, "MakeCurrent: incompatible visuals for context and drawbuffer"); return GL_FALSE; } } if (newCtx && readBuffer && newCtx->WinSysReadBuffer != readBuffer) { if (!check_compatible(newCtx, readBuffer)) { _mesa_warning(newCtx, "MakeCurrent: incompatible visuals for context and readbuffer"); return GL_FALSE; } } /* We used to call _glapi_check_multithread() here. Now do it in drivers */ _glapi_set_context((void *) newCtx); ASSERT(_mesa_get_current_context() == newCtx); if (!newCtx) { _glapi_set_dispatch(NULL); /* none current */ } else { _glapi_set_dispatch(newCtx->CurrentDispatch); if (drawBuffer && readBuffer) { /* TODO: check if newCtx and buffer's visual match??? */ ASSERT(drawBuffer->Name == 0); ASSERT(readBuffer->Name == 0); _mesa_reference_framebuffer(&newCtx->WinSysDrawBuffer, drawBuffer); _mesa_reference_framebuffer(&newCtx->WinSysReadBuffer, readBuffer); /* * Only set the context's Draw/ReadBuffer fields if they're NULL * or not bound to a user-created FBO. */ if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) { /* KW: merge conflict here, revisit. */ /* fix up the fb fields - these will end up wrong otherwise * if the DRIdrawable changes, and everything relies on them. * This is a bit messy (same as needed in _mesa_BindFramebufferEXT) */ unsigned int i; GLenum buffers[MAX_DRAW_BUFFERS]; _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer); for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) { buffers[i] = newCtx->Color.DrawBuffer[i]; } _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL); } if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); } /* XXX only set this flag if we're really changing the draw/read * framebuffer bindings. */ newCtx->NewState |= _NEW_BUFFERS; #if 1 /* We want to get rid of these lines: */ #if _HAVE_FULL_GL if (!drawBuffer->Initialized) { initialize_framebuffer_size(newCtx, drawBuffer); } if (readBuffer != drawBuffer && !readBuffer->Initialized) { initialize_framebuffer_size(newCtx, readBuffer); } _mesa_resizebuffers(newCtx); #endif #else /* We want the drawBuffer and readBuffer to be initialized by * the driver. * This generally means the Width and Height match the actual * window size and the renderbuffers (both hardware and software * based) are allocated to match. The later can generally be * done with a call to _mesa_resize_framebuffer(). * * It's theoretically possible for a buffer to have zero width * or height, but for now, assert check that the driver did what's * expected of it. */ ASSERT(drawBuffer->Width > 0); ASSERT(drawBuffer->Height > 0); #endif if (drawBuffer) { _mesa_check_init_viewport(newCtx, drawBuffer->Width, drawBuffer->Height); } } if (newCtx->FirstTimeCurrent) { check_context_limits(newCtx); /* We can use this to help debug user's problems. Tell them to set * the MESA_INFO env variable before running their app. Then the * first time each context is made current we'll print some useful * information. */ if (_mesa_getenv("MESA_INFO")) { _mesa_print_info(); } newCtx->FirstTimeCurrent = GL_FALSE; } } return GL_TRUE; }
/* Insert the active immediate struct onto the display list currently * being built. */ static void _save_compile_vertex_list( GLcontext *ctx ) { struct vbo_save_context *save = &vbo_context(ctx)->save; struct vbo_save_vertex_list *node; /* Allocate space for this structure in the display list currently * being compiled. */ node = (struct vbo_save_vertex_list *) _mesa_alloc_instruction(ctx, save->opcode_vertex_list, sizeof(*node)); if (!node) return; /* Duplicate our template, increment refcounts to the storage structs: */ _mesa_memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz)); node->vertex_size = save->vertex_size; node->buffer_offset = (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat); node->count = save->vert_count; node->wrap_count = save->copied.nr; node->dangling_attr_ref = save->dangling_attr_ref; node->prim = save->prim; node->prim_count = save->prim_count; node->vertex_store = save->vertex_store; node->prim_store = save->prim_store; node->vertex_store->refcount++; node->prim_store->refcount++; assert(node->attrsz[VBO_ATTRIB_POS] != 0 || node->count == 0); if (save->dangling_attr_ref) ctx->ListState.CurrentList->flags |= MESA_DLIST_DANGLING_REFS; save->vertex_store->used += save->vertex_size * node->count; save->prim_store->used += node->prim_count; /* Copy duplicated vertices */ save->copied.nr = _save_copy_vertices( ctx, node, save->buffer ); /* Deal with GL_COMPILE_AND_EXECUTE: */ if (ctx->ExecuteFlag) { struct _glapi_table *dispatch = GET_DISPATCH(); _glapi_set_dispatch(ctx->Exec); vbo_loopback_vertex_list( ctx, (const GLfloat *)((const char *)save->vertex_store->buffer + node->buffer_offset), node->attrsz, node->prim, node->prim_count, node->wrap_count, node->vertex_size); _glapi_set_dispatch(dispatch); } /* Decide whether the storage structs are full, or can be used for * the next vertex lists as well. */ if (save->vertex_store->used > VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) { /* Unmap old store: */ unmap_vertex_store( ctx, save->vertex_store ); /* Release old reference: */ save->vertex_store->refcount--; assert(save->vertex_store->refcount != 0); save->vertex_store = NULL; /* Allocate and map new store: */ save->vertex_store = alloc_vertex_store( ctx ); save->vbptr = map_vertex_store( ctx, save->vertex_store ); } if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) { save->prim_store->refcount--; assert(save->prim_store->refcount != 0); save->prim_store = alloc_prim_store( ctx ); } /* Reset our structures for the next run of vertices: */ _save_reset_counters( ctx ); }
/** * 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)