gceSTATUS glfCompactNamedObjectList(
	IN glsCONTEXT_PTR Context,
	IN glsNAMEDOBJECTLIST_PTR List
	)
{
	gceSTATUS status = gcvSTATUS_OK;

    gcmHEADER_ARG("Context=0x%x List=0x%x", Context, List);

	do
	{
		gceSTATUS last;

		glsNAMEDOBJECT_PTR wrapper = List->freeList;
		while (wrapper)
		{
			glsNAMEDOBJECT_PTR temp = wrapper;
			wrapper = wrapper->next;

			gcmCHECK_STATUS(gcmOS_SAFE_FREE(gcvNULL, temp));
		}

		List->freeList = gcvNULL;
	}
	while (gcvFALSE);

    gcmFOOTER();

	return status;
}
gceSTATUS
gcoOS_DisplayBufferRegions(
    IN HALNativeDisplayType Display,
    IN HALNativeWindowType Window,
    IN gctINT NumRects,
    IN gctINT_PTR Rects
    )
{
    screen_buffer_t buf[gcdDISPLAY_BACK_BUFFERS];
    int rc;
    gceSTATUS status = gcvSTATUS_OK;

    gcmHEADER_ARG("Display=0x%x Window=0x%x NumRects=%d", Display, Window, NumRects);

    rc = screen_get_window_property_pv((screen_window_t)Window, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)buf);
    if (rc) {
        goto OnError;
    }

    rc = screen_post_window((screen_window_t)Window, buf[0], NumRects, Rects, 0);
    if (rc) {
        goto OnError;
    }

    gcmFOOTER_NO();
    return status;

OnError:
    status = gcvSTATUS_INVALID_ARGUMENT;
    gcmFOOTER();
    return status;
}
gceSTATUS
gcoQUEUE_Free(
    IN gcoQUEUE Queue
    )
{
    gcmHEADER_ARG("Queue=0x%x", Queue);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE);

    /* Free any records in the queue. */
#ifdef __QNXNTO__
    Queue->head = gcvNULL;
#else
    while (Queue->head != gcvNULL)
    {
        gcsQUEUE_PTR record;

        /* Unlink the first record from the queue. */
        record      = Queue->head;
        Queue->head = record->next;

        /* Put record on free list. */
        record->next    = Queue->freeList;
        Queue->freeList = record;
    }
#endif

    /* Update count */
    Queue->recordCount = 0;

    /* Success. */
    gcmFOOTER_NO();
    return gcvSTATUS_OK;
}
/*******************************************************************************
**
**  gcoBUFFER_Write
**
**  Copy a number of bytes into the buffer.
**
**  INPUT:
**
**      gcoBUFFER Buffer
**          Pointer to an gcoBUFFER object.
**
**      gctCONST_POINTER Data
**          Pointer to a buffer that contains the data to be copied.
**
**      IN gctSIZE_T Bytes
**          Number of bytes to copy.
**
**      IN gctBOOL Aligned
**          gcvTRUE if the data needs to be aligned to 64-bit.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoBUFFER_Write(
    IN gcoBUFFER Buffer,
    IN gctCONST_POINTER Data,
    IN gctSIZE_T Bytes,
    IN gctBOOL Aligned
    )
{
    gceSTATUS status;
    gcoCMDBUF reserve;

    gcmHEADER_ARG("Buffer=0x%x Data=0x%x Bytes=%lu Aligned=%d",
                  Buffer, Data, Bytes, Aligned);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER);
    gcmDEBUG_VERIFY_ARGUMENT(Data != gcvNULL);
    gcmDEBUG_VERIFY_ARGUMENT(Bytes > 0);

    /* Reserve data in the buffer. */
    gcmONERROR(gcoBUFFER_Reserve(Buffer, Bytes, Aligned, &reserve));

    /* Write data into the buffer. */
    gcmONERROR(gcoOS_MemCopy(reserve->lastReserve, Data, Bytes));

    /* Success. */
    gcmFOOTER_NO();
    return gcvSTATUS_OK;

OnError:
    /* Return status. */
    gcmFOOTER();
    return status;
}
/* Write data to profile. */
gceSTATUS
gcoPROFILER_Write(
    IN gcoHAL Hal,
    IN gctSIZE_T ByteCount,
    IN gctCONST_POINTER Data
    )
{
    gceSTATUS status = gcvSTATUS_OK;

    gcmHEADER_ARG("ByteCount=%lu Data=0x%x", ByteCount, Data);

    /* Check if already destroyed. */
   	if (gcPLS.hal->profiler.enable)
    {
        if (gcPLS.hal->profiler.useSocket)
        {
            status = gcoOS_Send(gcvNULL,
                                gcPLS.hal->profiler.sockFd,
                                ByteCount, Data, 0);
        }
        else
        {
            status = gcoOS_Write(gcvNULL,
                                 gcPLS.hal->profiler.file,
                                 ByteCount, Data);
        }
    }

    gcmFOOTER();
    return status;
}
void
vgshRemoveObject(
	_VGContext   *Context,
	_VGObject    *Object
	)
{
	VGuint index;

	gcmHEADER_ARG("Context=0x%x Object=0x%x", Context, Object);

	index = Object->name % NAMED_OBJECTS_HASH;

	if (Object->prev != gcvNULL)
	{
		Object->prev->next = Object->next;
	}
	else
	{
		Context->sharedData->namedObjects[index] = Object->next;
	}

	if (Object->next != gcvNULL)
	{
		Object->next->prev = Object->prev;
	}

	gcmFOOTER_NO();
}
static void _ClearBindings(
    IN gctPOINTER Object
    )
{
    gctUINT32 i;

    /* Cast the object. */
    glsBUFFER_PTR object = (glsBUFFER_PTR) Object;

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

    /* Reset the bound target. */
    object->bound            = gcvFALSE;
    object->boundAtLeastOnce = gcvFALSE;

    /* Reset bound streams. */
    for (i = 0; i < glvTOTALBINDINGS; i++)
    {
        if (object->binding[i])
        {
            *object->binding[i] = gcvNULL;
            object->binding[i]  = gcvNULL;
        }
    }
    gcmFOOTER_NO();
}
/*******************************************************************************
**
**  gcoBUFFER_Destroy
**
**  Destroy an gcoBUFFER object.
**
**  INPUT:
**
**      gcoBUFFER Buffer
**          Pointer to an gcoBUFFER object to delete.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoBUFFER_Destroy(
    IN gcoBUFFER Buffer
    )
{
    gceSTATUS status;

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

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER);

    /* Commit buffer before destroying it. */
    if (Buffer->size != 0)
    {
        /* Commit the command buffers. */
        gcmONERROR(gcoHARDWARE_Commit());

        /* Stall the hardware. */
        gcmONERROR(gcoHARDWARE_Stall());
    }

    /* Free all associated objects. */
    gcmONERROR(gcoBUFFER_FreeObjects(Buffer));

OnError:
    /* Return the status. */
    gcmFOOTER();
    return status;
}
/*******************************************************************************
**
**  gcoDUMP_Destroy
**
**  Destroy a gcoDUMP object created by gcDUMP_COnstruct.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_Destroy(
    IN gcoDUMP Dump
    )
{
    gcmHEADER_ARG("Dump=0x%x", Dump);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);

    if (Dump->file != gcvNULL)
    {
        if (Dump->frameStart != 0)
        {
            gcoDUMP_FrameEnd(Dump);
        }

        /* Close any open file. */
        gcmVERIFY_OK(gcoDUMP_Control(Dump, gcvNULL));
    }

    if (gcPLS.hal->dump == Dump)
    {
        /* Remove current gcoDUMP object. */
        gcPLS.hal->dump = gcvNULL;
    }

    /* Free the gcoDUMP structure. */
    gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, Dump));

    /* Success. */
    gcmFOOTER_NO();
    return gcvSTATUS_OK;
}
gceSTATUS
gcoQUEUE_Destroy(
    IN gcoQUEUE Queue
    )
{
    gceSTATUS status;

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

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE);

#ifndef __QNXNTO__
    /* Free any records in the queue. */
    while (Queue->head != gcvNULL)
    {
        gcsQUEUE_PTR record;

        /* Unlink the first record from the queue. */
        record      = Queue->head;
        Queue->head = record->next;

        gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, record));
    }

    /* Free any records in the free list. */
    while (Queue->freeList != gcvNULL)
    {
        gcsQUEUE_PTR record;

        /* Unlink the first record from the queue. */
        record          = Queue->freeList;
        Queue->freeList = record->next;

        gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, record));
    }
#else
    /* Free any records in the queue. */
    if ( Queue->records )
    {
        gcmVERIFY_OK(gcoOS_FreeNonPagedMemory(gcvNULL,
                                              BUFFER_SIZE,
                                              gcvNULL,
                                              Queue->records));
    }
#endif

    /* Free the queue. */
    gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, Queue));

    /* Success. */
    gcmFOOTER_NO();
    return gcvSTATUS_OK;

OnError:
    /* Return the status. */
    gcmFOOTER();
    return status;
}
gceSTATUS
gcoPROFILER_ShaderVS(
    IN gcoHAL Hal,
    IN gctPOINTER Vs
    )
{
/*#if PROFILE_SHADER_COUNTERS*/
    gcmHEADER_ARG("Vs=0x%x", Vs);

	if (gcPLS.hal->profiler.enableSH)
	{
		if (gcPLS.hal->profiler.enable)
		{
#if gcdNEW_PROFILER_FILE
            gctUINT16 alu = 0, tex = 0, i;
            gcSHADER Shader = (gcSHADER)Vs;

            /* Profile shader */
            for (i = 0; i < Shader->codeCount; i++ )
            {
                switch (Shader->code[i].opcode)
                {
                case gcSL_NOP:
                    break;

                case gcSL_TEXLD:
                    tex++;
                    break;

                default:
                    alu++;
                    break;
                }
            }

            gcmWRITE_CONST(VPG_PVS);

            gcmWRITE_COUNTER(VPC_PVSINSTRCOUNT, (tex + alu));
            gcmWRITE_COUNTER(VPC_PVSALUINSTRCOUNT, alu);
            gcmWRITE_COUNTER(VPC_PVSTEXINSTRCOUNT, tex);
            gcmWRITE_COUNTER(VPC_PVSATTRIBCOUNT, (Shader->attributeCount));
            gcmWRITE_COUNTER(VPC_PVSUNIFORMCOUNT, (Shader->uniformCount));
            gcmWRITE_COUNTER(VPC_PVSFUNCTIONCOUNT, (Shader->functionCount));
#else
			gcmWRITE_STRING("<VS>\n");
			gcoPROFILER_Shader(gcvNULL, (gcSHADER) Vs);
#endif
#if gcdNEW_PROFILER_FILE
            gcmWRITE_CONST(VPG_END);
#else
			gcmWRITE_STRING("</VS>\n");
#endif
		}
	}
/*#endif*/

    gcmFOOTER_NO();
    return gcvSTATUS_OK;
}
gceSTATUS vgsMEMORYMANAGER_Construct(
    IN gcoOS Os,
	IN gctUINT ItemSize,
	IN gctUINT Granularity,
	OUT vgsMEMORYMANAGER_PTR * Manager
	)
{
	gceSTATUS status;
	vgsMEMORYMANAGER_PTR manager = gcvNULL;

    gcmHEADER_ARG("Os=0x%x ItemSize=0x%x Granularity=0x%x Manager=0x%x",
        Os, ItemSize, Granularity, Manager);

	gcmVERIFY_ARGUMENT(ItemSize > 0);
	gcmVERIFY_ARGUMENT(Granularity > 0);
	gcmVERIFY_ARGUMENT(Manager != gcvNULL);

	do
	{
		gctUINT itemSize;
		gctUINT allocationSize;

		/* Allocate the memory manager structure. */
		gcmERR_BREAK(gcoOS_Allocate(
			Os,
			gcmSIZEOF(vgsMEMORYMANAGER),
			(gctPOINTER *) &manager
			));

		/* Determine the size of the item. */
		itemSize = gcmSIZEOF(vgsMEMORYITEM) + ItemSize;

		/* Determine the allocation size. */
		allocationSize = gcmSIZEOF(vgsMEMORYITEM) + Granularity * itemSize;

		/* Initialize the structure. */
		manager->os             = Os;
		manager->allocationSize = allocationSize;
		manager->itemCount      = Granularity;
		manager->itemSize       = itemSize;
		manager->firstAllocated = gcvNULL;
		manager->firstFree      = gcvNULL;

#if vgvVALIDATE_MEMORY_MANAGER
		manager->allocatedCount       = 0;
		manager->maximumAllocated     = 0;
		manager->allocatedBufferCount = 0;
#endif

		/* Set the result pointer. */
		* Manager = manager;
	}
	while (gcvNULL);

    gcmFOOTER();

	/* Return status. */
	return status;
}
static gceSTATUS _DeleteBuffer(
    IN glsCONTEXT_PTR Context,
    IN gctPOINTER Object
    )
{
    gceSTATUS status = gcvSTATUS_OK;

    gcmHEADER_ARG("Context=0x%x Object=0x%x", Context, Object);

    do
    {
        /* Cast the object. */
        glsBUFFER_PTR object = (glsBUFFER_PTR) Object;

        /* Clear bindings. */
        _ClearBindings(Object);

        /* Clear mapping */
        _ClearMapping(Object);

        /* Destroy index object. */
        if (object->index)
        {
            gcoINDEX_Destroy(object->index);
            object->index = gcvNULL;
        }

        /* Destroy stream object. */
        if (object->stream)
        {
            gcoSTREAM_Destroy(object->stream);
            object->stream = gcvNULL;
        }

#if gcdUSE_TRIANGLE_STRIP_PATCH
        if (object->subCount > 0)
        {
            GLint i;

            for (i = 0; i < object->subCount; i++)
            {
                gcoINDEX_Destroy(object->subs[i].patchIndex);
                object->subs[i].patchIndex  = gcvNULL;
            }

            object->subCount = 0;
        }
#endif
        /* Reset the fields. */
        object->size = 0;
        object->usage = GL_STATIC_DRAW;
    }
    while (gcvFALSE);

    gcmFOOTER();

    return status;
}
gceSTATUS glfDeleteNamedObject(
	IN glsCONTEXT_PTR Context,
	IN glsNAMEDOBJECTLIST_PTR List,
	gctUINT32 Name
	)
{
	gceSTATUS status = gcvSTATUS_OK;
    gcmHEADER_ARG("Context=0x%x List=0x%x Name=%u",
                    Context, List, Name);

	do
	{
		/* Determine the hash table index. */
		gctUINT32 index = Name % glvNAMEDOBJECT_HASHTABLE_SIZE;

		/* Shortcut to the table entry. */
		glsNAMEDOBJECT_PTR* entry = &List->hashTable[index];

		/* Keep history. */
		glsNAMEDOBJECT_PTR prev = gcvNULL;

		/* Search from the beginning. */
		glsNAMEDOBJECT_PTR curr = *entry;

		/* Search collided object list. */
		while (curr)
        {
            if (curr->name == Name)
            {
                /* Remove the wrapper from the list of allocated objects. */
                if (prev)
                {
                    prev->next = curr->next;
                }
                else
                {
                    *entry = curr->next;
                }

                glfDereferenceNamedObject(Context, curr);

                break;
            }

            /* The current becomes history. */
            prev = curr;

            /* Move to the next one. */
            curr = curr->next;
        }
	}
	while (gcvFALSE);

    gcmFOOTER();

	return status;
}
GL_APICALL void GL_APIENTRY
glGenRenderbuffers(
    GLsizei n,
    GLuint *renderbuffers
    )
{
#if gcdNULL_DRIVER < 3
    GLContext context;
    GLRenderbuffer renderbuffer;
    GLsizei i;

    gcmHEADER_ARG("n=%d", n);

    context = _glshGetCurrentContext();
    if (context == gcvNULL)
    {
        gcmFOOTER_NO();
        return;
    }

    if (n < 0)
    {
        gl2mERROR(GL_INVALID_VALUE);
        gcmFOOTER_NO();
        return;
    }

    /* Loop while there are renderbuffers to generate. */
    for (i = 0; i < n; ++i)
    {
        /* Create a new renderbuffer. */
        renderbuffer = _NewRenderbuffer(context, 0);
        if (renderbuffer == gcvNULL)
        {
            gcmFOOTER_NO();
            return;
        }

        /* Return Renderbuffer name. */
        gcmTRACE(gcvLEVEL_VERBOSE,
                 "glGenRenderbuffers: ==> %u",
                 renderbuffer->object.name);
        renderbuffers[i] = renderbuffer->object.name;
    }

    gcmDUMP_API("${ES20 glGenRenderbuffers 0x%08X (0x%08X)", n, renderbuffers);
    gcmDUMP_API_ARRAY(renderbuffers, n);
    gcmDUMP_API("$}");
    gcmFOOTER_NO();
#else
    while (n-- > 0)
    {
        *renderbuffers++ = 1;
    }
#endif
}
/* Profile input fragment shader. */
gceSTATUS
gcoPROFILER_ShaderFS(
    IN gcoHAL Hal,
    IN gctPOINTER Fs
    )
{
    gcmHEADER_ARG("Fs=0x%x", Fs);
    gcmFOOTER_NO();
    return gcvSTATUS_INVALID_REQUEST;
}
static gceSTATUS _CreateBuffer(
    IN glsCONTEXT_PTR Context,
    IN gctUINT32 Buffer,
    OUT glsNAMEDOBJECT_PTR * Wrapper
    )
{
    gceSTATUS status;

    gcmHEADER_ARG("Context=0x%x Buffer=%u Wrapper=0x%x",
                  Context, Buffer, Wrapper);

    do
    {
        glsBUFFER_PTR object;
        glsCONTEXT_PTR shared;

        /* Map shared context. */
#if gcdRENDER_THREADS
        shared = (Context->shared != gcvNULL) ? Context->shared : Context;
#else
        shared = Context;
#endif

        /* Attempt to allocate a new buffer. */
        gcmERR_BREAK(glfCreateNamedObject(
            Context,
            &shared->bufferList,
            Buffer,
            _DeleteBuffer,
            Wrapper
            ));

        /* Get a pointer to the new buffer. */
        object = (glsBUFFER_PTR) (*Wrapper)->object;

        /* Init the buffer to the defaults. */
        gcoOS_ZeroMemory(object, sizeof(glsBUFFER));
        object->usage = GL_STATIC_DRAW;
        object->mapped = gcvFALSE;
        object->bufferMapPointer = gcvNULL;

#if gcdUSE_TRIANGLE_STRIP_PATCH
        object->stripPatchDirty = gcvTRUE;
        object->subCount        = 0;

        gcoOS_ZeroMemory(object->subs, sizeof(object->subs));
#endif
    }
    while (gcvFALSE);

    gcmFOOTER();

    /* Return result. */
    return status;
}
gceSTATUS
gcoPROFILER_Count(
	IN gcoHAL Hal,
	IN gctUINT32 Enum,
	IN gctINT Value
	)
{
    gcmHEADER_ARG("Enum=%lu Value=%d", Enum, Value);

    gcmFOOTER_NO();
    return gcvSTATUS_INVALID_REQUEST;
}
/* Write data to profile. */
gceSTATUS
gcoPROFILER_Write(
    IN gcoHAL Hal,
    IN gctSIZE_T ByteCount,
    IN gctCONST_POINTER Data
    )
{
    gcmHEADER_ARG("ByteCount=%lu Data=0x%x", ByteCount, Data);

    gcmFOOTER_NO();
    return gcvSTATUS_INVALID_REQUEST;
}
gceSTATUS
gcoPROFILER_Count(
	IN gcoHAL Hal,
	IN gctUINT32 Enum,
	IN gctINT Value
	)
{
#if PROFILE_HAL_COUNTERS
    gcmHEADER_ARG("Enum=%lu Value=%d", Enum, Value);

	if (gcPLS.hal->profiler.enable)
	{
		switch (Enum)
		{
		case GLINDEX_OBJECT:
			gcPLS.hal->profiler.indexBufferNewObjectsAlloc   += Value;
			gcPLS.hal->profiler.indexBufferTotalObjectsAlloc += Value;
			break;

		case GLINDEX_OBJECT_BYTES:
			gcPLS.hal->profiler.indexBufferNewBytesAlloc   += Value;
			gcPLS.hal->profiler.indexBufferTotalBytesAlloc += Value;
			break;

		case GLVERTEX_OBJECT:
			gcPLS.hal->profiler.vertexBufferNewObjectsAlloc   += Value;
			gcPLS.hal->profiler.vertexBufferTotalObjectsAlloc += Value;
			break;

		case GLVERTEX_OBJECT_BYTES:
			gcPLS.hal->profiler.vertexBufferNewBytesAlloc   += Value;
			gcPLS.hal->profiler.vertexBufferTotalBytesAlloc += Value;
			break;

		case GLTEXTURE_OBJECT:
			gcPLS.hal->profiler.textureBufferNewObjectsAlloc   += Value;
			gcPLS.hal->profiler.textureBufferTotalObjectsAlloc += Value;
			break;

		case GLTEXTURE_OBJECT_BYTES:
			gcPLS.hal->profiler.textureBufferNewBytesAlloc   += Value;
			gcPLS.hal->profiler.textureBufferTotalBytesAlloc += Value;
			break;

		default:
			break;
		}
	}
#endif

    gcmFOOTER_NO();
    return gcvSTATUS_OK;
}
/*******************************************************************************
**
**  gcoDUMP_AddSurface
**
**  Allocate a surface.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**      gctINT32 Width, Height
**          Width and height of the surface.
**
**      gceSURF_FORMAT PixelFormat
**          Pixel format for the surface.
**
**      gctUINT32 Address
**          Physical address to be used as a handle for the surface.
**
**      gctSIZE_T ByteCount
**          Number of bytes inside the surface.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_AddSurface(
    IN gcoDUMP Dump,
    IN gctINT32 Width,
    IN gctINT32 Height,
    IN gceSURF_FORMAT PixelFormat,
    IN gctUINT32 Address,
    IN gctSIZE_T ByteCount
    )
{
    gceSTATUS status;
    gcsDUMP_SURFACE surface;

    gcmHEADER_ARG("Dump=0x%x Width=%d Height=%d PixelFormat=%d Address=%x "
                  "ByteCount=%d",
                  Dump, Width, Height, PixelFormat, Address, ByteCount);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);
    gcmVERIFY_ARGUMENT(ByteCount > 0);

    if (Dump->file == gcvNULL)
    {
        /* There is no open dump file. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    do
    {
        /* Write the data record. */
        surface.type    = gcvTAG_SURFACE;
        surface.address = Address;
        surface.width   = (gctINT16) Width;
        surface.height  = (gctINT16) Height;
        surface.format  = PixelFormat;
        surface.length  = ByteCount;

        gcmERR_BREAK(
            gcoOS_Write(gcvNULL, Dump->file, sizeof(surface), &surface));

        /* Update the frame length. */
        Dump->frameLength += sizeof(surface);

        /* Update the file length. */
        Dump->length += sizeof(surface);
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
/*******************************************************************************
**
**  gcoDUMP_DumpData
**
**  Dump data the file.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**      gceDUMP_TAG Type
**          Type of data.
**
**      gctUINT32 Address
**          Physical address to be used as a handle for the data.
**
**      gctSIZE_T ByteCount
**          Number of bytes to write.
**
**      gctCONST_POINTER Data
**          Pointer to the data to write.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_DumpData(
    IN gcoDUMP Dump,
    IN gceDUMP_TAG Type,
    IN gctUINT32 Address,
    IN gctSIZE_T ByteCount,
    IN gctCONST_POINTER Data
    )
{
    gceSTATUS status;
    gcsDUMP_DATA header;

    gcmHEADER_ARG("Dump=0x%x Type=%d Address=%x ByteCount=%d Data=0x%x",
                    Dump, Type, Address, ByteCount, Data);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);
    gcmVERIFY_ARGUMENT(ByteCount > 0);
    gcmVERIFY_ARGUMENT(Data != gcvNULL);

    if (Dump->file == gcvNULL)
    {
        /* There is no open dump file. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    do
    {
        /* Write the data record. */
        header.type    = Type;
        header.length  = ByteCount;
        header.address = Address;

        gcmERR_BREAK(
            gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header));

        /* Write the data. */
        gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, ByteCount, Data));

        /* Update the frame length. */
        Dump->frameLength += sizeof(header) + ByteCount;

        /* Update the file length. */
        Dump->length += sizeof(header) + ByteCount;
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
gceSTATUS glfConstructNamedObjectList(
	IN glsCONTEXT_PTR Context,
	IN glsNAMEDOBJECTLIST_PTR List,
	IN gctUINT32 ObjectSize
	)
{
    gcmHEADER_ARG("Context=0x%x List=0x%x ObjectSize=%u",
                    Context, List, ObjectSize);
	List->objectSize = ObjectSize;
	List->nextName = 1;
    gcmFOOTER_ARG("return=%s", "gcvSTATUS_OK");
    return gcvSTATUS_OK;
}
/*******************************************************************************
**
**  gcoDUMP_FrameEnd
**
**  Mark the end of a frame.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_FrameEnd(
    IN gcoDUMP Dump
    )
{
    gceSTATUS status;
    gcsDUMP_DATA header;
    gctUINT32 pos;

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

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);

    if (Dump->file == gcvNULL)
    {
        /* There is no open dump file. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    do
    {
        /* Get the current position. */
        gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &pos));

        /* Seek to the beginning of the frame. */
        gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, Dump->frameStart));

        /* Make sure we got the right byte count. */
        gcmASSERT(pos - Dump->frameStart == Dump->frameLength + sizeof(header));

        /* Update the frame header. */
        header.type    = gcvTAG_FRAME;
        header.length  = Dump->frameLength;
        header.address = ++ Dump->frameCount;

        gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header));

        /* Seek to the end of the file. */
        gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, pos));

        /* Mark the frame as ended. */
        Dump->frameStart = 0;
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
glsNAMEDOBJECT_PTR glfFindNamedObject(
	IN glsNAMEDOBJECTLIST_PTR List,
	IN gctUINT32 Name
	)
{
    gcmHEADER_ARG("List=0x%x Name=%u", List, Name);

	/* Allocated objects can never have zero-valued names. */
	if (Name)
	{
		/* Determine the index into the hash table. */
		gctUINT32 index = Name % glvNAMEDOBJECT_HASHTABLE_SIZE;

		/* Get a shortcut to the table entry. */
		glsNAMEDOBJECT_PTR* entry = &List->hashTable[index];

		/* Keep history. */
		glsNAMEDOBJECT_PTR prev = gcvNULL;

		/* Start from the beginning. */
		glsNAMEDOBJECT_PTR curr = *entry;

		while (curr)
		{
			if (curr->name == Name)
			{
				/* Move to the front of the list. */
				if (prev != gcvNULL)
				{
					prev->next = curr->next;

					curr->next = *entry;
					*entry = curr;
				}

                gcmFOOTER_ARG("curr=0x%x", curr);
                return curr;
            }

			/* The current becomes history. */
			prev = curr;

			/* Move to the next one. */
			curr = curr->next;
		}
	}

    gcmFOOTER_ARG("curr=0x%x", gcvNULL);
    return gcvNULL;
}
/*******************************************************************************
**
**  gcoDUMP_SetDumpFlag
**
**  Enabel dump or not
**
**  INPUT:
**
**      gctBOOL DumpState
**          Dump state to set.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_SetDumpFlag(
    IN gctBOOL DumpState
    )
{
    gcmHEADER_ARG("DumpState=%d", DumpState);

    setDumpFlag = DumpState;

    /* Success. */
    gcmFOOTER_NO();

    return gcvSTATUS_OK;
}
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;
}
gceSTATUS
gcoPROFILER_Shader(
    IN gcoHAL Hal,
    IN gcSHADER Shader
    )
{
/*#if PROFILE_SHADER_COUNTERS*/

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

	if (gcPLS.hal->profiler.enableSH)
	{
	    gctUINT16 alu = 0, tex = 0, i;

		if (gcPLS.hal->profiler.enable)
		{
		    /* Profile shader */
    		for (i = 0; i < Shader->codeCount; i++ )
    		{
	        	switch (Shader->code[i].opcode)
    	    	{
				case gcSL_NOP:
					break;

				case gcSL_TEXLD:
					tex++;
					break;

				default:
					alu++;
					break;
				}
			}

    		gcmPRINT_XML("<InstructionCount value=\"%d\"/>\n", tex + alu);
			gcmPRINT_XML("<ALUInstructionCount value=\"%d\"/>\n", alu);
			gcmPRINT_XML("<TextureInstructionCount value=\"%d\"/>\n", tex);
			gcmPRINT_XML("<Attributes value=\"%lu\"/>\n", Shader->attributeCount);
			gcmPRINT_XML("<Uniforms value=\"%lu\"/>\n", Shader->uniformCount);
			gcmPRINT_XML("<Functions value=\"%lu\"/>\n", Shader->functionCount);
		}
/*#endif*/
	}

    gcmFOOTER_NO();
    return gcvSTATUS_OK;
}
gceSTATUS
gcoOS_SetDisplayVirtual(
    IN HALNativeDisplayType Display,
    IN HALNativeWindowType Window,
    IN gctUINT Offset,
    IN gctINT X,
    IN gctINT Y
    )
{
    screen_buffer_t buf[gcdDISPLAY_BACK_BUFFERS];
    int rc;
    int rects[4];
    gceSTATUS status = gcvSTATUS_OK;

    gcmHEADER_ARG("Display=0x%x Window=0x%x Offset=%u X=%d Y=%d", Display, Window, Offset, X, Y);

    rects[0] = 0;
    rects[1] = 0;

    rc = screen_get_window_property_pv((screen_window_t)Window, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)buf);
    if (rc)
    {
        goto OnError;
    }

    rc = screen_get_window_property_iv((screen_window_t)Window, SCREEN_PROPERTY_BUFFER_SIZE, &rects[2]);
    if (rc)
    {
        goto OnError;
    }

    rc = screen_post_window((screen_window_t)Window, buf[0], 1, rects, 0);
    if (rc)
    {
        goto OnError;
    }

    _ReleaseWindowInfoNode(Window);

    gcmFOOTER_NO();
    return status;

OnError:
    status = gcvSTATUS_INVALID_ARGUMENT;
    gcmFOOTER();
    return status;
}
/*******************************************************************************
**
**  gcoDUMP_Delete
**
**  Mark an address as deleted.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**      gctUINT32 Address
**          Physical address to delete.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_Delete(
    IN gcoDUMP Dump,
    IN gctUINT32 Address
    )
{
    gceSTATUS status;
    gcsDUMP_DATA header;

    gcmHEADER_ARG("Dump=0x%x Address=%x", Dump, Address);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);

    if (Dump->file == gcvNULL)
    {
        /* There is no open dump file. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    do
    {
        /* Write the delete record. */
        header.type    = gcvTAG_DELETE;
        header.length  = 0;
        header.address = Address;

        gcmERR_BREAK(
            gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header));

        /* Update the frame length. */
        Dump->frameLength += sizeof(header);

        /* Update the file length. */
        Dump->length += sizeof(header);
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}