void _mesa_meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit) { if (blit->VAO) { _mesa_DeleteVertexArrays(1, &blit->VAO); blit->VAO = 0; _mesa_reference_buffer_object(ctx, &blit->buf_obj, NULL); } _mesa_meta_blit_shader_table_cleanup(&blit->shaders_with_depth); _mesa_meta_blit_shader_table_cleanup(&blit->shaders_without_depth); _mesa_DeleteTextures(1, &blit->depthTex.TexObj); blit->depthTex.TexObj = 0; }
void brw_delete_transform_feedback(struct gl_context *ctx, struct gl_transform_feedback_object *obj) { struct brw_transform_feedback_object *brw_obj = (struct brw_transform_feedback_object *) obj; for (unsigned i = 0; i < ARRAY_SIZE(obj->Buffers); i++) { _mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL); } drm_intel_bo_unreference(brw_obj->offset_bo); drm_intel_bo_unreference(brw_obj->prim_count_bo); free(brw_obj); }
/** * Helper for initializing a vertex array. */ static void init_array(struct gl_context *ctx, struct gl_vertex_array *cl, unsigned size, const void *pointer) { memset(cl, 0, sizeof(*cl)); cl->Size = size; cl->Type = GL_FLOAT; cl->Format = GL_RGBA; cl->StrideB = 0; cl->_ElementSize = cl->Size * sizeof(GLfloat); cl->Ptr = pointer; _mesa_reference_buffer_object(ctx, &cl->BufferObj, ctx->Shared->NullBufferObj); }
/** * Initialize texture state for the given context. */ GLboolean _mesa_init_texture(struct gl_context *ctx) { GLuint u; /* Texture group */ ctx->Texture.CurrentUnit = 0; /* multitexture */ /* Appendix F.2 of the OpenGL ES 3.0 spec says: * * "OpenGL ES 3.0 requires that all cube map filtering be * seamless. OpenGL ES 2.0 specified that a single cube map face be * selected and used for filtering." * * Unfortunatley, a call to _mesa_is_gles3 below will only work if * the driver has already computed and set ctx->Version, however drivers * seem to call _mesa_initialize_context (which calls this) early * in the CreateContext hook and _mesa_compute_version much later (since * it needs information about available extensions). So, we will * enable seamless cubemaps by default since GLES2. This should work * for most implementations and drivers that don't support seamless * cubemaps for GLES2 can still disable it. */ ctx->Texture.CubeMapSeamless = ctx->API == API_OPENGLES2; for (u = 0; u < ARRAY_SIZE(ctx->Texture.Unit); u++) init_texture_unit(ctx, u); /* After we're done initializing the context's texture state the default * texture objects' refcounts should be at least * MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1. */ assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount >= MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1); /* Allocate proxy textures */ if (!alloc_proxy_textures( ctx )) return GL_FALSE; /* GL_ARB_texture_buffer_object */ _mesa_reference_buffer_object(ctx, &ctx->Texture.BufferObject, ctx->Shared->NullBufferObj); ctx->Texture.NumCurrentTexUsed = 0; return GL_TRUE; }
/** * Initialize a gl_array_object's arrays. */ void _mesa_initialize_array_object( struct gl_context *ctx, struct gl_array_object *obj, GLuint name ) { GLuint i; obj->Name = name; _glthread_INIT_MUTEX(obj->Mutex); obj->RefCount = 1; /* Init the individual arrays */ for (i = 0; i < Elements(obj->VertexAttrib); i++) { switch (i) { case VERT_ATTRIB_WEIGHT: init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_WEIGHT], 1, GL_FLOAT); break; case VERT_ATTRIB_NORMAL: init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_NORMAL], 3, GL_FLOAT); break; case VERT_ATTRIB_COLOR1: init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_COLOR1], 3, GL_FLOAT); break; case VERT_ATTRIB_FOG: init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_FOG], 1, GL_FLOAT); break; case VERT_ATTRIB_COLOR_INDEX: init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX], 1, GL_FLOAT); break; case VERT_ATTRIB_EDGEFLAG: init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_EDGEFLAG], 1, GL_BOOL); break; #if FEATURE_point_size_array case VERT_ATTRIB_POINT_SIZE: init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_POINT_SIZE], 1, GL_FLOAT); break; #endif default: init_array(ctx, &obj->VertexAttrib[i], 4, GL_FLOAT); break; } } _mesa_reference_buffer_object(ctx, &obj->ElementArrayBufferObj, ctx->Shared->NullBufferObj); }
static void init_array(struct gl_context *ctx, struct gl_client_array *array, GLint size, GLint type) { array->Size = size; array->Type = type; array->Stride = 0; array->StrideB = 0; array->Ptr = NULL; array->Enabled = GL_FALSE; array->Normalized = GL_FALSE; array->Integer = GL_FALSE; array->_ElementSize = size * _mesa_sizeof_type(type); /* Vertex array buffers */ _mesa_reference_buffer_object(ctx, &array->BufferObj, ctx->Shared->NullBufferObj); }
/** * Copy one client vertex array to another. */ void _mesa_copy_client_array(struct gl_context *ctx, struct gl_client_array *dst, struct gl_client_array *src) { dst->Size = src->Size; dst->Type = src->Type; dst->Stride = src->Stride; dst->StrideB = src->StrideB; dst->Ptr = src->Ptr; dst->Enabled = src->Enabled; dst->Normalized = src->Normalized; dst->Integer = src->Integer; dst->_ElementSize = src->_ElementSize; _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj); dst->_MaxElement = src->_MaxElement; }
GLboolean _vbo_CreateContext(struct gl_context *ctx) { struct vbo_context *vbo = CALLOC_STRUCT(vbo_context); ctx->vbo_context = vbo; /* Initialize the arrayelt helper */ if (!ctx->aelt_context && !_ae_create_context(ctx)) { return GL_FALSE; } vbo->binding.Offset = 0; vbo->binding.Stride = 0; vbo->binding.InstanceDivisor = 0; _mesa_reference_buffer_object(ctx, &vbo->binding.BufferObj, ctx->Shared->NullBufferObj); init_legacy_currval(ctx); init_generic_currval(ctx); init_mat_currval(ctx); _vbo_init_inputs(&vbo->draw_arrays); vbo_set_indirect_draw_func(ctx, vbo_draw_indirect_prims); /* make sure all VBO_ATTRIB_ values can fit in an unsigned byte */ STATIC_ASSERT(VBO_ATTRIB_MAX <= 255); /* Hook our functions into exec and compile dispatch tables. These * will pretty much be permanently installed, which means that the * vtxfmt mechanism can be removed now. */ vbo_exec_init(ctx); if (ctx->API == API_OPENGL_COMPAT) vbo_save_init(ctx); vbo->VAO = _mesa_new_vao(ctx, ~((GLuint)0)); /* The exec VAO assumes to have all arributes bound to binding 0 */ for (unsigned i = 0; i < VERT_ATTRIB_MAX; ++i) _mesa_vertex_attrib_binding(ctx, vbo->VAO, i, 0, false); _math_init_eval(); return GL_TRUE; }
static void init_mat_currval(struct gl_context *ctx) { struct vbo_context *vbo = vbo_context(ctx); struct gl_client_array *arrays = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT]; GLuint i; ASSERT(NR_MAT_ATTRIBS == MAT_ATTRIB_MAX); memset(arrays, 0, sizeof(*arrays) * NR_MAT_ATTRIBS); /* Set up a constant (StrideB == 0) array for each current * attribute: */ for (i = 0; i < NR_MAT_ATTRIBS; i++) { struct gl_client_array *cl = &arrays[i]; /* Size is fixed for the material attributes, for others will * be determined at runtime: */ switch (i - VERT_ATTRIB_GENERIC0) { case MAT_ATTRIB_FRONT_SHININESS: case MAT_ATTRIB_BACK_SHININESS: cl->Size = 1; break; case MAT_ATTRIB_FRONT_INDEXES: case MAT_ATTRIB_BACK_INDEXES: cl->Size = 3; break; default: cl->Size = 4; break; } cl->Ptr = (const void *)ctx->Light.Material.Attrib[i]; cl->Type = GL_FLOAT; cl->Format = GL_RGBA; cl->Stride = 0; cl->StrideB = 0; cl->Enabled = 1; cl->_ElementSize = cl->Size * sizeof(GLfloat); _mesa_reference_buffer_object(ctx, &cl->BufferObj, ctx->Shared->NullBufferObj); } }
/** * Initialize a gl_vertex_array_object's arrays. */ void _mesa_initialize_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj, GLuint name) { GLuint i; obj->Name = name; mtx_init(&obj->Mutex, mtx_plain); obj->RefCount = 1; /* Init the individual arrays */ for (i = 0; i < ARRAY_SIZE(obj->VertexAttrib); i++) { switch (i) { case VERT_ATTRIB_WEIGHT: init_array(ctx, obj, VERT_ATTRIB_WEIGHT, 1, GL_FLOAT); break; case VERT_ATTRIB_NORMAL: init_array(ctx, obj, VERT_ATTRIB_NORMAL, 3, GL_FLOAT); break; case VERT_ATTRIB_COLOR1: init_array(ctx, obj, VERT_ATTRIB_COLOR1, 3, GL_FLOAT); break; case VERT_ATTRIB_FOG: init_array(ctx, obj, VERT_ATTRIB_FOG, 1, GL_FLOAT); break; case VERT_ATTRIB_COLOR_INDEX: init_array(ctx, obj, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT); break; case VERT_ATTRIB_EDGEFLAG: init_array(ctx, obj, VERT_ATTRIB_EDGEFLAG, 1, GL_BOOL); break; case VERT_ATTRIB_POINT_SIZE: init_array(ctx, obj, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT); break; default: init_array(ctx, obj, i, 4, GL_FLOAT); break; } } _mesa_reference_buffer_object(ctx, &obj->IndexBufferObj, ctx->Shared->NullBufferObj); }
static void init_array(GLcontext *ctx, struct gl_client_array *array, GLint size, GLint type) { array->Size = size; array->Type = type; array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */ array->Stride = 0; array->StrideB = 0; array->Ptr = NULL; array->Enabled = GL_FALSE; array->Normalized = GL_FALSE; #if FEATURE_ARB_vertex_buffer_object /* Vertex array buffers */ _mesa_reference_buffer_object(ctx, &array->BufferObj, ctx->Shared->NullBufferObj); #endif }
void vbo_exec_vtx_init( struct vbo_exec_context *exec ) { GLcontext *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); GLuint i; /* Allocate a buffer object. Will just reuse this object * continuously, unless vbo_use_buffer_objects() is called to enable * use of real VBOs. */ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, ctx->Shared->NullBufferObj); ASSERT(!exec->vtx.buffer_map); exec->vtx.buffer_map = (GLfloat *)ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE, 64); exec->vtx.buffer_ptr = exec->vtx.buffer_map; vbo_exec_vtxfmt_init( exec ); /* Hook our functions into the dispatch table. */ _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt ); for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { ASSERT(i < Elements(exec->vtx.attrsz)); exec->vtx.attrsz[i] = 0; ASSERT(i < Elements(exec->vtx.active_sz)); exec->vtx.active_sz[i] = 0; } for (i = 0 ; i < VERT_ATTRIB_MAX; i++) { ASSERT(i < Elements(exec->vtx.inputs)); ASSERT(i < Elements(exec->vtx.arrays)); exec->vtx.inputs[i] = &exec->vtx.arrays[i]; } { struct gl_client_array *arrays = exec->vtx.arrays; memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); } exec->vtx.vertex_size = 0; }
void _mesa_meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx, struct gen_mipmap_state *mipmap) { if (mipmap->VAO == 0) return; _mesa_DeleteVertexArrays(1, &mipmap->VAO); mipmap->VAO = 0; _mesa_reference_buffer_object(ctx, &mipmap->buf_obj, NULL); _mesa_DeleteSamplers(1, &mipmap->Sampler); mipmap->Sampler = 0; if (mipmap->FBO != 0) { _mesa_DeleteFramebuffers(1, &mipmap->FBO); mipmap->FBO = 0; } _mesa_meta_blit_shader_table_cleanup(&mipmap->shaders); }
static void st_delete_transform_feedback(struct gl_context *ctx, struct gl_transform_feedback_object *obj) { struct st_transform_feedback_object *sobj = st_transform_feedback_object(obj); unsigned i; pipe_so_target_reference(&sobj->draw_count, NULL); /* Unreference targets. */ for (i = 0; i < sobj->num_targets; i++) { pipe_so_target_reference(&sobj->targets[i], NULL); } for (i = 0; i < Elements(sobj->base.Buffers); i++) { _mesa_reference_buffer_object(ctx, &sobj->base.Buffers[i], NULL); } free(obj); }
void brw_meta_fast_clear_free(struct brw_context *brw) { struct brw_fast_clear_state *clear = brw->fast_clear_state; GET_CURRENT_CONTEXT(old_context); if (clear == NULL) return; _mesa_make_current(&brw->ctx, NULL, NULL); _mesa_DeleteVertexArrays(1, &clear->vao); _mesa_reference_buffer_object(&brw->ctx, &clear->buf_obj, NULL); _mesa_reference_shader_program(&brw->ctx, &clear->shader_prog, NULL); free(clear); if (old_context) _mesa_make_current(old_context, old_context->WinSysDrawBuffer, old_context->WinSysReadBuffer); else _mesa_make_current(NULL, NULL, NULL); }
/** * Per-context free/clean-up for transform feedback. */ void _mesa_free_transform_feedback(struct gl_context *ctx) { /* core mesa expects this, even a dummy one, to be available */ assert(ctx->Driver.NewTransformFeedback); _mesa_reference_buffer_object(ctx, &ctx->TransformFeedback.CurrentBuffer, NULL); /* Delete all feedback objects */ _mesa_HashDeleteAll(ctx->TransformFeedback.Objects, delete_cb, ctx); _mesa_DeleteHashTable(ctx->TransformFeedback.Objects); /* Delete the default feedback object */ assert(ctx->Driver.DeleteTransformFeedback); ctx->Driver.DeleteTransformFeedback(ctx, ctx->TransformFeedback.DefaultObject); ctx->TransformFeedback.CurrentObject = NULL; }
void _vbo_DestroyContext( struct gl_context *ctx ) { struct vbo_context *vbo = vbo_context(ctx); if (ctx->aelt_context) { _ae_destroy_context( ctx ); ctx->aelt_context = NULL; } if (vbo) { GLuint i; for (i = 0; i < VBO_ATTRIB_MAX; i++) { _mesa_reference_buffer_object(ctx, &vbo->currval[i].BufferObj, NULL); } vbo_exec_destroy(ctx); vbo_save_destroy(ctx); FREE(vbo); ctx->swtnl_im = NULL; } }
/** * Per-context init for transform feedback. */ void _mesa_init_transform_feedback(struct gl_context *ctx) { /* core mesa expects this, even a dummy one, to be available */ assert(ctx->Driver.NewTransformFeedback); ctx->TransformFeedback.DefaultObject = ctx->Driver.NewTransformFeedback(ctx, 0); assert(ctx->TransformFeedback.DefaultObject->RefCount == 1); reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject, ctx->TransformFeedback.DefaultObject); assert(ctx->TransformFeedback.DefaultObject->RefCount == 2); ctx->TransformFeedback.Objects = _mesa_NewHashTable(); _mesa_reference_buffer_object(ctx, &ctx->TransformFeedback.CurrentBuffer, ctx->Shared->NullBufferObj); }
void _vbo_DestroyContext(struct gl_context *ctx) { struct vbo_context *vbo = vbo_context(ctx); if (ctx->aelt_context) { _ae_destroy_context(ctx); ctx->aelt_context = NULL; } if (vbo) { _mesa_reference_buffer_object(ctx, &vbo->binding.BufferObj, NULL); vbo_exec_destroy(ctx); if (ctx->API == API_OPENGL_COMPAT) vbo_save_destroy(ctx); _mesa_reference_vao(ctx, &vbo->VAO, NULL); free(vbo); ctx->vbo_context = NULL; } }
/** * Helper used by BindBufferRange() and BindBufferBase(). */ static void bind_buffer_range(struct gl_context *ctx, struct gl_transform_feedback_object *obj, GLuint index, struct gl_buffer_object *bufObj, GLintptr offset, GLsizeiptr size, bool dsa) { /* Note: no need to FLUSH_VERTICES or flag NewTransformFeedback, because * transform feedback buffers can't be changed while transform feedback is * active. */ if (!dsa) { /* The general binding point */ _mesa_reference_buffer_object(ctx, &ctx->TransformFeedback.CurrentBuffer, bufObj); } /* The per-attribute binding point */ _mesa_set_transform_feedback_binding(ctx, obj, index, bufObj, offset, size); }
/** * Tell the VBO module to use a real OpenGL vertex buffer object to * store accumulated immediate-mode vertex data. * This replaces the malloced buffer which was created in * vb_exec_vtx_init() below. */ void vbo_use_buffer_objects(struct gl_context *ctx) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; /* Any buffer name but 0 can be used here since this bufferobj won't * go into the bufferobj hashtable. */ GLuint bufName = IMM_BUFFER_NAME; GLenum target = GL_ARRAY_BUFFER_ARB; GLenum usage = GL_STREAM_DRAW_ARB; GLsizei size = VBO_VERT_BUFFER_SIZE; /* Make sure this func is only used once */ assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj); if (exec->vtx.buffer_map) { _mesa_align_free(exec->vtx.buffer_map); exec->vtx.buffer_map = NULL; exec->vtx.buffer_ptr = NULL; } /* Allocate a real buffer object now */ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target); ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj); }
static void init_generic_currval(GLcontext *ctx) { struct vbo_context *vbo = vbo_context(ctx); struct gl_client_array *arrays = vbo->generic_currval; GLuint i; memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS); for (i = 0; i < NR_GENERIC_ATTRIBS; i++) { struct gl_client_array *cl = &arrays[i]; /* This will have to be determined at runtime: */ cl->Size = 1; cl->Type = GL_FLOAT; cl->Format = GL_RGBA; cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]; cl->Stride = 0; cl->StrideB = 0; cl->Enabled = 1; _mesa_reference_buffer_object(ctx, &cl->BufferObj, ctx->Shared->NullBufferObj); } }
/** * Bind the specified target to buffer for the specified context. */ static void bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer) { struct gl_buffer_object *oldBufObj; struct gl_buffer_object *newBufObj = NULL; struct gl_buffer_object **bindTarget = NULL; switch (target) { case GL_ARRAY_BUFFER_ARB: bindTarget = &ctx->Array.ArrayBufferObj; break; case GL_ELEMENT_ARRAY_BUFFER_ARB: bindTarget = &ctx->Array.ElementArrayBufferObj; break; case GL_PIXEL_PACK_BUFFER_EXT: bindTarget = &ctx->Pack.BufferObj; break; case GL_PIXEL_UNPACK_BUFFER_EXT: bindTarget = &ctx->Unpack.BufferObj; break; case GL_COPY_READ_BUFFER: if (ctx->Extensions.ARB_copy_buffer) { bindTarget = &ctx->CopyReadBuffer; } break; case GL_COPY_WRITE_BUFFER: if (ctx->Extensions.ARB_copy_buffer) { bindTarget = &ctx->CopyWriteBuffer; } break; default: ; /* no-op / we'll hit the follow error test next */ } if (!bindTarget) { _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)"); return; } /* Get pointer to old buffer object (to be unbound) */ oldBufObj = get_buffer(ctx, target); if (oldBufObj && oldBufObj->Name == buffer) return; /* rebinding the same buffer object- no change */ /* * Get pointer to new buffer object (newBufObj) */ if (buffer == 0) { /* The spec says there's not a buffer object named 0, but we use * one internally because it simplifies things. */ newBufObj = ctx->Shared->NullBufferObj; } else { /* non-default buffer object */ newBufObj = _mesa_lookup_bufferobj(ctx, buffer); if (!newBufObj) { /* if this is a new buffer object id, allocate a buffer object now */ ASSERT(ctx->Driver.NewBufferObject); newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target); if (!newBufObj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB"); return; } _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, newBufObj); } } /* bind new buffer */ _mesa_reference_buffer_object(ctx, bindTarget, newBufObj); /* Pass BindBuffer call to device driver */ if (ctx->Driver.BindBuffer) ctx->Driver.BindBuffer( ctx, target, newBufObj ); }
void vbo_exec_vtx_init( struct vbo_exec_context *exec ) { struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); GLuint i; /* Allocate a buffer object. Will just reuse this object * continuously, unless vbo_use_buffer_objects() is called to enable * use of real VBOs. */ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, ctx->Shared->NullBufferObj); ASSERT(!exec->vtx.buffer_map); exec->vtx.buffer_map = (GLfloat *)_mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64); exec->vtx.buffer_ptr = exec->vtx.buffer_map; vbo_exec_vtxfmt_init( exec ); _mesa_noop_vtxfmt_init(&exec->vtxfmt_noop); /* Hook our functions into the dispatch table. */ _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { ASSERT(i < Elements(exec->vtx.attrsz)); exec->vtx.attrsz[i] = 0; ASSERT(i < Elements(exec->vtx.active_sz)); exec->vtx.active_sz[i] = 0; } for (i = 0 ; i < VERT_ATTRIB_MAX; i++) { ASSERT(i < Elements(exec->vtx.inputs)); ASSERT(i < Elements(exec->vtx.arrays)); exec->vtx.inputs[i] = &exec->vtx.arrays[i]; } { struct gl_client_array *arrays = exec->vtx.arrays; unsigned i; memcpy(arrays, vbo->legacy_currval, VERT_ATTRIB_FF_MAX * sizeof(arrays[0])); for (i = 0; i < VERT_ATTRIB_FF_MAX; ++i) { struct gl_client_array *array; array = &arrays[VERT_ATTRIB_FF(i)]; array->BufferObj = NULL; _mesa_reference_buffer_object(ctx, &arrays->BufferObj, vbo->legacy_currval[i].BufferObj); } memcpy(arrays + VERT_ATTRIB_GENERIC(0), vbo->generic_currval, VERT_ATTRIB_GENERIC_MAX * sizeof(arrays[0])); for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; ++i) { struct gl_client_array *array; array = &arrays[VERT_ATTRIB_GENERIC(i)]; array->BufferObj = NULL; _mesa_reference_buffer_object(ctx, &array->BufferObj, vbo->generic_currval[i].BufferObj); } } exec->vtx.vertex_size = 0; exec->begin_vertices_flags = FLUSH_UPDATE_CURRENT; }
/** * Free the data associated with the given context. * * But doesn't free the GLcontext struct itself. * * \sa _mesa_initialize_context() and init_attrib_groups(). */ void _mesa_free_context_data( GLcontext *ctx ) { GLint RefCount; if (!_mesa_get_current_context()){ /* No current context, but we may need one in order to delete * texture objs, etc. So temporarily bind the context now. */ _mesa_make_current(ctx, NULL, NULL); } /* unreference WinSysDraw/Read buffers */ _mesa_reference_framebuffer(&ctx->WinSysDrawBuffer, NULL); _mesa_reference_framebuffer(&ctx->WinSysReadBuffer, NULL); _mesa_reference_framebuffer(&ctx->DrawBuffer, NULL); _mesa_reference_framebuffer(&ctx->ReadBuffer, NULL); _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL); _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); _mesa_free_attrib_data(ctx); _mesa_free_lighting_data( ctx ); _mesa_free_eval_data( ctx ); _mesa_free_texture_data( ctx ); _mesa_free_matrix_data( ctx ); _mesa_free_viewport_data( ctx ); _mesa_free_colortables_data( ctx ); _mesa_free_program_data(ctx); _mesa_free_shader_state(ctx); _mesa_free_queryobj_data(ctx); #if FEATURE_ARB_sync _mesa_free_sync_data(ctx); #endif _mesa_free_varray_data(ctx); _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj); #if FEATURE_ARB_pixel_buffer_object _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL); _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL); #endif #if FEATURE_ARB_vertex_buffer_object _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL); _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL); #endif /* free dispatch tables */ _mesa_free(ctx->Exec); _mesa_free(ctx->Save); /* Shared context state (display lists, textures, etc) */ _glthread_LOCK_MUTEX(ctx->Shared->Mutex); RefCount = --ctx->Shared->RefCount; _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); assert(RefCount >= 0); if (RefCount == 0) { /* free shared state */ _mesa_free_shared_state( ctx, ctx->Shared ); } /* needs to be after freeing shared state */ _mesa_free_display_list_data(ctx); if (ctx->Extensions.String) _mesa_free((void *) ctx->Extensions.String); /* unbind the context if it's currently bound */ if (ctx == _mesa_get_current_context()) { _mesa_make_current(NULL, NULL, NULL); } }
/* TODO: populate these as the vertex is defined: */ static void vbo_exec_bind_arrays( struct gl_context *ctx ) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct gl_client_array *arrays = exec->vtx.arrays; const GLuint count = exec->vtx.vert_count; const GLuint *map; GLuint attr; GLbitfield64 varying_inputs = 0x0; /* Install the default (ie Current) attributes first, then overlay * all active ones. */ switch (get_program_mode(exec->ctx)) { case VP_NONE: for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) { exec->vtx.inputs[attr] = &vbo->legacy_currval[attr]; } for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { ASSERT(VERT_ATTRIB_GENERIC(attr) < Elements(exec->vtx.inputs)); exec->vtx.inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->mat_currval[attr]; } map = vbo->map_vp_none; break; case VP_NV: case VP_ARB: /* The aliasing of attributes for NV vertex programs has already * occurred. NV vertex programs cannot access material values, * nor attributes greater than VERT_ATTRIB_TEX7. */ for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) { exec->vtx.inputs[attr] = &vbo->legacy_currval[attr]; } for (attr = 0; attr < VERT_ATTRIB_GENERIC_MAX; attr++) { ASSERT(VERT_ATTRIB_GENERIC(attr) < Elements(exec->vtx.inputs)); exec->vtx.inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->generic_currval[attr]; } map = vbo->map_vp_arb; /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read. * In that case we effectively need to route the data from * glVertexAttrib(0, val) calls to feed into the GENERIC0 input. */ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 && (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) { exec->vtx.inputs[VERT_ATTRIB_GENERIC0] = exec->vtx.inputs[0]; exec->vtx.attrsz[VERT_ATTRIB_GENERIC0] = exec->vtx.attrsz[0]; exec->vtx.attrptr[VERT_ATTRIB_GENERIC0] = exec->vtx.attrptr[0]; exec->vtx.attrsz[0] = 0; } break; default: assert(0); } /* Make all active attributes (including edgeflag) available as * arrays of floats. */ for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) { const GLuint src = map[attr]; if (exec->vtx.attrsz[src]) { GLsizeiptr offset = (GLbyte *)exec->vtx.attrptr[src] - (GLbyte *)exec->vtx.vertex; /* override the default array set above */ ASSERT(attr < Elements(exec->vtx.inputs)); ASSERT(attr < Elements(exec->vtx.arrays)); /* arrays[] */ exec->vtx.inputs[attr] = &arrays[attr]; if (_mesa_is_bufferobj(exec->vtx.bufferobj)) { /* a real buffer obj: Ptr is an offset, not a pointer*/ assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */ assert(offset >= 0); arrays[attr].Ptr = (GLubyte *)exec->vtx.bufferobj->Offset + offset; } else { /* Ptr into ordinary app memory */ arrays[attr].Ptr = (GLubyte *)exec->vtx.buffer_map + offset; } arrays[attr].Size = exec->vtx.attrsz[src]; arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Type = GL_FLOAT; arrays[attr].Format = GL_RGBA; arrays[attr].Enabled = 1; arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat); _mesa_reference_buffer_object(ctx, &arrays[attr].BufferObj, exec->vtx.bufferobj); arrays[attr]._MaxElement = count; /* ??? */ varying_inputs |= VERT_BIT(attr); ctx->NewState |= _NEW_ARRAY; } } _mesa_set_varying_vp_inputs( ctx, varying_inputs ); }
void vbo_exec_vtx_init( struct vbo_exec_context *exec ) { struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); GLuint i; /* Allocate a buffer object. Will just reuse this object * continuously, unless vbo_use_buffer_objects() is called to enable * use of real VBOs. */ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, ctx->Shared->NullBufferObj); assert(!exec->vtx.buffer_map); exec->vtx.buffer_map = _mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64); exec->vtx.buffer_ptr = exec->vtx.buffer_map; vbo_exec_vtxfmt_init( exec ); _mesa_noop_vtxfmt_init(&exec->vtxfmt_noop); exec->vtx.enabled = 0; for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { assert(i < ARRAY_SIZE(exec->vtx.attrsz)); exec->vtx.attrsz[i] = 0; assert(i < ARRAY_SIZE(exec->vtx.attrtype)); exec->vtx.attrtype[i] = GL_FLOAT; assert(i < ARRAY_SIZE(exec->vtx.active_sz)); exec->vtx.active_sz[i] = 0; } for (i = 0 ; i < VERT_ATTRIB_MAX; i++) { assert(i < ARRAY_SIZE(exec->vtx.inputs)); assert(i < ARRAY_SIZE(exec->vtx.arrays)); exec->vtx.inputs[i] = &exec->vtx.arrays[i]; } { struct gl_client_array *arrays = exec->vtx.arrays; unsigned i; memcpy(arrays, &vbo->currval[VBO_ATTRIB_POS], VERT_ATTRIB_FF_MAX * sizeof(arrays[0])); for (i = 0; i < VERT_ATTRIB_FF_MAX; ++i) { struct gl_client_array *array; array = &arrays[VERT_ATTRIB_FF(i)]; array->BufferObj = NULL; _mesa_reference_buffer_object(ctx, &array->BufferObj, vbo->currval[VBO_ATTRIB_POS+i].BufferObj); } memcpy(arrays + VERT_ATTRIB_GENERIC(0), &vbo->currval[VBO_ATTRIB_GENERIC0], VERT_ATTRIB_GENERIC_MAX * sizeof(arrays[0])); for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; ++i) { struct gl_client_array *array; array = &arrays[VERT_ATTRIB_GENERIC(i)]; array->BufferObj = NULL; _mesa_reference_buffer_object(ctx, &array->BufferObj, vbo->currval[VBO_ATTRIB_GENERIC0+i].BufferObj); } } exec->vtx.vertex_size = 0; exec->begin_vertices_flags = FLUSH_UPDATE_CURRENT; }
/** * Delete a set of buffer objects. * * \param n Number of buffer objects to delete. * \param ids Array of \c n buffer object IDs. */ void GLAPIENTRY _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) { GET_CURRENT_CONTEXT(ctx); GLsizei i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)"); return; } _glthread_LOCK_MUTEX(ctx->Shared->Mutex); for (i = 0; i < n; i++) { struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]); if (bufObj) { struct gl_array_object *arrayObj = ctx->Array.ArrayObj; GLuint j; ASSERT(bufObj->Name == ids[i]); if (bufObj->Pointer) { /* if mapped, unmap it now */ ctx->Driver.UnmapBuffer(ctx, 0, bufObj); bufObj->AccessFlags = DEFAULT_ACCESS; bufObj->Pointer = NULL; } /* unbind any vertex pointers bound to this buffer */ unbind(ctx, &arrayObj->Vertex.BufferObj, bufObj); unbind(ctx, &arrayObj->Weight.BufferObj, bufObj); unbind(ctx, &arrayObj->Normal.BufferObj, bufObj); unbind(ctx, &arrayObj->Color.BufferObj, bufObj); unbind(ctx, &arrayObj->SecondaryColor.BufferObj, bufObj); unbind(ctx, &arrayObj->FogCoord.BufferObj, bufObj); unbind(ctx, &arrayObj->Index.BufferObj, bufObj); unbind(ctx, &arrayObj->EdgeFlag.BufferObj, bufObj); for (j = 0; j < Elements(arrayObj->TexCoord); j++) { unbind(ctx, &arrayObj->TexCoord[j].BufferObj, bufObj); } for (j = 0; j < Elements(arrayObj->VertexAttrib); j++) { unbind(ctx, &arrayObj->VertexAttrib[j].BufferObj, bufObj); } if (ctx->Array.ArrayBufferObj == bufObj) { _mesa_BindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); } if (ctx->Array.ElementArrayBufferObj == bufObj) { _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); } /* unbind any pixel pack/unpack pointers bound to this buffer */ if (ctx->Pack.BufferObj == bufObj) { _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 ); } if (ctx->Unpack.BufferObj == bufObj) { _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 ); } /* The ID is immediately freed for re-use */ _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name); _mesa_reference_buffer_object(ctx, &bufObj, NULL); } } _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); }
/** * Treat the vertex storage as a VBO, define vertex arrays pointing * into it: */ static void vbo_bind_vertex_list(struct gl_context *ctx, const struct vbo_save_vertex_list *node) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_save_context *save = &vbo->save; struct gl_client_array *arrays = save->arrays; GLuint buffer_offset = node->buffer_offset; const GLuint *map; GLuint attr; GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */ GLenum node_attrtype[VBO_ATTRIB_MAX]; /* copy of node->attrtype[] */ GLbitfield64 varying_inputs = 0x0; memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz)); memcpy(node_attrtype, node->attrtype, sizeof(node->attrtype)); /* Install the default (ie Current) attributes first, then overlay * all active ones. */ switch (get_program_mode(ctx)) { case VP_NONE: for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) { save->inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr]; } for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { save->inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+attr]; } map = vbo->map_vp_none; break; case VP_ARB: for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) { save->inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr]; } for (attr = 0; attr < VERT_ATTRIB_GENERIC_MAX; attr++) { save->inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->currval[VBO_ATTRIB_GENERIC0+attr]; } map = vbo->map_vp_arb; /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read. * In that case we effectively need to route the data from * glVertexAttrib(0, val) calls to feed into the GENERIC0 input. */ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 && (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) { save->inputs[VERT_ATTRIB_GENERIC0] = save->inputs[0]; node_attrsz[VERT_ATTRIB_GENERIC0] = node_attrsz[0]; node_attrtype[VERT_ATTRIB_GENERIC0] = node_attrtype[0]; node_attrsz[0] = 0; } break; default: assert(0); } for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { const GLuint src = map[attr]; if (node_attrsz[src]) { /* override the default array set above */ save->inputs[attr] = &arrays[attr]; arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset; arrays[attr].Size = node_attrsz[src]; arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); arrays[attr].Type = node_attrtype[src]; arrays[attr].Integer = vbo_attrtype_to_integer_flag(node_attrtype[src]); arrays[attr].Format = GL_RGBA; arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat); _mesa_reference_buffer_object(ctx, &arrays[attr].BufferObj, node->vertex_store->bufferobj); assert(arrays[attr].BufferObj->Name); buffer_offset += node_attrsz[src] * sizeof(GLfloat); varying_inputs |= VERT_BIT(attr); } } _mesa_set_varying_vp_inputs( ctx, varying_inputs ); ctx->NewDriverState |= ctx->DriverFlags.NewArray; }
/** * Initialize texture state for the given context. */ GLboolean _mesa_init_texture(struct gl_context *ctx) { GLuint u; /* Texture group */ ctx->Texture.CurrentUnit = 0; /* multitexture */ /* Appendix F.2 of the OpenGL ES 3.0 spec says: * * "OpenGL ES 3.0 requires that all cube map filtering be * seamless. OpenGL ES 2.0 specified that a single cube map face be * selected and used for filtering." * * Unfortunatley, a call to _mesa_is_gles3 below will only work if * the driver has already computed and set ctx->Version, however drivers * seem to call _mesa_initialize_context (which calls this) early * in the CreateContext hook and _mesa_compute_version much later (since * it needs information about available extensions). So, we will * enable seamless cubemaps by default since GLES2. This should work * for most implementations and drivers that don't support seamless * cubemaps for GLES2 can still disable it. */ ctx->Texture.CubeMapSeamless = ctx->API == API_OPENGLES2; for (u = 0; u < ARRAY_SIZE(ctx->Texture.Unit); u++) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u]; GLuint tex; /* initialize current texture object ptrs to the shared default objects */ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) { _mesa_reference_texobj(&texUnit->CurrentTex[tex], ctx->Shared->DefaultTex[tex]); } texUnit->_BoundTextures = 0; } for (u = 0; u < ARRAY_SIZE(ctx->Texture.FixedFuncUnit); u++) { struct gl_fixedfunc_texture_unit *texUnit = &ctx->Texture.FixedFuncUnit[u]; texUnit->EnvMode = GL_MODULATE; ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 ); texUnit->Combine = default_combine_state; texUnit->_EnvMode = default_combine_state; texUnit->_CurrentCombine = & texUnit->_EnvMode; texUnit->TexGenEnabled = 0x0; texUnit->GenS.Mode = GL_EYE_LINEAR; texUnit->GenT.Mode = GL_EYE_LINEAR; texUnit->GenR.Mode = GL_EYE_LINEAR; texUnit->GenQ.Mode = GL_EYE_LINEAR; texUnit->GenS._ModeBit = TEXGEN_EYE_LINEAR; texUnit->GenT._ModeBit = TEXGEN_EYE_LINEAR; texUnit->GenR._ModeBit = TEXGEN_EYE_LINEAR; texUnit->GenQ._ModeBit = TEXGEN_EYE_LINEAR; /* Yes, these plane coefficients are correct! */ ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 ); ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 ); ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 ); ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 ); ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 ); ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 ); ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 ); ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 ); } /* After we're done initializing the context's texture state the default * texture objects' refcounts should be at least * MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1. */ assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount >= MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1); /* Allocate proxy textures */ if (!alloc_proxy_textures( ctx )) return GL_FALSE; /* GL_ARB_texture_buffer_object */ _mesa_reference_buffer_object(ctx, &ctx->Texture.BufferObject, ctx->Shared->NullBufferObj); ctx->Texture.NumCurrentTexUsed = 0; return GL_TRUE; }