Example #1
0
__fini(
	void
    )
{
	VEGLThreadData thread;

	gcmHEADER();

	if (initialized)
	{
		/* Get a pointer to the associated object. */
		thread = (VEGLThreadData) pthread_getspecific(key);

		if (0 == access(GAL_DEV, F_OK)) {
		    veglDestroyThreadData(thread);
		}

		gcmVERIFY_OK(gcoOS_Free(gcvNULL, thread));

		pthread_setspecific(key, NULL);

		pthread_key_delete(key);

		_thread = NULL;

		veglDeinitializeGlobalData();

		initialized = gcvFALSE;
	}

	gcmFOOTER_NO();
}
static gctBOOL
OutputShaderData(
    IN gcoOS Os,
    IN gctCONST_STRING FileName,
    IN gctSIZE_T Size,
    IN gctCONST_STRING Data
    )
{
    gceSTATUS   status;
    gctSTRING   dataFileName;
    gctSIZE_T   length;
    gctFILE     file;

    gcmASSERT(FileName);

    gcmVERIFY_OK(gcoOS_StrLen(FileName, &length));
    length += 6;
    gcmVERIFY_OK(gcoOS_Allocate(Os, length, (gctPOINTER *) &dataFileName));
    gcmVERIFY_OK(gcoOS_StrCopySafe(dataFileName, length, FileName));
    gcmVERIFY_OK(gcoOS_StrCatSafe(dataFileName, length, ".gcSL"));

    status = gcoOS_Open(Os, dataFileName, gcvFILE_CREATE, &file);

    if (gcmIS_ERROR(status))
    {
        gcoOS_Free(Os, dataFileName);
        printf("*ERROR* Failed to open the data file: %s\n", dataFileName);
        return gcvFALSE;
    }
    gcoOS_Free(Os, dataFileName);

    gcmASSERT(file);
    status = gcoOS_Write(Os, file, Size, Data);

    if (!gcmIS_SUCCESS(status))
    {
        printf("*ERROR* Failed to write the data file: %s\n", dataFileName);
        goto ErrorExit;
    }

    gcmVERIFY_OK(gcoOS_Close(Os, file));
    return gcvTRUE;

ErrorExit:
    gcmVERIFY_OK(gcoOS_Close(Os, file));
    return gcvFALSE;
}
gceSTATUS vgsMEMORYMANAGER_Destroy(
	IN vgsMEMORYMANAGER_PTR Manager
	)
{
	gceSTATUS status;
	vgsMEMORYITEM_PTR current;
	vgsMEMORYITEM_PTR next;

    gcmHEADER_ARG("Manager=0x%x", Manager);

	/* Verify arguments. */
	gcmVERIFY_ARGUMENT(Manager != gcvNULL);

	/* Assume success. */
	status = gcvSTATUS_OK;

	/* Everything has to be freed. */
#if vgvVALIDATE_MEMORY_MANAGER
	gcmASSERT(Manager->allocatedCount == 0);
#endif

	/* Destroy all allocated buffers. */
	while (Manager->firstAllocated)
	{
		/* Get the current buffer. */
		current = Manager->firstAllocated;

		/* Get the next buffer. */
		next = current->next;

		/* Free the current. */
		gcmERR_BREAK(gcoOS_Free(Manager->os, current));

		/* Advance to the next one. */
		Manager->firstAllocated = next;
	}

	/* Success? */
	if (gcmIS_SUCCESS(status))
	{
		status = gcoOS_Free(Manager->os, Manager);
	}

    gcmFOOTER();
	/* Return status. */
	return status;
}
Example #4
0
gceSTATUS vgfDereferenceObject(
	vgsCONTEXT_PTR Context,
	vgsOBJECT_PTR * Object
	)
{
	gceSTATUS status = gcvSTATUS_OK;

	gcmASSERT(Context != gcvNULL);
	gcmASSERT(Object != gcvNULL);

	do
	{
		/* Get a shortcut to the object. */
		vgsOBJECT_PTR object = *Object;

		/* Already destroyed? */
		if (object == gcvNULL)
		{
			break;
		}

		/* Valid reference count? */
		if (object->referenceCount < 1)
		{
			gcmFATAL("Invalid reference count found.");
			status = gcvSTATUS_INVALID_OBJECT;
			break;
		}

		/* Decrement the reference count. */
		object->referenceCount--;

		/* Time to destroy? */
		if (object->referenceCount == 0)
		{
			vgsOBJECT_LIST_PTR objectList;

			/* Get a shortcut to the object list. */
			objectList = &Context->objectCache->cache[object->type];

			/* Call the destructor. */
			gcmASSERT(objectList->destructor != gcvNULL);
			gcmERR_BREAK(objectList->destructor(Context, object));

			/* Remove the object from the cache. */
			gcmERR_BREAK(vgfObjectCacheRemove(Context, object));

			/* Free the object. */
			gcmERR_BREAK(gcoOS_Free(Context->os, object));

			/* Reset the pointer. */
			*Object = gcvNULL;
		}
	}
	while (gcvFALSE);

	/* Return status. */
	return status;
}
/************************************************************************
 * PIXMAP RELATED (START)
 ************************************************************************/
static gctBOOL FreeGPUSurface(VIVGPUPtr gpuctx, Viv2DPixmapPtr ppriv) {
    TRACE_ENTER();
    gceSTATUS status = gcvSTATUS_OK;
    GenericSurfacePtr surf = gcvNULL;
    gceSURF_TYPE surftype;
    Bool cacheable;

    surf = (GenericSurfacePtr) (ppriv->mVidMemInfo);
    if (surf->mIsWrapped) {
        goto delete_wrapper;
    }
    TRACE_INFO("DESTROYED SURFACE ADDRESS = %x - %x\n", surf, ppriv->mVidMemInfo);

    surf = AddGSurfIntoPool(surf);

    if ( surf ==NULL )
    {
        ppriv->mVidMemInfo = NULL;
        TRACE_EXIT(gcvTRUE);
    }

    if ( surf->mData )
        pixman_image_unref( (pixman_image_t *)surf->mData );

    surf->mData = gcvNULL;

    if ( surf->mAlignedWidth >= IMX_EXA_NONCACHESURF_WIDTH && surf->mAlignedHeight >= IMX_EXA_NONCACHESURF_HEIGHT )
    {
        surftype = gcvSURF_BITMAP;
        cacheable = FALSE;
    } else {
        surftype = SURFACE_TYPE;
        cacheable = SURFACE_CACHEABLE;
    }

    if (surf->mVideoNode.mNode != gcvNULL) {
        if (surf->mVideoNode.mLogicalAddr != gcvNULL) {
            status = UnlockVideoNode(gpuctx->mDriver->mHal, surf->mVideoNode.mNode, surftype);
            if (status != gcvSTATUS_OK) {
                TRACE_ERROR("Unable to UnLock video node\n");
                TRACE_EXIT(gcvFALSE);
            }
        }
        status = FreeVideoNode(gpuctx->mDriver->mHal, surf->mVideoNode.mNode);
        if (status != gcvSTATUS_OK) {
            TRACE_ERROR("Unable to Free video node\n");
            TRACE_EXIT(gcvFALSE);
        }
delete_wrapper:
        status = gcoOS_Free(gcvNULL, surf);
        if (status != gcvSTATUS_OK) {
            TRACE_ERROR("Unable to Free surface\n");
            TRACE_EXIT(gcvFALSE);
        }
        ppriv->mVidMemInfo = NULL;
    }
    TRACE_EXIT(gcvTRUE);
}
/**
 *
 * @param device - to be destroyed
 * @return
 */
static gctBOOL DestroyDevice(Viv2DDevicePtr device) {
    TRACE_ENTER();
    gceSTATUS status = gcvSTATUS_OK;
    status = gcoOS_Free(gcvNULL, device);

    if (status != gcvSTATUS_OK) {
        TRACE_ERROR("Unable to free driver structure, status = %d\n", status);
        TRACE_EXIT(gcvFALSE);
    }
    device = gcvNULL;
    TRACE_EXIT(gcvTRUE);
}
Example #7
0
static void
veglThreadDestructor(
	void * Thread
	)
{
	gcmHEADER_ARG("Thread=0x%x", Thread);

	pthread_setspecific(key, Thread);

	if (Thread != NULL)
	{
		veglDestroyThreadData(Thread);

		gcmVERIFY_OK(gcoOS_Free(gcvNULL, Thread));

		if (_thread == Thread) _thread = NULL;
	}

	pthread_setspecific(key, NULL);

	gcmFOOTER_NO();
}
int
main(
    int argc,
    char * argv[]
    )
{
    gctBOOL         dumpLog      = gcvFALSE;
    gctSTRING       fileName[2]  = { gcvNULL, gcvNULL };
    gcSHADER        shaders[2]   = { gcvNULL, gcvNULL };
    gctINT          i;
    gcoOS           os           = gcvNULL;
    gcoHAL          hal          = gcvNULL;
    gceSTATUS       result;
    gctUINT         option       = 1;   /* no optimization */
    char            outFile[128] = { '\0' };
    char            logVSFile[128] = { '\0' };
    char            logFSFile[128] = { '\0' };

    printf("vCompile version 0.8, Copyright (c) 2005-2011, Vivante Corporation\n\n");

#ifdef _WIN32
    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) /*| _CRTDBG_CHECK_ALWAYS_DF*/ | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
    /* _CrtSetBreakAlloc(79); */
#endif

#if gcdDEBUG
    gcoOS_SetDebugLevel(gcvLEVEL_VERBOSE);
    gcoOS_SetDebugZone(gcvZONE_COMPILER);
#endif

    for (i = 1; i < argc; i++)
    {
        if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-l")))
        {
            dumpLog = gcvTRUE;
        }
        else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-O0")))
        {
            /* Currently, optimization level is either FULL or NONE */
            option = 0;     /* no optimization */
        }
        else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-O")))
        {
            option = 1;     /* full optimization */
        }
        else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-OT")))
        {
            /* For optimization unit test */
            if (i++ == argc)
            {
                printf("*ERROR* Optimization testing pattern not provided.\n");
                return 1;
            }
            else
            {
                gctINT testPattern;

                gcmVERIFY_OK(gcoOS_StrToInt(argv[i], (gctINT *)&testPattern));
                if (testPattern < 0)
                {
                    printf("*ERROR* Unknown optimization testing pattern.\n");
                    return 1;
                }
                option = testPattern;
            }
        }
        else
        {
            if (fileName[0] == gcvNULL) fileName[0] = argv[i];
            else if (fileName[1] == gcvNULL) fileName[1] = argv[i];
            else
            {
                printf("*ERROR* Too many shaders.\n");
                return 1;
            }
        }
    }

    if (fileName[0] == gcvNULL)
    {
        printf("Usage: %s [-l] [-O0] shaderFileName [shaderFileName]\n", argv[0]);
        printf("  -l   Generate log file.\n"
               "  -O0  Disable optimizations.\n"
               "\n"
               "If only one shader is specified, that shader will be compiled into a .gcSL\n"
               "file.  If two shaders are specified, those shaders will be compiled and\n"
               "linked into a .gcPGM file. With two shaders, the vertex shader file needs\n"
               "to be the first.\n");
        return 0;
    }

    result = gcoOS_Construct(gcvNULL, &os);
    if (result != gcvSTATUS_OK)
    {
        printf("*ERROR* Failed to construct a new gcoOS object\n");
        return 1;
    }

    result = gcoHAL_Construct(gcvNULL, os, &hal);
    if (result != gcvSTATUS_OK)
    {
        printf("*ERROR* Failed to construct a new gcoHAL object\n");
        goto ErrorExit;
    }

    /* Dump compile log only when one shader is present */
    shaders[0] = CompileFile(os, fileName[0], hal, option, dumpLog && (fileName[1] == gcvNULL), fileName[1] == gcvNULL );

    if (shaders[0] == gcvNULL)
    {
        goto ErrorExit;
    }

    if (fileName[1] != gcvNULL)
    {
        gctSIZE_T programBufferSize = 0;
        gctPOINTER programBuffer = gcvNULL;
        gcsHINT_PTR hints = gcvNULL;
        gceSTATUS status;
        gctPOINTER binary = gcvNULL;
        gctSIZE_T binarySize = 0;
        FILE * f;
        gctSTRING p;

        gcoOS_StrCopySafe(outFile, gcmSIZEOF(outFile), fileName[0]);
        p = strrchr(outFile, '.');
        gcoOS_StrCopySafe(p, gcmSIZEOF(outFile) - (p - outFile), ".gcPGM");

        gcoOS_StrCopySafe(logVSFile, gcmSIZEOF(logVSFile), fileName[0]);
        gcoOS_StrCatSafe(logVSFile, gcmSIZEOF(logVSFile), ".log");

        gcoOS_StrCopySafe(logFSFile, gcmSIZEOF(logFSFile), fileName[1]);
        gcoOS_StrCatSafe(logFSFile, gcmSIZEOF(logFSFile), ".log");

        shaders[1] = CompileFile(os, fileName[1], hal, option, gcvFALSE, gcvFALSE);
        if (shaders[1] == gcvNULL)
        {
            goto ErrorExit;
        }

        if ( dumpLog)
        {
            gcoOS_SetDebugShaderFiles(logVSFile, logFSFile);
        }
        status = gcLinkShaders(shaders[0],
                               shaders[1],
                               gcvSHADER_DEAD_CODE
                               | gcvSHADER_RESOURCE_USAGE
                               | gcvSHADER_OPTIMIZER
                               | gcvSHADER_USE_GL_Z
                               | gcvSHADER_USE_GL_POSITION
                               | gcvSHADER_USE_GL_FACE,
                               &programBufferSize,
                               &programBuffer,
                               &hints);
        if ( dumpLog)
        {
            gcoOS_SetDebugShaderFiles(gcvNULL, gcvNULL);
        }

        if (gcmIS_ERROR(status))
        {
            printf("*ERROR* gcLinkShaders returned errror %d\n", status);
        }
        else
        {
            int ret;
            status = gcSaveProgram(shaders[0],
                                   shaders[1],
                                   programBufferSize,
                                   programBuffer,
                                   hints,
                                   &binary,
                                   &binarySize);

            if (gcmIS_ERROR(status))
            {
                printf("*ERROR* gcSaveShaders returned errror %d\n", status);
            }

            f = fopen(outFile, "wb");
            ret = fwrite(binary, binarySize, 1, f);
            if (ret);
            fclose(f);
        }

        if (programBuffer != gcvNULL) gcoOS_Free(os, programBuffer);
        if (hints         != gcvNULL) gcoOS_Free(os, hints);
        if (binary        != gcvNULL) gcoOS_Free(os, binary);
    }

    gcSHADER_Destroy(shaders[0]);
    if (shaders[1] != gcvNULL) gcSHADER_Destroy(shaders[1]);
    gcoHAL_Destroy(hal);
    gcoOS_Destroy(os);
    return 0;

ErrorExit:
    if (shaders[0] != gcvNULL) gcSHADER_Destroy(shaders[0]);
    if (shaders[1] != gcvNULL) gcSHADER_Destroy(shaders[1]);
    if (gcvNULL != hal) gcoHAL_Destroy(hal);
    if (gcvNULL != os) gcoOS_Destroy(os);

    return 1;
}
static gcSHADER
CompileFile(
    IN gcoOS Os,
    IN gctCONST_STRING FileName,
    IN gcoHAL Hal,
    IN gctUINT Option,
    IN gctBOOL DumpLog,
    IN gctBOOL DumpCompiledShader
    )
{
    gceSTATUS   status;
    gctINT      shaderType;
    gctSIZE_T   sourceSize;
    gctSTRING   source          = gcvNULL;
    gcSHADER    binary;
    gctSTRING   log             = gcvNULL;
    gctSIZE_T   bufferSize;
    gctSTRING   buffer;
    gctSTRING   dataFileName    = gcvNULL;
    gctSIZE_T   length;
    gctFILE     logFile         = gcvNULL;

    gcmASSERT(FileName);

    shaderType = GetShaderType(FileName);

    if (!ReadSource(Os, FileName, &sourceSize, &source)) return gcvNULL;

    status = gcCompileShader(Hal,
                             shaderType,
                             sourceSize, source,
                             &binary,
                             &log);

    if (log != gcvNULL)
    {
        printf("<LOG>\n");
        printf("%s", log);
        printf("</LOG>\n");
    }

    if (gcmIS_ERROR(status))
    {
        gcmASSERT(binary == gcvNULL);
        binary = gcvNULL;

        printf("*ERROR* Failed to compile %s (error: %d)\n", FileName, status);
        goto Exit;
    }

    gcmASSERT(binary != gcvNULL);

    if (DumpLog)
    {
        gcmVERIFY_OK(gcoOS_StrLen(FileName, &length));
        length += 5;
        gcmVERIFY_OK(gcoOS_Allocate(Os, length, (gctPOINTER *) &dataFileName));
        gcmVERIFY_OK(gcoOS_StrCopySafe(dataFileName, length, FileName));
        gcmVERIFY_OK(gcoOS_StrCatSafe(dataFileName, length, ".log"));

        status = gcoOS_Open(Os, dataFileName, gcvFILE_CREATETEXT, &logFile);
        if (gcmIS_ERROR(status))
        {
            logFile = gcvNULL;

            printf("*ERROR* Failed to open the log file: %s\n", dataFileName);
        }
        gcoOS_Free(Os, dataFileName);
    }

    gcmVERIFY_OK(gcSHADER_SetOptimizationOption(binary, Option));

    status = gcOptimizeShader(binary, logFile);

    if (!gcmIS_SUCCESS(status))
    {
        printf("*ERROR* Failed to optimize %s (error: %d)\n", FileName, status);
    }

    if (logFile != gcvNULL)
    {
        gcmVERIFY_OK(gcoOS_Close(Os, logFile));
    }

    if (DumpCompiledShader)
    {
        status = gcSHADER_Save(binary, gcvNULL, &bufferSize);
        if (gcmIS_ERROR(status))
        {
            printf("*ERROR* Failed to get the buffer size of the shader\n");
            goto Exit;
        }

        status = gcoOS_Allocate(Os, bufferSize, (gctPOINTER *) &buffer);
        if (!gcmIS_SUCCESS(status))
        {
            printf("*ERROR* Not enough memory\n");
            goto Exit;
        }

        status = gcSHADER_Save(binary, buffer, &bufferSize);
        if (status != gcvSTATUS_OK)
        {
            printf("*ERROR* Failed to get the buffer size of the shader\n");
            gcoOS_Free(Os, buffer);
            goto Exit;
        }

        OutputShaderData(Os, FileName, bufferSize, buffer);

        gcoOS_Free(Os, buffer);
    }


Exit:
    if (DumpLog && log != gcvNULL)
    {
        printf("**************** Compile Log ****************");
        printf("%s", log);
        printf("*********************************************");
    }

    if (log != gcvNULL) gcoOS_Free(Os, log);

    if (source != gcvNULL) gcoOS_Free(Os, source);

    return binary;
}
/**
 *
 * @param driver - driver object to be destroyed
 * @return  - status of the destriuction
 */
