📄 context.c
字号:
_glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); if (ctx->Shared->RefCount == 0) { /* free shared state */ free_shared_state( ctx, ctx->Shared ); } if (ctx->Extensions.String) FREE((void *) ctx->Extensions.String);}/** * Destroy a GLcontext structure. * * \param ctx GL context. * * Calls _mesa_free_context_data() and frees the GLcontext structure itself. */void_mesa_destroy_context( GLcontext *ctx ){ if (ctx) { _mesa_free_context_data(ctx); FREE( (void *) ctx ); }}#if _HAVE_FULL_GL/** * Copy attribute groups from one context to another. * * \param src source context * \param dst destination context * \param mask bitwise OR of GL_*_BIT flags * * According to the bits specified in \p mask, copies the corresponding * attributes from \p src into \p dst. For many of the attributes a simple \c * memcpy is not enough due to the existence of internal pointers in their data * structures. */void_mesa_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask ){ if (mask & GL_ACCUM_BUFFER_BIT) { /* OK to memcpy */ dst->Accum = src->Accum; } if (mask & GL_COLOR_BUFFER_BIT) { /* OK to memcpy */ dst->Color = src->Color; } if (mask & GL_CURRENT_BIT) { /* OK to memcpy */ dst->Current = src->Current; } if (mask & GL_DEPTH_BUFFER_BIT) { /* OK to memcpy */ dst->Depth = src->Depth; } if (mask & GL_ENABLE_BIT) { /* no op */ } if (mask & GL_EVAL_BIT) { /* OK to memcpy */ dst->Eval = src->Eval; } if (mask & GL_FOG_BIT) { /* OK to memcpy */ dst->Fog = src->Fog; } if (mask & GL_HINT_BIT) { /* OK to memcpy */ dst->Hint = src->Hint; } if (mask & GL_LIGHTING_BIT) { GLuint i; /* begin with memcpy */ dst->Light = src->Light; /* fixup linked lists to prevent pointer insanity */ make_empty_list( &(dst->Light.EnabledList) ); for (i = 0; i < MAX_LIGHTS; i++) { if (dst->Light.Light[i].Enabled) { insert_at_tail(&(dst->Light.EnabledList), &(dst->Light.Light[i])); } } } if (mask & GL_LINE_BIT) { /* OK to memcpy */ dst->Line = src->Line; } if (mask & GL_LIST_BIT) { /* OK to memcpy */ dst->List = src->List; } if (mask & GL_PIXEL_MODE_BIT) { /* OK to memcpy */ dst->Pixel = src->Pixel; } if (mask & GL_POINT_BIT) { /* OK to memcpy */ dst->Point = src->Point; } if (mask & GL_POLYGON_BIT) { /* OK to memcpy */ dst->Polygon = src->Polygon; } if (mask & GL_POLYGON_STIPPLE_BIT) { /* Use loop instead of MEMCPY due to problem with Portland Group's * C compiler. Reported by John Stone. */ GLuint i; for (i = 0; i < 32; i++) { dst->PolygonStipple[i] = src->PolygonStipple[i]; } } if (mask & GL_SCISSOR_BIT) { /* OK to memcpy */ dst->Scissor = src->Scissor; } if (mask & GL_STENCIL_BUFFER_BIT) { /* OK to memcpy */ dst->Stencil = src->Stencil; } if (mask & GL_TEXTURE_BIT) { /* Cannot memcpy because of pointers */ _mesa_copy_texture_state(src, dst); } if (mask & GL_TRANSFORM_BIT) { /* OK to memcpy */ dst->Transform = src->Transform; } if (mask & GL_VIEWPORT_BIT) { /* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */ dst->Viewport.X = src->Viewport.X; dst->Viewport.Y = src->Viewport.Y; dst->Viewport.Width = src->Viewport.Width; dst->Viewport.Height = src->Viewport.Height; dst->Viewport.Near = src->Viewport.Near; dst->Viewport.Far = src->Viewport.Far; _math_matrix_copy(&dst->Viewport._WindowMap, &src->Viewport._WindowMap); } /* XXX FIXME: Call callbacks? */ dst->NewState = _NEW_ALL;}#endif/** * Check if the given context can render into the given framebuffer * by checking visual attributes. * * XXX this may go away someday because we're moving toward more freedom * in binding contexts to drawables with different visual attributes. * The GL_EXT_f_b_o extension is prompting some of that. * * \return GL_TRUE if compatible, GL_FALSE otherwise. */static GLboolean check_compatible(const GLcontext *ctx, const GLframebuffer *buffer){ const GLvisual *ctxvis = &ctx->Visual; const GLvisual *bufvis = &buffer->Visual; if (ctxvis == bufvis) return GL_TRUE; if (ctxvis->rgbMode != bufvis->rgbMode) return GL_FALSE;#if 0 /* disabling this fixes the fgl_glxgears pbuffer demo */ if (ctxvis->doubleBufferMode && !bufvis->doubleBufferMode) return GL_FALSE;#endif if (ctxvis->stereoMode && !bufvis->stereoMode) return GL_FALSE; if (ctxvis->haveAccumBuffer && !bufvis->haveAccumBuffer) return GL_FALSE; if (ctxvis->haveDepthBuffer && !bufvis->haveDepthBuffer) return GL_FALSE; if (ctxvis->haveStencilBuffer && !bufvis->haveStencilBuffer) return GL_FALSE; if (ctxvis->redMask && ctxvis->redMask != bufvis->redMask) return GL_FALSE; if (ctxvis->greenMask && ctxvis->greenMask != bufvis->greenMask) return GL_FALSE; if (ctxvis->blueMask && ctxvis->blueMask != bufvis->blueMask) return GL_FALSE; if (ctxvis->depthBits && ctxvis->depthBits != bufvis->depthBits) return GL_FALSE; if (ctxvis->stencilBits && ctxvis->stencilBits != bufvis->stencilBits) return GL_FALSE; return GL_TRUE;}/** * Do one-time initialization for the given framebuffer. Specifically, * ask the driver for the window's current size and update the framebuffer * object to match. * Really, the device driver should totally take care of this. */static voidinitialize_framebuffer_size(GLcontext *ctx, GLframebuffer *fb){ GLuint width, height; ASSERT(ctx->Driver.GetBufferSize); ctx->Driver.GetBufferSize(fb, &width, &height); if (ctx->Driver.ResizeBuffers) ctx->Driver.ResizeBuffers(ctx, fb, width, height); fb->Initialized = GL_TRUE;}/** * 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 */void_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; } } if (newCtx && readBuffer && newCtx->WinSysReadBuffer != readBuffer) { if (!check_compatible(newCtx, readBuffer)) { _mesa_warning(newCtx, "MakeCurrent: incompatible visuals for context and readbuffer"); return; } } /* 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); newCtx->WinSysDrawBuffer = drawBuffer; 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) { newCtx->DrawBuffer = drawBuffer; } if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { newCtx->ReadBuffer = readBuffer; } newCtx->NewState |= _NEW_BUFFERS;#if _HAVE_FULL_GL if (!drawBuffer->Initialized) { initialize_framebuffer_size(newCtx, drawBuffer); } if (readBuffer != drawBuffer && !readBuffer->Initialized) { initialize_framebuffer_size(newCtx, readBuffer); }#endif if (newCtx->FirstTimeCurrent) { /* set initial viewport and scissor size now */ _mesa_set_viewport(newCtx, 0, 0, drawBuffer->Width, drawBuffer->Height); _mesa_set_scissor(newCtx, 0, 0, drawBuffer->Width, drawBuffer->Height ); } } /* 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 (newCtx->FirstTimeCurrent) { if (_mesa_getenv("MESA_INFO")) { _mesa_print_info(); } newCtx->FirstTimeCurrent = GL_FALSE; } }}/** * Make context 'ctx' share the display lists, textures and programs * that are associated with 'ctxToShare'. * Any display lists, textures or programs associated with 'ctx' will * be deleted if nobody else is sharing them. */GLboolean_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare){ if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) { ctx->Shared->RefCount--; if (ctx->Shared->RefCount == 0) { free_shared_state(ctx, ctx->Shared); } ctx->Shared = ctxToShare->Shared; ctx->Shared->RefCount++; return GL_TRUE; } else { return GL_FALSE; }}/** * Get current context for the calling thread. * * \return pointer to the current GL context. * * Calls _glapi_get_context(). This isn't the fastest way to get the current * context. If you need speed, see the #GET_CURRENT_CONTEXT macro in context.h. */GLcontext *_mesa_get_current_context( void ){ return (GLcontext *) _glapi_get_context();}/** * Get context's current API dispatch table. * * It'll either be the immediate-mode execute dispatcher or the display list * compile dispatcher. * * \param ctx GL context. * * \return pointer to dispatch_table. * * Simply returns __GLcontextRec::CurrentDispatch. */struct _glapi_table *_mesa_get_dispatch(GLcontext *ctx){ return ctx->CurrentDispatch;}/*@}*//**********************************************************************//** \name Miscellaneous functions *//**********************************************************************//*@{*//** * Record an error. * * \param ctx GL context. * \param error error code. * * Records the given error code and call the driver's dd_function_table::Error * function if defined. * * \sa * This is called via _mesa_error(). */void_mesa_record_error( GLcontext *ctx, GLenum error ){ if (!ctx) return; if (ctx->ErrorValue == GL_NO_ERROR) { ctx->ErrorValue = error; } /* Call device driver's error handler, if any. This is used on the Mac. */ if (ctx->Driver.Error) { (*ctx->Driver.Error)( ctx ); }}/** * Execute glFinish(). * * Calls the #ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH macro and the * dd_function_table::Finish driver callback, if not NULL. */void GLAPIENTRY_mesa_Finish( void ){ GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (ctx->Driver.Finish) { (*ctx->Driver.Finish)( ctx ); }}/** * Execute glFlush(). * * Calls the #ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH macro and the * dd_function_table::Flush driver callback, if not NULL. */void GLAPIENTRY_mesa_Flush( void ){ GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (ctx->Driver.Flush) { (*ctx->Driver.Flush)( ctx ); }}/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -