/*
 * Add or update an entry in the Global MDVSN cache for a versioning event
 * found in the event list. Reconcile with current contents of the cache
 * if needed.
 *  event: The event containing the versioning information for an update
 */
static void
mdver_globalhandler_add_version(mdver_event *event)
{
    Assert(NULL != event);

    Cache *glob_mdvsn = mdver_get_glob_mdvsn();

    if (mdver_is_nuke_event(event))
    {
        mdver_glob_mdvsn_nuke();
        return;
    }

    mdver_entry mdver = { InvalidOid, INVALID_MD_VERSION, INVALID_MD_VERSION };
    mdver.key = event->key;
    mdver.ddl_version = INVALID_MD_VERSION;
    mdver.dml_version = INVALID_MD_VERSION;

    /* FIXME gcaragea 04/14/2014: Trigger evictions if cache is full (MPP-22923) */
    CacheEntry *acquired_entry = Cache_AcquireEntry(glob_mdvsn, &mdver);
    Assert(NULL != acquired_entry);

    /*
     * We're about to look-up and insert/update a shared cache entry.
     * Grab writer lock in exclusive mode, so that no other backend
     * tries to insert or update the same entry at the same time.
     */
    LWLockAcquire(MDVerWriteLock, LW_EXCLUSIVE);

    CacheEntry *cached_entry = Cache_Lookup(glob_mdvsn, acquired_entry);

    if (NULL != cached_entry)
    {
        mdver_globalhandler_reconcile(event, cached_entry);

        /* Done with the looked-up entry. Release it */
        Cache_Release(glob_mdvsn, cached_entry);
    }
    else
    {
        /* Entry not found, insert new entry */
        mdver_entry *new_mdver_entry = CACHE_ENTRY_PAYLOAD(acquired_entry);

#ifdef MD_VERSIONING_INSTRUMENTATION
        elog(gp_mdversioning_loglevel, "Inserting into GlobalMDVSN entry %d: (%d,%d)",
             event->key,
             (int) event->new_ddl_version, (int) event->new_dml_version);
#endif

        new_mdver_entry->ddl_version = event->new_ddl_version;
        new_mdver_entry->dml_version = event->new_dml_version;

        Cache_Insert(glob_mdvsn, acquired_entry);
    }

    Cache_Release(glob_mdvsn, acquired_entry);
    LWLockRelease(MDVerWriteLock);
}
/*
 * Sweeps through the cache and marks all entries as deleted
 *
 * Returns the number of elements it found and marked deleted.
 */
int32
Cache_Clear(Cache *cache)
{
	Assert(NULL != cache);

	int32 startIdx = cdb_randint(cache->cacheHdr->nEntries - 1, 0);
	int32 entryIdx = startIdx;
	int32 numClearedEntries = 0;

	while (true)
	{
		entryIdx = (entryIdx + 1) % cache->cacheHdr->nEntries;
		if (entryIdx == startIdx)
		{
			/* Completed one loop through the list of all entries. We're done */
			break;
		}

		CacheEntry *crtEntry = Cache_GetEntryByIndex(cache->cacheHdr, entryIdx);

		/* Lock entry so that nobody else changes its state until we're done with it */
		Cache_LockEntry(cache, crtEntry);

		if (crtEntry->state != CACHE_ENTRY_CACHED)
		{
			/* Not interested in free/acquired/deleted entries. Go back and look at next entry */
			Cache_UnlockEntry(cache, crtEntry);
			continue;
		}

		/* Found cached entry */
		Cache_EntryAddRef(cache, crtEntry);

		if (crtEntry->state == CACHE_ENTRY_FREE || crtEntry->state == CACHE_ENTRY_ACQUIRED)
		{
			/* Someone freed up the entry before we had a chance to Add-Ref it. Skip it. */
			Assert(false);
			Cache_EntryDecRef(cache, crtEntry);
			Cache_UnlockEntry(cache, crtEntry);
			continue;
		}

		Cache_RegisterCleanup(cache, crtEntry, true /* isCachedEntry */);

		Cache_Remove(cache, crtEntry);

		/* Done with changing the state. Unlock the entry */
		Cache_UnlockEntry(cache, crtEntry);

		Cache_Release(cache, crtEntry);

		numClearedEntries++;

	}

	return numClearedEntries;
}
/*
 * Look up an entry in the Global MDVSN component.
 * To avoid any concurrency issues, this returns a copy of the entry,
 * palloc'ed in the current memory context. The caller is responsible
 * for freeing this copy.
 *
 * 	 Returns a copy of the entry if found, NULL otherwise.
 *
 */