static gctBOOL DestroyDriver
(
        IN Viv2DDriverPtr driver
        ) {
    gceSTATUS status = gcvSTATUS_OK;
    gcmASSERT(driver != gcvNULL);
    TRACE_ENTER();
    /*Committing what is left*/
    gcoHAL_Commit(driver->mHal, gcvTRUE);


    /*Unmapping the memory*/
    if (driver->g_Internal != gcvNULL) {
        /* Unmap the local internal memory. */
        status = gcoHAL_UnmapMemory(driver->mHal,
                driver->g_InternalPhysical,
                driver->g_InternalSize,
                driver->g_Internal
                );
        if (status < 0) {
            TRACE_ERROR("gcoHAL_UnMapMemory failed, status = %d\n", status);
            TRACE_EXIT(gcvFALSE);
        }
    }

    if (driver->g_External != gcvNULL) {
        /* Unmap the local external memory. */
        status = gcoHAL_UnmapMemory(driver->mHal,
                driver->g_ExternalPhysical,
                driver->g_ExternalSize,
                driver->g_External
                );
        if (status < 0) {
            TRACE_ERROR("gcoHAL_UnMapMemory failed, status = %d\n", status);
            TRACE_EXIT(gcvFALSE);
        }
    }
    if (driver->g_Contiguous != gcvNULL) {
        /* Unmap the contiguous memory. */
        status = gcoHAL_UnmapMemory(driver->mHal,
                driver->g_ContiguousPhysical,
                driver->g_ContiguousSize,
                driver->g_Contiguous
                );

        if (status < 0) {
            TRACE_ERROR("gcoHAL_UnMapMemory failed, status = %d\n", status);
            TRACE_EXIT(gcvFALSE);
        }
    }


    /* Shutdown */
    if (driver->mHal != gcvNULL) {
        status = gcoHAL_Destroy(driver->mHal);
        if (status != gcvSTATUS_OK) {
            TRACE_ERROR("Unable to destroy HAL object, status = %d\n", status);
            TRACE_EXIT(gcvFALSE);
        }
        driver->mHal = gcvNULL;
    }

    /*Os Destroy*/
    if (driver->mOs != gcvNULL) {
        status = gcoOS_Destroy(driver->mOs);
        if (status != gcvSTATUS_OK) {
            TRACE_ERROR("Unable to destroy Os object, status = %d\n", status);
            TRACE_EXIT(gcvFALSE);
        }
        driver->mOs = gcvNULL;
    }
    status = gcoOS_Free(gcvNULL, driver);
    if (status != gcvSTATUS_OK) {
        TRACE_ERROR("Unable to free driver structure, status = %d\n", status);
        TRACE_EXIT(gcvFALSE);
    }
    driver = gcvNULL;
    TRACE_EXIT(gcvTRUE);
}
Example #11
0
static gceSTATUS _ReferenceObjectCache(
	vgsCONTEXT_PTR Context,
	vgsOBJECT_CACHE_PTR * ObjectCache
	)
{
	gceSTATUS status, last;
	vgsOBJECT_CACHE_PTR objectCache = gcvNULL;

	do
	{
		/* Has the object cache been created? */
		if (*ObjectCache == gcvNULL)
		{
			static vgtSET_OBJECT_LIST initList[] =
			{
				vgfSetPathObjectList,
				vgfSetImageObjectList,
				vgfSetMaskObjectList,
				vgfSetFontObjectList,
				vgfSetPaintObjectList
			};

			gctUINT i;

			/* Allocate the context structure. */
			gcmERR_BREAK(gcoOS_Allocate(
				Context->os,
				gcmSIZEOF(vgsOBJECT_CACHE),
				(gctPOINTER *) &objectCache
				));

			gcmERR_BREAK(gcoOS_ZeroMemory(
				objectCache,
				gcmSIZEOF(vgsOBJECT_CACHE)));

			/* Initialize the object. */
			objectCache->loHandle       = ~0;
			objectCache->hiHandle       =  0;
			objectCache->referenceCount =  0;

			/* Initialize object arrays. */
			for (i = 0; i < gcmCOUNTOF(initList); i++)
			{
				initList[i] (&objectCache->cache[i]);
			}

			/* Set the result pointer. */
			*ObjectCache = objectCache;
		}

		/* Increment the counter. */
		(*ObjectCache)->referenceCount++;

		/* Success. */
		return gcvSTATUS_OK;
	}
	while (gcvFALSE);

	/* Roll back. */
	if (objectCache != gcvNULL)
	{
		gcmCHECK_STATUS(gcoOS_Free(Context->os, objectCache));
	}

	/* Return status. */
	return status;
}
Example #12
0
static gceSTATUS _DereferenceObjectCache(
	vgsCONTEXT_PTR Context,
	vgsOBJECT_CACHE_PTR * ObjectCache
	)
{
	/* Define the result and assume success. */
	gceSTATUS status = gcvSTATUS_OK;

	do
	{
		vgsOBJECT_PTR object;
		vgsOBJECT_LIST_PTR objectList;

		/* Get a shortcut to the object cache. */
		vgsOBJECT_CACHE_PTR objectCache = *ObjectCache;

		/* Existing object cache? */
		if (objectCache == gcvNULL)
		{
			break;
		}

		/* Valid reference count? */
		if (objectCache->referenceCount < 1)
		{
			gcmFATAL("Invalid reference count found.\n");
			status = gcvSTATUS_INVALID_OBJECT;
			break;
		}

		/* Decrement the counter. */
		objectCache->referenceCount--;

		/* Time to destroy? */
		if (objectCache->referenceCount == 0)
		{
			gctUINT i;

			/* Delete objects that are still in the cache. */
			for (i = 0; i < vgvOBJECTTYPE_COUNT; i++)
			{
				gctUINT32 index;

				/* Get the current object list. */
				objectList = &objectCache->cache[i];

				for (index = 0; index < vgvNAMED_OBJECTS_HASH; index++)
				{
					/* Are there objects in the list? */
					if (objectList->head[index] != gcvNULL)
					{
						gcmTRACE(
							gcvLEVEL_ERROR,
							"%s (%d): object cache %d still has objects in it.\n",
							__FUNCTION__, __LINE__, i
							);

						/* Delete the objects. */
						while (objectList->head[index])
                                        	{
							/* Copy the head object. */
							object = objectList->head[index];

							/* Dereference it. */
							gcmERR_BREAK(vgfDereferenceObject(
								Context,
								&object
								));
						}
					}
				 }

				/* Error? */
				if (gcmIS_ERROR(status))
				{
					break;
				}
			}

			/* Error? */
			if (gcmIS_ERROR(status))
			{
				break;
			}

			/* Allocate the context structure. */
			gcmERR_BREAK(gcoOS_Free(
				Context->os,
				(gctPOINTER *) objectCache
				));

			/* Reset the object. */
			*ObjectCache = gcvNULL;
		}
	}
	while (gcvFALSE);

	/* Return status. */
	return status;
}