static void GLAPIENTRY _save_End(void) { GET_CURRENT_CONTEXT(ctx); struct vbo_save_context *save = &vbo_context(ctx)->save; GLint i = save->prim_count - 1; ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; save->prim[i].end = 1; save->prim[i].count = (save->vert_count - save->prim[i].start); if (i == (GLint) save->prim_max - 1) { _save_compile_vertex_list(ctx); assert(save->copied.nr == 0); } /* Swap out this vertex format while outside begin/end. Any color, * etc. received between here and the next begin will be compiled * as opcodes. */ if (save->out_of_memory) { _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop); } else { _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); } }
/* Cope with EvalCoord/CallList called within a begin/end object: * -- Flush current buffer * -- Fallback to opcodes for the rest of the begin/end object. */ static void dlist_fallback(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; if (save->vert_count || save->prim_count) { if (save->prim_count > 0) { /* Close off in-progress primitive. */ GLint i = save->prim_count - 1; save->prim[i].count = save->vert_count - save->prim[i].start; } /* Need to replay this display list with loopback, * unfortunately, otherwise this primitive won't be handled * properly: */ save->dangling_attr_ref = 1; _save_compile_vertex_list(ctx); } _save_copy_to_current(ctx); _save_reset_vertex(ctx); _save_reset_counters(ctx); if (save->out_of_memory) { _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop); } else { _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); } ctx->Driver.SaveNeedFlush = 0; }
/* This begin is hooked into ... Updating of * ctx->Driver.CurrentSavePrimitive is already taken care of. */ GLboolean vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint i = save->prim_count++; assert(i < save->prim_max); save->prim[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK; save->prim[i].begin = 1; save->prim[i].end = 0; save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0; save->prim[i].no_current_update = (mode & VBO_SAVE_PRIM_NO_CURRENT_UPDATE) ? 1 : 0; save->prim[i].pad = 0; save->prim[i].start = save->vert_count; save->prim[i].count = 0; save->prim[i].num_instances = 1; if (save->out_of_memory) { _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop); } else { _mesa_install_save_vtxfmt(ctx, &save->vtxfmt); } ctx->Driver.SaveNeedFlush = 1; return GL_TRUE; }
/** * Called via ctx->Driver.NotifySaveBegin() when a glBegin is getting * compiled into a display list. * Updating of ctx->Driver.CurrentSavePrimitive is already taken care of. */ GLboolean vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode) { struct vbo_save_context *save = &vbo_context(ctx)->save; const GLuint i = save->prim_count++; assert(i < save->prim_max); save->prim[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK; save->prim[i].begin = 1; save->prim[i].end = 0; save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0; save->prim[i].no_current_update = (mode & VBO_SAVE_PRIM_NO_CURRENT_UPDATE) ? 1 : 0; save->prim[i].pad = 0; save->prim[i].start = save->vert_count; save->prim[i].count = 0; save->prim[i].num_instances = 1; save->prim[i].base_instance = 0; if (save->out_of_memory) { _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop); } else { _mesa_install_save_vtxfmt(ctx, &save->vtxfmt); } /* We need to call SaveFlushVertices() if there's state change */ ctx->Driver.SaveNeedFlush = GL_TRUE; /* GL_TRUE means we've handled this glBegin here; don't compile a BEGIN * opcode into the display list. */ return GL_TRUE; }
/** * Initialize the display list compiler */ void vbo_save_api_init( struct vbo_save_context *save ) { GLcontext *ctx = save->ctx; GLuint i; save->opcode_vertex_list = _mesa_alloc_opcode( ctx, sizeof(struct vbo_save_vertex_list), vbo_save_playback_vertex_list, vbo_destroy_vertex_list, vbo_print_vertex_list ); ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin; _save_vtxfmt_init( ctx ); _save_current_init( ctx ); /* These will actually get set again when binding/drawing */ for (i = 0; i < VBO_ATTRIB_MAX; i++) save->inputs[i] = &save->arrays[i]; /* Hook our array functions into the outside-begin-end vtxfmt in * ctx->ListState. */ ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf; ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays; ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements; ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements; _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); }
void vbo_save_EndList( GLcontext *ctx ) { struct vbo_save_context *save = &vbo_context(ctx)->save; /* EndList called inside a (saved) Begin/End pair? */ if (ctx->Driver.CurrentSavePrimitive != PRIM_OUTSIDE_BEGIN_END) { if (save->prim_count > 0) { GLint i = save->prim_count - 1; ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; save->prim[i].end = 0; save->prim[i].count = (save->vert_count - save->prim[i].start); } /* Make sure this vertex list gets replayed by the "loopback" * mechanism: */ save->dangling_attr_ref = 1; vbo_save_SaveFlushVertices( ctx ); /* Swap out this vertex format while outside begin/end. Any color, * etc. received between here and the next begin will be compiled * as opcodes. */ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); } unmap_vertex_store( ctx, save->vertex_store ); assert(save->vertex_size == 0); }
/** * Initialize the display list compiler */ void _tnl_save_init( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct tnl_vertex_arrays *tmp = &tnl->save_inputs; GLuint i; for (i = 0; i < _TNL_ATTRIB_MAX; i++) _mesa_vector4f_init( &tmp->Attribs[i], 0, 0); tnl->save.opcode_vertex_list = _mesa_alloc_opcode( ctx, sizeof(struct tnl_vertex_list), _tnl_playback_vertex_list, _tnl_destroy_vertex_list, _tnl_print_vertex_list ); ctx->Driver.NotifySaveBegin = _save_NotifyBegin; _save_vtxfmt_init( ctx ); _save_current_init( ctx ); /* Hook our array functions into the outside-begin-end vtxfmt in * ctx->ListState. */ ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf; ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays; ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements; ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements; _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); }
/* Cope with EvalCoord/CallList called within a begin/end object: * -- Flush current buffer * -- Fallback to opcodes for the rest of the begin/end object. */ static void DO_FALLBACK( GLcontext *ctx ) { struct vbo_save_context *save = &vbo_context(ctx)->save; if (save->vert_count || save->prim_count) { GLint i = save->prim_count - 1; /* Close off in-progress primitive. */ save->prim[i].count = (save->vert_count - save->prim[i].start); /* Need to replay this display list with loopback, * unfortunately, otherwise this primitive won't be handled * properly: */ save->dangling_attr_ref = 1; _save_compile_vertex_list( ctx ); } _save_copy_to_current( ctx ); _save_reset_vertex( ctx ); _save_reset_counters( ctx ); _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); ctx->Driver.SaveNeedFlush = 0; }
void _tnl_wakeup_save_exec( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); _tnl_wakeup_exec( ctx ); _mesa_install_save_vtxfmt( ctx, &tnl->save_vtxfmt ); }
/** * Install VBO vtxfmt functions. * * This function depends on ctx->Version. */ void _mesa_initialize_vbo_vtxfmt(struct gl_context *ctx) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; _mesa_install_exec_vtxfmt(ctx, &exec->vtxfmt); if (ctx->API == API_OPENGL_COMPAT) { _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); } }
/* This begin is hooked into ... Updating of * ctx->Driver.CurrentSavePrimitive is already taken care of. */ GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode ) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint i = save->prim_count++; assert(i < save->prim_max); save->prim[i].mode = mode & ~VBO_SAVE_PRIM_WEAK; save->prim[i].begin = 1; save->prim[i].end = 0; save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0; save->prim[i].pad = 0; save->prim[i].start = save->vert_count; save->prim[i].count = 0; _mesa_install_save_vtxfmt( ctx, &save->vtxfmt ); ctx->Driver.SaveNeedFlush = 1; return GL_TRUE; }
/* This begin is hooked into ... Updating of * ctx->Driver.CurrentSavePrimitive is already taken care of. */ static GLboolean _save_NotifyBegin( GLcontext *ctx, GLenum mode ) { TNLcontext *tnl = TNL_CONTEXT(ctx); if (1) { GLuint i = tnl->save.prim_count++; assert(i < tnl->save.prim_max); tnl->save.prim[i].mode = mode | PRIM_BEGIN; tnl->save.prim[i].start = tnl->save.initial_counter - tnl->save.counter; tnl->save.prim[i].count = 0; _mesa_install_save_vtxfmt( ctx, &tnl->save_vtxfmt ); ctx->Driver.SaveNeedFlush = 1; return GL_TRUE; } else return GL_FALSE; }
static void GLAPIENTRY _save_End( void ) { GET_CURRENT_CONTEXT( ctx ); TNLcontext *tnl = TNL_CONTEXT(ctx); GLint i = tnl->save.prim_count - 1; ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; tnl->save.prim[i].mode |= PRIM_END; tnl->save.prim[i].count = ((tnl->save.initial_counter - tnl->save.counter) - tnl->save.prim[i].start); if (i == (GLint) tnl->save.prim_max - 1) { _save_compile_vertex_list( ctx ); assert(tnl->save.copied.nr == 0); } /* Swap out this vertex format while outside begin/end. Any color, * etc. received between here and the next begin will be compiled * as opcodes. */ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); }
static struct vbo_save_vertex_store * alloc_vertex_store(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; struct vbo_save_vertex_store *vertex_store = CALLOC_STRUCT(vbo_save_vertex_store); /* obj->Name needs to be non-zero, but won't ever be examined more * closely than that. In particular these buffers won't be entered * into the hash and can never be confused with ones visible to the * user. Perhaps there could be a special number for internal * buffers: */ vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID, GL_ARRAY_BUFFER_ARB); if (vertex_store->bufferobj) { save->out_of_memory = !ctx->Driver.BufferData(ctx, GL_ARRAY_BUFFER_ARB, VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat), NULL, GL_STATIC_DRAW_ARB, vertex_store->bufferobj); } else { save->out_of_memory = GL_TRUE; } if (save->out_of_memory) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "internal VBO allocation"); _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop); } vertex_store->buffer = NULL; vertex_store->used = 0; vertex_store->refcount = 1; return vertex_store; }
/** * Initialize a GLcontext struct (rendering context). * * This includes allocating all the other structs and arrays which hang off of * the context by pointers. * Note that the driver needs to pass in its dd_function_table here since * we need to at least call driverFunctions->NewTextureObject to create the * default texture objects. * * Called by _mesa_create_context(). * * Performs the imports and exports callback tables initialization, and * miscellaneous one-time initializations. If no shared context is supplied one * is allocated, and increase its reference count. Setups the GL API dispatch * tables. Initialize the TNL module. Sets the maximum Z buffer depth. * Finally queries the \c MESA_DEBUG and \c MESA_VERBOSE environment variables * for debug flags. * * \param ctx the context to initialize * \param visual describes the visual attributes for this context * \param share_list points to context to share textures, display lists, * etc with, or NULL * \param driverFunctions table of device driver functions for this context * to use * \param driverContext pointer to driver-specific context data */ GLboolean _mesa_initialize_context(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 (share_list) { /* share state with another context */ shared = share_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_save_table(ctx->Save); _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); #endif /* Neutral tnl module stuff */ _mesa_init_exec_vtxfmt( ctx ); ctx->TnlModule.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; }