mdver_entry *
mdver_glob_mdvsn_find(Oid oid)
{

	Assert(NULL != mdver_glob_mdvsn);

	mdver_entry mdver_info;
	mdver_info.key = oid;

	/* FIXME gcaragea 03/18/2014: Trigger evictions if cache is full (MPP-22923) */
	CacheEntry *localEntry = Cache_AcquireEntry(mdver_glob_mdvsn, &mdver_info);
	Assert(NULL != localEntry);

	CacheEntry *cachedEntry = Cache_Lookup(mdver_glob_mdvsn, localEntry);

	/* Release local entry. We don't need it anymore */
	Cache_Release(mdver_glob_mdvsn, localEntry);

	mdver_entry *mdver_copy = NULL;
	if (NULL != cachedEntry)
	{
		/* Found a match. Make a local copy */
		mdver_entry *shared_mdver = (mdver_entry *) CACHE_ENTRY_PAYLOAD(cachedEntry);
		mdver_copy = (mdver_entry *) palloc0(sizeof(mdver_entry));

		/* Lock entry to ensure atomicity of copy */
		Cache_LockEntry(mdver_glob_mdvsn, cachedEntry);

		memcpy(mdver_copy, shared_mdver, sizeof(mdver_entry));

		/* Got the copy, unlock entry */
		Cache_UnlockEntry(mdver_glob_mdvsn, cachedEntry);

		/*
		 * We're also done with the entry, release our pincount on it
		 *
		 * TODO gcaragea 05/02/2014: Are there cases where we need to hold the
		 * entry past this point? (MPP-22923)
		 */
		Cache_Release(mdver_glob_mdvsn, cachedEntry);
	}

	return mdver_copy;
}
示例#4
0
void
R_AliasDrawModel (alight_t *plighting)
{
	int          size;
	finalvert_t *finalverts;

	r_amodels_drawn++;

	if (!(paliashdr = currententity->model->aliashdr))
		paliashdr = Cache_Get (&currententity->model->cache);
	pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model);

	size = (CACHE_SIZE - 1)
		+ sizeof (finalvert_t) * (pmdl->numverts + 1)
		+ sizeof (auxvert_t) * pmdl->numverts;
	finalverts = (finalvert_t *) Hunk_TempAlloc (size);
	if (!finalverts)
		Sys_Error ("R_AliasDrawModel: out of memory");

	// cache align
	pfinalverts = (finalvert_t *)
		(((intptr_t) &finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
	pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1];

	R_AliasSetupSkin ();
	R_AliasSetUpTransform (currententity->trivial_accept);
	R_AliasSetupLighting (plighting);
	R_AliasSetupFrame ();

	r_affinetridesc.drawtype = (currententity->trivial_accept == 3) &&
		r_recursiveaffinetriangles;

	if (!acolormap)
		acolormap = vid.colormap8;

	if (r_affinetridesc.drawtype) {
		D_PolysetUpdateTables ();		// FIXME: precalc...
	} else {
#ifdef USE_INTEL_ASM
		D_Aff8Patch (acolormap);
#endif
	}

	if (currententity != vr_data.view_model)
		ziscale = (float) 0x8000 *(float) 0x10000;
	else
		ziscale = (float) 0x8000 *(float) 0x10000 *3.0;

	if (currententity->trivial_accept && pmdl->ident != HEADER_MDL16)
		R_AliasPrepareUnclippedPoints ();
	else
		R_AliasPreparePoints ();

	if (!currententity->model->aliashdr)
		Cache_Release (&currententity->model->cache);
}
示例#5
0
void
sw32_R_AliasDrawModel (alight_t *plighting)
{
	int         size;
	finalvert_t *finalverts;

	sw32_r_amodels_drawn++;

	if (!(paliashdr = currententity->model->aliashdr))
		paliashdr = Cache_Get (&currententity->model->cache);
	pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model);

	size = (CACHE_SIZE - 1)
		   + sizeof (finalvert_t) * (pmdl->numverts + 1)
		   + sizeof (auxvert_t) * pmdl->numverts;
	finalverts = (finalvert_t *) Hunk_TempAlloc (size);
	if (!finalverts)
		Sys_Error ("R_AliasDrawModel: out of memory");

	// cache align
	pfinalverts = (finalvert_t *)
		(((intptr_t) &finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
	sw32_pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1];

	R_AliasSetupSkin ();
	sw32_R_AliasSetUpTransform (currententity->trivial_accept);
	R_AliasSetupLighting (plighting);
	R_AliasSetupFrame ();

	if (!sw32_acolormap)
		sw32_acolormap = vid.colormap8;
	if (sw32_acolormap == &vid.colormap8 && sw32_r_pixbytes != 1)
	{
		if (sw32_r_pixbytes == 2)
			sw32_acolormap = vid.colormap16;
		else if (sw32_r_pixbytes == 4)
			sw32_acolormap = vid.colormap32;
		else
			Sys_Error("R_AliasDrawmodel: unsupported r_pixbytes %i",
					  sw32_r_pixbytes);
	}

	if (currententity != vr_data.view_model)
		sw32_ziscale = (float) 0x8000 *(float) 0x10000;
	else
		sw32_ziscale = (float) 0x8000 *(float) 0x10000 *3.0;

	if (currententity->trivial_accept)
		R_AliasPrepareUnclippedPoints ();
	else
		R_AliasPreparePoints ();

	if (!currententity->model->aliashdr)
		Cache_Release (&currententity->model->cache);
}
示例#6
0
文件: workfile_mgr.c 项目: LJoNe/gpdb
/*
 * Close a spill file set. If we're planning to re-use it, insert it in the
 * cache. If not, let the cleanup routine delete the files and free up memory.
 */
void
workfile_mgr_close_set(workfile_set *work_set)
{
	Assert(work_set!=NULL);

	elog(gp_workfile_caching_loglevel, "closing workfile set: location: %s, size=" INT64_FORMAT
			" in_progress_size=" INT64_FORMAT,
		 work_set->path,
		 work_set->size, work_set->in_progress_size);

	CacheEntry *cache_entry = CACHE_ENTRY_HEADER(work_set);
	Cache_Release(workfile_mgr_cache, cache_entry);
}
示例#7
0
static void
PrintFrameName (model_t *m, int frame)
{
	aliashdr_t *hdr;
	maliasframedesc_t *pframedesc;

	hdr = Cache_TryGet (&m->cache);
	if (!hdr)
		return;
	pframedesc = &hdr->frames[frame];

	Sys_Printf ("frame %i: %s\n", frame, pframedesc->name);
	Cache_Release (&m->cache);
}
示例#8
0
/*
 * Close a spill file set. If we're planning to re-use it, insert it in the
 * cache. If not, let the cleanup routine delete the files and free up memory.
 */
void
workfile_mgr_close_set(workfile_set *work_set)
{
	Assert(work_set!=NULL);

	elog(gp_workfile_caching_loglevel, "closing workfile set: can_be_reused=%d complete=%d location: %s, size=" INT64_FORMAT
			" in_progress_size=" INT64_FORMAT,
		 work_set->can_be_reused, work_set->complete, work_set->path,
		 work_set->size, work_set->in_progress_size);

	CacheEntry *cache_entry = CACHE_ENTRY_HEADER(work_set);

	if (Cache_IsCached(cache_entry))
	{
		/* Workset came from cache. Just release it, nothing to do */
		Cache_Release(workfile_mgr_cache, cache_entry);
		return;
	}

	if (work_set->complete && work_set->can_be_reused)
	{
		cache_entry->size = work_set->size;

		/* We want to keep this one around. Insert into cache */
		Cache_Insert(workfile_mgr_cache, cache_entry);
		Cache_Release(workfile_mgr_cache, cache_entry);
		return;
	}


	/*
	 * Fall-through case: We need to delete this work_set, as it's not reusable.
	 */
	Assert(!work_set->complete || !work_set->can_be_reused);
	Cache_Release(workfile_mgr_cache, cache_entry);
}
示例#9
0
文件: snd_mem.c 项目: luaman/qforge-1
void
SND_CacheRelease (sfx_t *sfx)
{
	sfxblock_t *block = sfx->data.block;
	// due to the possibly asynchronous nature of the mixer, the cache
	// may have been flushed behind our backs
	if (block->cache.data) {
		if (!Cache_ReadLock (&block->cache)) {
			Sys_Printf ("WARNING: taniwha screwed up in the sound engine: %s\n",
						sfx->name);
			return;
		}
		Cache_Release (&block->cache);
		if (!Cache_ReadLock (&block->cache))
			block->buffer = 0;
	}
}
示例#10
0
/*
 *  Look up file set the cache given a certain PlanState.
 *  Return NULL if not found.
 */
