void GLAPIENTRY _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) { GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)"); return; } if (!renderbuffers) return; first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n); for (i = 0; i < n; i++) { GLuint name = first + i; renderbuffers[i] = name; /* insert dummy placeholder into hash table */ _glthread_LOCK_MUTEX(ctx->Shared->Mutex); _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); } }
/** * Generate a list of new program identifiers. * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ void _mesa_GenProgramsNV(GLsizei n, GLuint *ids) { GLuint first; GLuint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramsNV"); return; } if (!ids) return; first = _mesa_HashFindFreeKeyBlock(ctx->Shared->VertexPrograms, n); for (i = 0; i < (GLuint) n; i++) { struct vp_program *vprog = CALLOC_STRUCT(vp_program); if (!vprog) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramsNV"); return; } vprog->RefCount = 1; _mesa_HashInsert(ctx->Shared->VertexPrograms, first + i, vprog); } /* Return the program names */ for (i = 0; i < (GLuint) n; i++) { ids[i] = first + i; } }
/** * Generate a list of new program identifiers. * \note Not compiled into display lists. * \note Called by both glGenProgramsNV and glGenProgramsARB. */ void GLAPIENTRY _mesa_GenPrograms(GLsizei n, GLuint *ids) { GLuint first; GLuint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms"); return; } if (!ids) return; first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n); /* Insert pointer to dummy program as placeholder */ for (i = 0; i < (GLuint) n; i++) { _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram); } /* Return the program names */ for (i = 0; i < (GLuint) n; i++) { ids[i] = first + i; } }
void GLAPIENTRY _mesa_GenQueriesARB(GLsizei n, GLuint *ids) { GLuint first; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); return; } /* No query objects can be active at this time! */ if (ctx->Query.CurrentOcclusionObject || ctx->Query.CurrentTimerObject) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB"); return; } first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n); if (first) { GLsizei i; for (i = 0; i < n; i++) { struct gl_query_object *q = ctx->Driver.NewQueryObject(ctx, first + i); if (!q) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); return; } ids[i] = first + i; _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q); } } }
void GLAPIENTRY _mesa_GenSamplers(GLsizei count, GLuint *samplers) { GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glGenSamplers(%d)\n", count); if (count < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers"); return; } if (!samplers) return; first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count); /* Insert the ID and pointer to new sampler object into hash table */ for (i = 0; i < count; i++) { struct gl_sampler_object *sampObj = ctx->Driver.NewSamplerObject(ctx, first + i); _mesa_HashInsert(ctx->Shared->SamplerObjects, first + i, sampObj); samplers[i] = first + i; } }
static void create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers, const char *caller) { GLuint first; GLint i; if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "%s(%d)\n", caller, count); if (count < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller); return; } if (!samplers) return; first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count); /* Insert the ID and pointer to new sampler object into hash table */ for (i = 0; i < count; i++) { struct gl_sampler_object *sampObj = ctx->Driver.NewSamplerObject(ctx, first + i); _mesa_HashInsert(ctx->Shared->SamplerObjects, first + i, sampObj); samplers[i] = first + i; } }
/** * Generate a set of unique array object IDs and store them in \c arrays. * Helper for _mesa_GenVertexArrays[APPLE]() functions below. * \param n Number of IDs to generate. * \param arrays Array of \c n locations to store the IDs. * \param vboOnly Will arrays have to reside in VBOs? */ static void gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays) { GLuint first; GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenVertexArraysAPPLE"); return; } if (!arrays) { return; } first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n); /* Allocate new, empty array objects and return identifiers */ for (i = 0; i < n; i++) { struct gl_array_object *obj; GLuint name = first + i; obj = (*ctx->Driver.NewArrayObject)( ctx, name ); if (!obj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE"); return; } save_array_object(ctx, obj); arrays[i] = first + i; } }
static void create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers, const char *caller) { GLuint first; GLint i; if (!samplers) return; _mesa_HashLockMutex(ctx->Shared->SamplerObjects); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count); /* Insert the ID and pointer to new sampler object into hash table */ for (i = 0; i < count; i++) { struct gl_sampler_object *sampObj; GLuint name = first + i; sampObj = ctx->Driver.NewSamplerObject(ctx, name); if (!sampObj) { _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); return; } _mesa_HashInsertLocked(ctx->Shared->SamplerObjects, name, sampObj); samplers[i] = name; } _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); }
/** * Generate a set of unique pipeline object IDs and store them in \c pipelines. * \param n Number of IDs to generate. * \param pipelines pipeline of \c n locations to store the IDs. */ void GLAPIENTRY _mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines) { GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramPipelines(n<0)"); return; } if (!pipelines) { return; } first = _mesa_HashFindFreeKeyBlock(ctx->Pipeline.Objects, n); for (i = 0; i < n; i++) { struct gl_pipeline_object *obj; GLuint name = first + i; obj = _mesa_new_pipeline_object(ctx, name); if (!obj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramPipelines"); return; } save_pipeline_object(ctx, obj); pipelines[i] = first + i; } }
/** * Create new transform feedback objects. Transform feedback objects * encapsulate the state related to transform feedback to allow quickly * switching state (and drawing the results, below). * Part of GL_ARB_transform_feedback2. */ void GLAPIENTRY _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names) { GLuint first; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenTransformFeedbacks(n < 0)"); return; } if (!names) return; /* we don't need contiguous IDs, but this might be faster */ first = _mesa_HashFindFreeKeyBlock(ctx->TransformFeedback.Objects, n); if (first) { GLsizei i; for (i = 0; i < n; i++) { struct gl_transform_feedback_object *obj = ctx->Driver.NewTransformFeedback(ctx, first + i); if (!obj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks"); return; } names[i] = first + i; _mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj); } } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks"); } }
GLuint _mesa_create_program(GLcontext *ctx) { GLuint name; struct gl_shader_program *shProg; name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); shProg = _mesa_new_shader_program(ctx, name); _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg); assert(shProg->RefCount == 1); return name; }
static GLuint create_shader_program(struct gl_context *ctx) { GLuint name; struct gl_shader_program *shProg; name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); shProg = ctx->Driver.NewShaderProgram(ctx, name); _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg); assert(shProg->RefCount == 1); return name; }
static GLuint create_shader(struct gl_context *ctx, GLenum type) { struct gl_shader *sh; GLuint name; if (!validate_shader_target(ctx, type)) { _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)"); return 0; } name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); sh = ctx->Driver.NewShader(ctx, name, type); _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh); return name; }
/** * Generate texture names. * * \param n number of texture names to be generated. * \param textures an array in which will hold the generated texture names. * * \sa glGenTextures(). * * While holding the GenTexturesLock lock, calls _mesa_HashFindFreeKeyBlock() * to find a block of free texture IDs which are stored in \p textures. * Corresponding empty texture objects are also generated. */ void GLAPIENTRY _mesa_GenTextures( GLsizei n, GLuint *textures ) { GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" ); return; } if (!textures) return; /* * This must be atomic (generation and allocation of texture IDs) */ _glthread_LOCK_MUTEX(GenTexturesLock); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n); /* Allocate new, empty texture objects */ for (i = 0; i < n; i++) { struct gl_texture_object *texObj; GLuint name = first + i; GLenum target = 0; texObj = (*ctx->Driver.NewTextureObject)( ctx, name, target); if (!texObj) { _glthread_UNLOCK_MUTEX(GenTexturesLock); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures"); return; } /* insert into hash table */ _glthread_LOCK_MUTEX(ctx->Shared->Mutex); _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj); _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); textures[i] = name; } _glthread_UNLOCK_MUTEX(GenTexturesLock); }
static void create_transform_feedbacks(struct gl_context *ctx, GLsizei n, GLuint *ids, bool dsa) { GLuint first; const char* func; if (dsa) func = "glCreateTransformFeedbacks"; else func = "glGenTransformFeedbacks"; if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); return; } if (!ids) return; /* we don't need contiguous IDs, but this might be faster */ first = _mesa_HashFindFreeKeyBlock(ctx->TransformFeedback.Objects, n); if (first) { GLsizei i; for (i = 0; i < n; i++) { struct gl_transform_feedback_object *obj = ctx->Driver.NewTransformFeedback(ctx, first + i); if (!obj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; } ids[i] = first + i; _mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj); if (dsa) { /* this is normally done at bind time in the non-dsa case */ obj->EverBound = GL_TRUE; } } } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); } }
void _mesa_test_hash_functions(void) { int a, b, c; struct _mesa_HashTable *t; t = _mesa_NewHashTable(); _mesa_HashInsert(t, 501, &a); _mesa_HashInsert(t, 10, &c); _mesa_HashInsert(t, 0xfffffff8, &b); /*_mesa_HashPrint(t);*/ assert(_mesa_HashLookup(t,501)); assert(!_mesa_HashLookup(t,1313)); assert(_mesa_HashFindFreeKeyBlock(t, 100)); _mesa_DeleteHashTable(t); test_hash_walking(); }
/** * Generate a set of unique array object IDs and store them in \c arrays. * * \param n Number of IDs to generate. * \param arrays Array of \c n locations to store the IDs. */ void GLAPIENTRY _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays) { GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenVertexArraysAPPLE"); return; } if (!arrays) { return; } /* * This must be atomic (generation and allocation of array object IDs) */ _glthread_LOCK_MUTEX(ctx->Shared->Mutex); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ArrayObjects, n); /* Allocate new, empty array objects and return identifiers */ for (i = 0; i < n; i++) { struct gl_array_object *obj; GLuint name = first + i; obj = (*ctx->Driver.NewArrayObject)( ctx, name ); if (!obj) { _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE"); return; } _mesa_save_array_object(ctx, obj); arrays[i] = first + i; } _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); }
/** * Generate a set of unique pipeline object IDs and store them in \c pipelines. * \param n Number of IDs to generate. * \param pipelines pipeline of \c n locations to store the IDs. */ static void create_program_pipelines(struct gl_context *ctx, GLsizei n, GLuint *pipelines, bool dsa) { const char *func; GLuint first; GLint i; func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines"; if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "%s (n < 0)", func); return; } if (!pipelines) { return; } first = _mesa_HashFindFreeKeyBlock(ctx->Pipeline.Objects, n); for (i = 0; i < n; i++) { struct gl_pipeline_object *obj; GLuint name = first + i; obj = _mesa_new_pipeline_object(ctx, name); if (!obj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; } if (dsa) { /* make dsa-allocated objects behave like program objects */ obj->EverBound = GL_TRUE; } save_pipeline_object(ctx, obj); pipelines[i] = first + i; } }
/** * Generate a set of unique buffer object IDs and store them in \c buffer. * * \param n Number of IDs to generate. * \param buffer Array of \c n locations to store the IDs. */ void GLAPIENTRY _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) { GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB"); return; } if (!buffer) { return; } /* * This must be atomic (generation and allocation of buffer object IDs) */ _glthread_LOCK_MUTEX(ctx->Shared->Mutex); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); /* Allocate new, empty buffer objects and return identifiers */ for (i = 0; i < n; i++) { struct gl_buffer_object *bufObj; GLuint name = first + i; GLenum target = 0; bufObj = ctx->Driver.NewBufferObject( ctx, name, target ); if (!bufObj) { _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenBuffersARB"); return; } _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, bufObj); buffer[i] = first + i; } _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); }
int main(int argc, char *argv[]) { int a, b, c; struct HashTable *t; _mesa_printf("&a = %p\n", &a); _mesa_printf("&b = %p\n", &b); t = _mesa_NewHashTable(); _mesa_HashInsert(t, 501, &a); _mesa_HashInsert(t, 10, &c); _mesa_HashInsert(t, 0xfffffff8, &b); _mesa_HashPrint(t); _mesa_printf("Find 501: %p\n", _mesa_HashLookup(t,501)); _mesa_printf("Find 1313: %p\n", _mesa_HashLookup(t,1313)); _mesa_printf("Find block of 100: %d\n", _mesa_HashFindFreeKeyBlock(t, 100)); _mesa_DeleteHashTable(t); return 0; }
GLuint _mesa_create_shader(GLcontext *ctx, GLenum type) { struct gl_shader *sh; GLuint name; name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); switch (type) { case GL_FRAGMENT_SHADER: case GL_VERTEX_SHADER: sh = _mesa_new_shader(ctx, name, type); break; default: _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)"); return 0; } _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh); return name; }
/** * Generate a list of new program identifiers. * \note Not compiled into display lists. * \note Called by both glGenProgramsNV and glGenProgramsARB. */ void GLAPIENTRY _mesa_GenPrograms(GLsizei n, GLuint *ids) { GLuint first; GLuint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms"); return; } if (!ids) return; first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n); for (i = 0; i < (GLuint) n; i++) { const int bytes = MAX2(sizeof(struct vertex_program), sizeof(struct fragment_program)); struct program *prog = (struct program *) _mesa_calloc(bytes); if (!prog) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenPrograms"); return; } prog->RefCount = 1; prog->Id = first + i; _mesa_HashInsert(ctx->Shared->Programs, first + i, prog); } /* Return the program names */ for (i = 0; i < (GLuint) n; i++) { ids[i] = first + i; } }
/** * Generate a set of unique array object IDs and store them in \c arrays. * Helper for _mesa_GenVertexArrays[APPLE]() and _mesa_CreateVertexArrays() * below. * * \param n Number of IDs to generate. * \param arrays Array of \c n locations to store the IDs. * \param create Indicates that the objects should also be created. * \param func The name of the GL entry point. */ static void gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays, bool create, const char *func) { GLuint first; GLint i; if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); return; } if (!arrays) { return; } first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n); /* For the sake of simplicity we create the array objects in both * the Gen* and Create* cases. The only difference is the value of * EverBound, which is set to true in the Create* case. */ for (i = 0; i < n; i++) { struct gl_vertex_array_object *obj; GLuint name = first + i; obj = _mesa_new_vao(ctx, name); if (!obj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; } obj->EverBound = create; save_array_object(ctx, obj); arrays[i] = first + i; } }
/** * Generate a set of unique buffer object IDs and store them in \c buffer. * * \param n Number of IDs to generate. * \param buffer Array of \c n locations to store the IDs. */ void GLAPIENTRY _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) { GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glGenBuffers(%d)\n", n); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB"); return; } if (!buffer) { return; } /* * This must be atomic (generation and allocation of buffer object IDs) */ _glthread_LOCK_MUTEX(ctx->Shared->Mutex); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); /* Insert the ID and pointer to dummy buffer object into hash table */ for (i = 0; i < n; i++) { _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, &DummyBufferObject); buffer[i] = first + i; } _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); }