📄 context.c
字号:
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 */
MEMCPY( &dst->Light, &src->Light, sizeof(struct gl_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.
* \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 (ctxvis->doubleBufferMode && !bufvis->doubleBufferMode)
return GL_FALSE;
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;
}
/**
* Bind the given context to the given draw-buffer and read-buffer and
* make it the current context for this thread.
*
* \param newCtx new GL context. If NULL then there will be no current GL
* context.
* \param drawBuffer draw framebuffer.
* \param readBuffer read framebuffer.
*
* Check that the context's and framebuffer's visuals are compatible, returning
* immediately otherwise. Sets the glapi current context via
* _glapi_set_context(). If \p newCtx is not NULL, associates \p drawBuffer and
* \p readBuffer with it and calls dd_function_table::ResizeBuffers if the buffers size has changed.
* Calls dd_function_table::MakeCurrent callback if defined.
*
* When a context is bound by the first time and the \c MESA_INFO environment
* variable is set it calls print_info() as an aid for remote user
* troubleshooting.
*/
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->DrawBuffer != drawBuffer) {
if (!check_compatible(newCtx, drawBuffer))
return;
}
if (newCtx && readBuffer && newCtx->ReadBuffer != readBuffer) {
if (!check_compatible(newCtx, readBuffer))
return;
}
#if !defined(IN_DRI_DRIVER)
/* We call this function periodically (just here for now) in
* order to detect when multithreading has begun. In a DRI driver, this
* step is done by the driver loader (e.g., libGL).
*/
_glapi_check_multithread();
#endif /* !defined(IN_DRI_DRIVER) */
_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;
/* don't replace user-buffer bindings with window system buffer */
if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
newCtx->DrawBuffer = drawBuffer;
newCtx->ReadBuffer = readBuffer;
}
newCtx->NewState |= _NEW_BUFFERS;
#if _HAVE_FULL_GL
if (!drawBuffer->Initialized) {
/* get initial window size */
GLuint bufWidth, bufHeight;
/* ask device driver for size of the buffer */
(*newCtx->Driver.GetBufferSize)(drawBuffer, &bufWidth, &bufHeight);
/* set initial buffer size */
if (newCtx->Driver.ResizeBuffers)
newCtx->Driver.ResizeBuffers(newCtx, drawBuffer,
bufWidth, bufHeight);
drawBuffer->Initialized = GL_TRUE;
}
if (readBuffer != drawBuffer && !readBuffer->Initialized) {
/* get initial window size */
GLuint bufWidth, bufHeight;
/* ask device driver for size of the buffer */
(*newCtx->Driver.GetBufferSize)(readBuffer, &bufWidth, &bufHeight);
/* set initial buffer size */
if (newCtx->Driver.ResizeBuffers)
newCtx->Driver.ResizeBuffers(newCtx, readBuffer,
bufWidth, bufHeight);
readBuffer->Initialized = GL_TRUE;
}
#endif
if (newCtx->FirstTimeCurrent) {
/* set initial viewport and scissor size now */
_mesa_set_viewport(newCtx, 0, 0, drawBuffer->Width, drawBuffer->Height);
newCtx->Scissor.Width = drawBuffer->Width;
newCtx->Scissor.Height = drawBuffer->Height;
}
}
/* Alert the driver - usually passed on to the sw t&l module,
* but also used to detect threaded cases in the radeon codegen
* hw t&l module.
*/
if (newCtx->Driver.MakeCurrent)
newCtx->Driver.MakeCurrent( newCtx, drawBuffer, readBuffer );
/* 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 + -