static workfile_set *
workfile_mgr_lookup_set(PlanState *ps)
{
	Assert(NULL != ps);
	Assert(NULL != workfile_mgr_cache);
	Assert(NULL != ps->plan);
	Assert(nodeTag(ps->plan) >= T_Plan && nodeTag(ps->plan) < T_PlanInvalItem);

	/* Create parameter info for the populate function */
	workset_info set_info;
	set_info.dir_path = NULL;
	set_info.operator_work_mem = get_operator_work_mem(ps);
	set_info.on_disk = false;

	CacheEntry *localEntry = acquire_entry_retry(workfile_mgr_cache, &set_info);
	Assert(localEntry != NULL);

	workfile_set *local_work_set = (workfile_set *) CACHE_ENTRY_PAYLOAD(localEntry);

	/* Populate the rest of the entries needed for look-up
	 * Allocate the serialized plan in the TopMemoryContext since this memory
	 * context is still available when calling the transaction callback at the
	 * time when the transaction aborts.
	 */
	MemoryContext oldcxt = MemoryContextSwitchTo(TopMemoryContext);
	workfile_set_plan *s_plan = workfile_mgr_serialize_plan(ps);
	MemoryContextSwitchTo(oldcxt);

	Assert(s_plan != NULL);
	local_work_set->set_plan = s_plan;
	local_work_set->key = workfile_mgr_hash_key(s_plan);

	CacheEntry *cachedEntry = Cache_Lookup(workfile_mgr_cache, localEntry);

	/* Release local entry and free up plan memory. We don't need it anymore */
	Cache_Release(workfile_mgr_cache, localEntry);

	workfile_set *work_set = NULL;
	if (NULL != cachedEntry)
	{
		work_set = (workfile_set *) CACHE_ENTRY_PAYLOAD(cachedEntry);
	}

	return work_set;
}
示例#11
0
/*
 * Close a spill file set. If we're planning to re-use it, insert it in the
 * cache. If not, let the cleanup routine delete the files and free up memory.
 */
