Next, let's take a look at what happened after the WMesaMakeCurrent function calls _ mesa_make_current:
_ Mesa_make_current // context. c from row 1,310th to row 1,436th 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 comparator als are compatible. */if (newCtx & drawBuffer & newCtx-> WinSysDrawBuffer! = DrawBuffer) {if (! Check_compatible (newCtx, drawBuffer) {_ mesa_warning (newCtx, "MakeCurrent: incompatible events als for context and drawbuffer"); return GL_FALSE ;}} if (newCtx & readBuffer & newCtx-> WinSysReadBuffer! = ReadBuffer) {if (! Check_compatible (newCtx, readBuffer) {_ mesa_warning (newCtx, "MakeCurrent: incompatible logs als 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]; _ buffers (& newCtx-> DrawBuffer, drawBuffer); (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 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 ;}
Line 3 calls glapi. the _ glapi_set_context function in c sets the current ctx, that is, the value of the project global variable _ glapi_Context points to the context, and the first member in the wmesa_context structure is GLcontext, so the pointer addresses of the two are the same;
In line 3, call _ glapi_set_dispatch in glapi. c to set the current function handle, that is, set the global variable _ glapi_Dispatch to point.
In glapitable. h defines the _ glapi_table structure, which includes all the gl * function pointer member variables of the OpenGL release function. Basically, the Code body of the function released in the gl * series obtains the address of the current _ glapi_Dispatch member, call the function pointer address pointed to by the Member. The assignment of these members is done when the _ mesa_initialize_context function is executed. Here, call _ glapi_set_dispatch to match _ glapi_Dispatch with the specific corresponding function address.
If _ mesa_make_current is not called to associate the two, _ glapi_Dispatch points to _ glapi_noop_table. If NULL is used to call _ mesa_make_current, _ glapi_Dispatch points to _ glapi_noop_table.
The global variable _ glapi_noop_table in the file domain is in glapi. c contains glapitemp. h define macro replacement to declare the definition. On the one hand, the macro replacement defines a group of empty gl * functions that only warn and do not do anything. The first is Noop *, like their functions, these function pointers are then collected to indicate the value of the _ glapi_noop_table variable. Obviously, if the user does not call wglMakeCurrent beforehand to associate it with the available hglrc, therefore, gl * series functions should not be used.
The operations on the frame cache area will not be followed for the time being.
Now let's look back at the members related to _ glapi_table in the GLcontext structure and their initialization values:
// mtypes.h /*2893*/ struct __GLcontextRec/*2894*/ { // ....../*2898*/ /** \name API function pointer tables *//*2899*/ /*@{*//*2900*/ struct _glapi_table *Save;/**< Display list save functions *//*2901*/ struct _glapi_table *Exec;/**< Execute functions *//*2902*/ struct _glapi_table *CurrentDispatch; /**< == Save or Exec !! *//*2903*/ /*@}*/ // ....../*3094*/ };
_ GLcontextRec is the GLcontext structure. Members Save and Exec are initialized when _ mesa_initialize_context. Many gl * release functions set the corresponding function pointer address here, the following code tries to figure out the specific work done by the function:
_ Mesa_initialize_context/context. c from row 843rd to row 933 (GLcontext * ctx, const GLvisual * visual, GLcontext * share_list, const struct dd_function_table * driverFunctions, void * driverContext) {struct gl_shared_state * shared; /* ASSERT (driverContext); */assert (driverFunctions-> NewTextureObject); assert (driverFunctions-> FreeTexImageData);/* misc one-time initializations */one _ Time_init (ctx); ctx-> Visual = * visual; ctx-> DrawBuffer = NULL; ctx-> ReadBuffer = NULL; ctx-> WinSysDrawBuffer = NULL; ctx-> WinSysReadBuffer = NULL;/* Plug in driver functions and context pointer here. * This is important because when we call alloc_shared_state () below * we'll call ctx-> Driver. newTextureObject () to create the default * textures. */ctx-> Driver = * driverFunctions; ctx-> DriverCtx = DriverContext; if (cmd_list) {/* share state with another context */shared = cmd_list-> Shared;} else {/* allocate new, unshared state */shared = _ mesa_alloc_shared_state (ctx); if (! Shared) return GL_FALSE;} _ glthread_LOCK_MUTEX (shared-> Mutex); ctx-> Shared = shared; shared-> RefCount ++; _ glthread_UNLOCK_MUTEX (shared-> Mutex ); if (! Init_attrib_groups (ctx) {_ mesa_free_shared_state (ctx, ctx-> Shared); return GL_FALSE;}/* setup the API dispatch tables */ctx-> Exec = alloc_dispatch_table (); ctx-> Save = alloc_dispatch_table (); if (! Ctx-> Exec |! Ctx-> Save) {_ mesa_free_shared_state (ctx, ctx-> Shared); if (ctx-> Exec) _ mesa_free (ctx-> Exec); return GL_FALSE ;} # if FEATURE_dispatch _ mesa_init_exec_table (ctx-> Exec); # endif ctx-> CurrentDispatch = ctx-> Exec; # if FEATURE_dlist _ mesa_init_dlist_table (ctx-> Save ); _ mesa_install_save_vtxfmt (ctx, & ctx-> ListState. listVtxfmt); # endif/* Neutral tnl module stuff */_ mesa_init_exec_vtxfmt (ctx); ctx-> TnlModu Le. Current = NULL; ctx-> TnlModule. SwapCount = 0; ctx-> FragmentProgram. _ MaintainTexEnvProgram = (_ mesa_getenv ("MESA_TEX_PROG ")! = NULL); ctx-> VertexProgram. _ MaintainTnlProgram = (_ mesa_getenv ("MESA_TNL_PROG ")! = NULL); if (ctx-> VertexProgram. _ MaintainTnlProgram) {/* this is required... */ctx-> FragmentProgram. _ MaintainTexEnvProgram = GL_TRUE;} # ifdef FEATURE_extra_context_init _ mesa_initialize_context_extra (ctx); # endif ctx-> FirstTimeCurrent = GL_TRUE; return GL_TRUE ;}
Row 3: apply for the _ glapi_table structure, initialize with a warning function pointer, and assign it to ctx-> Exec. The 896th rows are the same;
Row 3: Call the _ mesa_init_exec_table function of Row 3 in api_exec.c to set the pointer of each member of ctx-> Exec to the corresponding engineering function;
Row 3: sets the current function Shard to point to ctx-> Exec;
Rows 908th and 909th initialize ctx-> Save and do not parse the data temporarily;
The second line is to call the _ mesa_init_exec_vtxfmt function in vtxfmt. c to set the initialization of the member function pointer corresponding to the GLvertexformat structure in ctx-> Exec;
The GLvertexformat structure is defined in the dd. h header file. All the functions it contains are functions that may be used between glBegin () and glEnd.
Neutral_vtxfmt is a file domain global variable defined by vtxfmt_tmp.h in the definition macro vtxfmt_tmp.h. The Code bodies of these functions are similar and it is estimated that they interact with the tnl module;
Lines 913rd and 914 indicate that no Member values have been exchanged between the vtxfmt and tnl modules.