void
workfile_mgr_close_set(workfile_set *work_set)
{
	Assert(work_set!=NULL);
	/* Although work_set is in shared memory only this process has access to it */
	if (work_set->prev)
		work_set->prev->next = work_set->next;
	else
		open_workfile_sets = work_set->next;
	if (work_set->next)
		work_set->next->prev = work_set->prev;

	elog(gp_workfile_caching_loglevel, "closing workfile set: location: %s, size=" INT64_FORMAT
			" in_progress_size=" INT64_FORMAT,
		 work_set->path,
		 work_set->size, work_set->in_progress_size);

	CacheEntry *cache_entry = CACHE_ENTRY_HEADER(work_set);
	Cache_Release(workfile_mgr_cache, cache_entry);
}
示例#12
0
qboolean
sw32_R_AliasCheckBBox (void)
{
	int         i, flags, frame, numv;
	aliashdr_t *pahdr;
	float       zi, basepts[8][3], v0, v1, frac;
	finalvert_t *pv0, *pv1, viewpts[16];
	auxvert_t  *pa0, *pa1, viewaux[16];
	maliasframedesc_t *pframedesc;
	qboolean    zclipped, zfullyclipped;
	unsigned int anyclip, allclip;
	int         minz;

	// expand, rotate, and translate points into worldspace
	currententity->trivial_accept = 0;
	pmodel = currententity->model;
	if (!(pahdr = pmodel->aliashdr))
		pahdr = Cache_Get (&pmodel->cache);
	pmdl = (mdl_t *) ((byte *) pahdr + pahdr->model);

	sw32_R_AliasSetUpTransform (0);

	// construct the base bounding box for this frame
	frame = currententity->frame;
// TODO: don't repeat this check when drawing?
	if ((frame >= pmdl->numframes) || (frame < 0)) {
		Sys_MaskPrintf (SYS_DEV, "No such frame %d %s\n", frame, pmodel->name);
		frame = 0;
	}

	pframedesc = &pahdr->frames[frame];

	// x worldspace coordinates
	basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] =
		(float) pframedesc->bboxmin.v[0];
	basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] =
		(float) pframedesc->bboxmax.v[0];

	// y worldspace coordinates
	basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] =
		(float) pframedesc->bboxmin.v[1];
	basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] =
		(float) pframedesc->bboxmax.v[1];

	// z worldspace coordinates
	basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] =
		(float) pframedesc->bboxmin.v[2];
	basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] =
		(float) pframedesc->bboxmax.v[2];

	zclipped = false;
	zfullyclipped = true;

	minz = 9999;
	for (i = 0; i < 8; i++) {
		sw32_R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]);

		if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) {
			// we must clip points that are closer than the near clip plane
			viewpts[i].flags = ALIAS_Z_CLIP;
			zclipped = true;
		} else {
			if (viewaux[i].fv[2] < minz)
				minz = viewaux[i].fv[2];
			viewpts[i].flags = 0;
			zfullyclipped = false;
		}
	}

	if (zfullyclipped) {
		if (!pmodel->aliashdr)
			Cache_Release (&pmodel->cache);
		return false;					// everything was near-z-clipped
	}

	numv = 8;

	if (zclipped) {
		// organize points by edges, use edges to get new points (possible
		// trivial reject)
		for (i = 0; i < 12; i++) {
			// edge endpoints
			pv0 = &viewpts[aedges[i].index0];
			pv1 = &viewpts[aedges[i].index1];
			pa0 = &viewaux[aedges[i].index0];
			pa1 = &viewaux[aedges[i].index1];

			// if one end is clipped and the other isn't, make a new point
			if (pv0->flags ^ pv1->flags) {
				frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) /
					(pa1->fv[2] - pa0->fv[2]);
				viewaux[numv].fv[0] = pa0->fv[0] +
					(pa1->fv[0] - pa0->fv[0]) * frac;
				viewaux[numv].fv[1] = pa0->fv[1] +
					(pa1->fv[1] - pa0->fv[1]) * frac;
				viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE;
				viewpts[numv].flags = 0;
				numv++;
			}
		}
	}
	// project the vertices that remain after clipping
	anyclip = 0;
	allclip = ALIAS_XY_CLIP_MASK;

// TODO: probably should do this loop in ASM, especially if we use floats
	for (i = 0; i < numv; i++) {
		// we don't need to bother with vertices that were z-clipped
		if (viewpts[i].flags & ALIAS_Z_CLIP)
			continue;

		zi = 1.0 / viewaux[i].fv[2];

		// FIXME: do with chop mode in ASM, or convert to float
		v0 = (viewaux[i].fv[0] * sw32_xscale * zi) + sw32_xcenter;
		v1 = (viewaux[i].fv[1] * sw32_yscale * zi) + sw32_ycenter;

		flags = 0;

		if (v0 < r_refdef.fvrectx)
			flags |= ALIAS_LEFT_CLIP;
		if (v1 < r_refdef.fvrecty)
			flags |= ALIAS_TOP_CLIP;
		if (v0 > r_refdef.fvrectright)
			flags |= ALIAS_RIGHT_CLIP;
		if (v1 > r_refdef.fvrectbottom)
			flags |= ALIAS_BOTTOM_CLIP;

		anyclip |= flags;
		allclip &= flags;
	}

	if (allclip) {
		if (!pmodel->aliashdr)
			Cache_Release (&pmodel->cache);
		return false;					// trivial reject off one side
	}

	currententity->trivial_accept = !anyclip & !zclipped;

	if (currententity->trivial_accept) {
		if (minz > (sw32_r_aliastransition + (pmdl->size * sw32_r_resfudge))) {
			currententity->trivial_accept |= 2;
		}
	}

	if (!pmodel->aliashdr)
		Cache_Release (&pmodel->cache);
	return true;
}
示例#13
0
/*
 * When a backend is requesting the more recent version of an object,
 * if the Local MDVSN cache doesn't have the version, and if a NUKE event
 * hasn't been encountered in the current transaction, it is looked up
 * in the Global MDVSN shared cache.
 *
 * If the object is found in Global MDVSN, return the global version.
 * If the object is not found, generate a new version, record it in Global MDVSN
 * and then return it.
 *
 *   key: The key of the looked-up object
 *   ddl_version: used to return the ddl version for the object
 *   dml_version: used to return the dml version for the object
 *
 */
static void
mdver_request_from_global(Oid key, uint64 *ddl_version, uint64 *dml_version)
{

	Assert(NULL != ddl_version);
	Assert(NULL != dml_version);

	Cache *mdver_glob_mdvsn = mdver_get_glob_mdvsn();
	Assert(NULL != mdver_glob_mdvsn);

	mdver_entry entry = {key, INVALID_MD_VERSION, INVALID_MD_VERSION};

	/* FIXME gcaragea 06/03/2014: Trigger evictions if cache is full (MPP-22923) */
	CacheEntry *localEntry = Cache_AcquireEntry(mdver_glob_mdvsn, &entry);

	Assert(NULL != localEntry);

	/*
	 * We're about to look-up and insert a shared cache entry.
	 * Grab writer lock in exclusive mode, so that no other backend
	 * can insert or update the same entry at the same time.
	 */
	LWLockAcquire(MDVerWriteLock, LW_EXCLUSIVE);

	CacheEntry *cachedEntry = Cache_Lookup(mdver_glob_mdvsn, localEntry);

	if (NULL != cachedEntry)
	{
		/* Not found in LVSN, not nuke happened, eventually found in GVSN */
		mdver_entry *crt_entry = CACHE_ENTRY_PAYLOAD(cachedEntry);

		*ddl_version = crt_entry->ddl_version;
		*dml_version = crt_entry->dml_version;

#ifdef MD_VERSIONING_INSTRUMENTATION
		elog(gp_mdversioning_loglevel, "Found version in Global MDVSN: (%d, " UINT64_FORMAT ", " UINT64_FORMAT "). Adding it to Local MDVSN",
				key, crt_entry->ddl_version, crt_entry->dml_version);
#endif

		/*
		 * We're also done with the entry, release our pincount on it
		 *
		 * TODO gcaragea 05/02/2014: Are there cases where we need to hold the
		 * entry past this point? (MPP-22923)
		 */

		Cache_Release(mdver_glob_mdvsn, cachedEntry);
	}
	else
	{
		/* Not found in LVSN, not nuke happened, not found in GVSN either */

		/* Generate new version */
		*ddl_version = mdver_next_global_version();
		*dml_version = mdver_next_global_version();

		/* Add to GVSN */
		mdver_entry *new_entry = CACHE_ENTRY_PAYLOAD(localEntry);
		new_entry->ddl_version = *ddl_version;
		new_entry->dml_version = *dml_version;

#ifdef MD_VERSIONING_INSTRUMENTATION
		elog(gp_mdversioning_loglevel, "Inserting new version in Global MDVSN: (%d, " UINT64_FORMAT ", " UINT64_FORMAT "). Adding it to Local MDVSN",
				key, new_entry->ddl_version, new_entry->dml_version);
#endif

		Cache_Insert(mdver_glob_mdvsn, localEntry);

	}

	LWLockRelease(MDVerWriteLock);

	/* Release local entry. We don't need it anymore */
	Cache_Release(mdver_glob_mdvsn, localEntry);
}
示例#14
0
//#define TETRAHEDRON
void
glsl_R_DrawAlias (void)
{
#ifdef TETRAHEDRON
	static aliasvrt_t debug_verts[] = {
		{{  0,  0}, {-18918,-18918,-18918}, {  0,  0,  0}},
		{{  0,300}, { 18918, 18918,-18918}, {255,255,  0}},
		{{300,300}, {-18918, 18918, 18918}, {  0,255,255}},
		{{300,  0}, { 18918,-18918, 18918}, {255,  0,255}},
	};
	static GLushort debug_indices[] = {
		0, 1, 2,
		0, 3, 1,
		1, 3, 2,
		0, 2, 3,
	};
#endif
	static quat_t color = { 1, 1, 1, 1};
	static vec3_t lightvec;
	float       ambient;
	float       shadelight;
	float       skin_size[2];
	float       blend;
	entity_t   *ent = currententity;
	model_t    *model = ent->model;
	aliashdr_t *hdr;
	vec_t       norm_mat[9];
	mat4_t      mvp_mat;
	int         skin_tex;
	int         colormap;
	aliasvrt_t *pose1 = 0;		// VBO's are null based
	aliasvrt_t *pose2 = 0;		// VBO's are null based

	if (!(hdr = model->aliashdr))
		hdr = Cache_Get (&model->cache);

	calc_lighting (ent, &ambient, &shadelight, lightvec);

	// we need only the rotation for normals.
	VectorCopy (ent->transform + 0, norm_mat + 0);
	VectorCopy (ent->transform + 4, norm_mat + 3);
	VectorCopy (ent->transform + 8, norm_mat + 6);

	// ent model scaling and offset
	Mat4Zero (mvp_mat);
	mvp_mat[0] = hdr->mdl.scale[0];
	mvp_mat[5] = hdr->mdl.scale[1];
	mvp_mat[10] = hdr->mdl.scale[2];
	mvp_mat[15] = 1;
	VectorCopy (hdr->mdl.scale_origin, mvp_mat + 12);
	Mat4Mult (ent->transform, mvp_mat, mvp_mat);
	Mat4Mult (alias_vp, mvp_mat, mvp_mat);

	colormap = glsl_colormap;
	if (ent->skin && ent->skin->auxtex)
		colormap = ent->skin->auxtex;
	if (ent->skin && ent->skin->texnum) {
		skin_t     *skin = ent->skin;
		skin_tex = skin->texnum;
	} else {
		maliasskindesc_t *skindesc;
		skindesc = R_AliasGetSkindesc (ent->skinnum, hdr);
		skin_tex = skindesc->texnum;
	}
	blend = R_AliasGetLerpedFrames (ent, hdr);

	pose1 += ent->pose1 * hdr->poseverts;
	pose2 += ent->pose2 * hdr->poseverts;

	skin_size[0] = hdr->mdl.skinwidth;
	skin_size[1] = hdr->mdl.skinheight;

	qfeglActiveTexture (GL_TEXTURE0 + 1);
	qfeglBindTexture (GL_TEXTURE_2D, colormap);
	qfeglActiveTexture (GL_TEXTURE0 + 0);
	qfeglBindTexture (GL_TEXTURE_2D, skin_tex);

#ifndef TETRAHEDRON
	qfeglBindBuffer (GL_ARRAY_BUFFER, hdr->posedata);
	qfeglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, hdr->commands);
#endif

	qfeglVertexAttrib4fv (quake_mdl.colora.location, color);
	qfeglVertexAttrib4fv (quake_mdl.colorb.location, color);
	qfeglUniform1f (quake_mdl.blend.location, blend);
	qfeglUniform1f (quake_mdl.ambient.location, ambient);
	qfeglUniform1f (quake_mdl.shadelight.location, shadelight);
	qfeglUniform3fv (quake_mdl.lightvec.location, 1, lightvec);
	qfeglUniform2fv (quake_mdl.skin_size.location, 1, skin_size);
	qfeglUniformMatrix4fv (quake_mdl.mvp_matrix.location, 1, false, mvp_mat);
	qfeglUniformMatrix3fv (quake_mdl.norm_matrix.location, 1, false, norm_mat);

#ifndef TETRAHEDRON
	set_arrays (&quake_mdl.vertexa, &quake_mdl.normala, &quake_mdl.sta, pose1);
	set_arrays (&quake_mdl.vertexb, &quake_mdl.normalb, &quake_mdl.stb, pose2);
	qfeglDrawElements (GL_TRIANGLES, 3 * hdr->mdl.numtris,
					  GL_UNSIGNED_SHORT, 0);
#else
	set_arrays (&quake_mdl.vertexa, &quake_mdl.normala, &quake_mdl.sta,
				debug_verts);
	set_arrays (&quake_mdl.vertexb, &quake_mdl.normalb, &quake_mdl.stb,
				debug_verts);
	qfeglDrawElements (GL_TRIANGLES,
					  sizeof (debug_indices) / sizeof (debug_indices[0]),
					  GL_UNSIGNED_SHORT, debug_indices);
#endif
	if (!model->aliashdr)
		Cache_Release (&model->cache);
}