gctINT
slScanFloatConstant(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING Text,
	OUT slsLexToken * Token
	)
{
	gcmASSERT(Token);

	Token->lineNo			= LineNo;
	Token->stringNo			= StringNo;
	Token->type			= T_FLOATCONSTANT;

	gcmVERIFY_OK(gcoOS_StrToFloat(Text, &Token->u.constant.floatValue));

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\" type=\"floatConstant\""
								" value=\"%f\" />",
								LineNo,
								StringNo,
								Token->u.constant.floatValue));

	return T_FLOATCONSTANT;
}
/*******************************************************************************
**
**  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;
}
void
_glshDereferenceRenderbuffer(
    GLContext Context,
    GLRenderbuffer Renderbuffer
    )
{
    gcmASSERT((Renderbuffer->object.reference - 1) >= 0);

    if (--Renderbuffer->object.reference == 0)
    {
        if (Renderbuffer->surface != gcvNULL)
        {
            if (Renderbuffer->combined == gcvNULL)
            {
                gcmVERIFY_OK(gcoSURF_Destroy(Renderbuffer->surface));
            }
            else
            {
                Renderbuffer->combined->combined = gcvNULL;
            }
        }

        gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, Renderbuffer));
    }
}
gceSTATUS
gcfDump(
    IN gcoOS Os,
    IN gctCONST_STRING Message,
    ...
    )
{

    gctUINT offset = 0;
    gctARGUMENTS args;
    char buffer[80];

    if (!setDumpFlag)
        return gcvSTATUS_OK;

#if gcdDUMP_IN_KERNEL
    gcsHAL_INTERFACE ioctl;

    gcmARGUMENTS_START(args, Message);
    gcmVERIFY_OK(gcoOS_PrintStrVSafe(ioctl.u.Debug.message,
                                     gcmSIZEOF(ioctl.u.Debug.message),
                                     &offset,
                                     Message, args));
    gcmARGUMENTS_END(args);

    ioctl.command     = gcvHAL_DEBUG;
    ioctl.u.Debug.set = gcvFALSE;
#if gcdDUMP
    ioctl.u.Debug.type = gcvMESSAGE_TEXT;
#else
    ioctl.u.Debug.type = gcvMESSAGE_DUMP;
#endif
    ioctl.u.Debug.messageSize = (gctUINT32)gcmSIZEOF(ioctl.u.Debug.message);

    gcmVERIFY_OK(gcoOS_DeviceControl(Os,
                                     IOCTL_GCHAL_INTERFACE,
                                     &ioctl, gcmSIZEOF(ioctl),
                                     &ioctl, gcmSIZEOF(ioctl)));
#else

    gcmARGUMENTS_START(args, Message);
    gcmVERIFY_OK(gcoOS_PrintStrVSafe(buffer, gcmSIZEOF(buffer),
                                     &offset,
                                     Message, args));
    gcmARGUMENTS_END(args);

    gcoOS_Print("%s", buffer);
#endif

    return gcvSTATUS_OK;
}
gctINT
slScanOperator(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING Text,
	IN gctINT tokenType,
	OUT slsLexToken * Token
	)
{
	gcmASSERT(Token);

	Token->lineNo			= LineNo;
	Token->stringNo			= StringNo;
	Token->type				= tokenType;
	Token->u.operator		= tokenType;

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\""
								" type=\"operator\" symbol=\"%s\" />",
								LineNo,
								StringNo,
								Text));

	return tokenType;
}
gctINT
slScanHexIntConstant(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING Text,
	OUT slsLexToken * Token
	)
{
    gctINT index = 2;

	gcmASSERT(Token);

	Token->lineNo			= LineNo;
	Token->stringNo			= StringNo;
	Token->type			= T_INTCONSTANT;
	Token->u.constant.intValue	= StringToIntConstant(Compiler, LineNo, StringNo, Text, 16, &index);
    gcmASSERT(Text[index] == '\0');

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\" type=\"intConstant\""
								" format=\"hexadecimal\" value=\"%d\" />",
								LineNo,
								StringNo,
								Token->u.constant.intValue));

	return T_INTCONSTANT;
}
gctINT
slScanBoolConstant(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctBOOL Value,
	OUT slsLexToken * Token
	)
{
	gcmASSERT(Token);

	Token->lineNo			= LineNo;
	Token->stringNo			= StringNo;
	Token->type			= T_BOOLCONSTANT;
	Token->u.constant.boolValue	= Value;

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\" type=\"boolConstant\" value=\"%s\" />",
								LineNo,
								StringNo,
								(Token->u.constant.boolValue)? "true" : "false"));

	return T_BOOLCONSTANT;
}
gctINT
slScanConvToUnsignedType(
IN sloCOMPILER Compiler,
IN gctUINT LineNo,
IN gctUINT StringNo,
IN gctSTRING Symbol,
OUT slsLexToken * Token
)
{
	gcmASSERT(Token);
	Token->lineNo	= LineNo;
	Token->stringNo	= StringNo;

	/* Check as a reserved keyword */
	switch(_SearchKeyword(Symbol)) {
	case T_INT:
		Token->type = T_UINT;
		break;

	default:
		gcmASSERT(0);
		return T_EOF;
	}

	gcmVERIFY_OK(sloCOMPILER_Dump(Compiler,
				      slvDUMP_SCANNER,
				      "<TOKEN line=\"%d\" string=\"%d\" type=\"keyword\" symbol=\"%s\" />",
				      LineNo,
				      StringNo,
				      Symbol));
	return T_UINT;
}
void
glfDereferenceNamedObject(
    IN glsCONTEXT_PTR Context,
    IN glsNAMEDOBJECT_PTR Object
    )
{
    glsNAMEDOBJECTLIST_PTR list;

    if (!Object || !Context)
    {
        return;
    }

    if (--Object->referenceCount == 0)
    {
        list = Object->listBelonged;

        /* Destruct the object. */
        gcmVERIFY_OK((*Object->deleteObject) (Context, Object->object));
        Object->deleteObject = gcvNULL;

        /* Reset the object. */
        gcoOS_ZeroMemory(Object->object, list->objectSize);

        /* Add to the free list. */
        Object->next = list->freeList;
        list->freeList = Object;
    }
}
Example #10
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();
}
gceSTATUS
ppoPREPROCESSOR_MacroExpand_0_SelfContain(
    ppoPREPROCESSOR     PP,
    ppoINPUT_STREAM     *IS,
    ppoTOKEN            *Head,
    ppoTOKEN            *End,
    gctBOOL             *AnyExpanationHappened,
    gctBOOL             *MatchCase,
    ppoTOKEN            *ID)
{
    gceSTATUS status = gcvSTATUS_INVALID_DATA;

    ppoTOKEN id = gcvNULL;

    gctBOOL inhs = gcvFALSE;

    gcmONERROR(
        (*IS)->GetToken(PP, IS, &id, !ppvICareWhiteSpace)
        );

    gcmASSERT(id && id->type == ppvTokenType_ID);

    *ID = id;

    gcmTRACE(gcvLEVEL_VERBOSE, "ME : Begin to process %s.", id->poolString);

    gcmONERROR(
        ppoHIDE_SET_LIST_ContainSelf(PP, id, &inhs)
        );

    if (inhs == gcvTRUE)
    {
        gcmTRACE(gcvLEVEL_VERBOSE, "ME : self-contain.",id->poolString);

        *Head = id;
        *End  = id;
        *AnyExpanationHappened = gcvFALSE;
        *MatchCase = gcvTRUE;

        return gcvSTATUS_OK;
    }
    else
    {
        gcmTRACE(gcvLEVEL_VERBOSE, "ME : not self-contain.",id->poolString);

        *Head = gcvNULL;
        *End  = gcvNULL;
        *AnyExpanationHappened = gcvFALSE;
        *MatchCase = gcvFALSE;

        return gcvSTATUS_OK;
    }
OnError:
    if (id != gcvNULL)
    {
        gcmVERIFY_OK(ppoTOKEN_Destroy(PP, id));
        id = gcvNULL;
    }
    return status;
}
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
ppoPREPROCESSOR_MacroExpand_4_NoRealArg(
                                        ppoPREPROCESSOR     PP,
                                        ppoINPUT_STREAM     *IS,
                                        ppoTOKEN            *Head,
                                        ppoTOKEN            *End,
                                        gctBOOL             *AnyExpanationHappened,
                                        gctBOOL             *MatchCase,
                                        ppoTOKEN            ID
                                        )
{
    gceSTATUS status;

    ppoTOKEN id = ID;

    ppoTOKEN ahead = gcvNULL;

    gcmONERROR(
        (*IS)->GetToken(PP, IS, &ahead, !ppvICareWhiteSpace)
        );

    if (ahead->poolString != PP->keyword->lpara)
    {
        gcmTRACE(gcvLEVEL_VERBOSE, "ME : %s, no real arg.", id->poolString);

        *Head = id;
        *End  = id;
        *AnyExpanationHappened = gcvFALSE;
        *MatchCase = gcvTRUE;

        gcmONERROR(
            ppoINPUT_STREAM_UnGetToken(PP, (ppoINPUT_STREAM *)IS, ahead));

        gcmONERROR(ppoTOKEN_Destroy(PP, ahead));

        return gcvSTATUS_OK;
    }
    else
    {
        gcmTRACE(gcvLEVEL_VERBOSE, "ME : %s, real arg.", id->poolString);

        *MatchCase = gcvFALSE;
        *AnyExpanationHappened = gcvFALSE;

        gcmONERROR(
            ppoINPUT_STREAM_UnGetToken(PP, IS, ahead)
            );

        return gcvSTATUS_OK;
    }
OnError:
    if (ahead != gcvNULL)
    {
        gcmVERIFY_OK(ppoTOKEN_Destroy(PP, ahead));
        ahead = gcvNULL;
    }
	return status;
}
void
_glshInitializeRenderbuffer(
    GLContext Context
    )
{
    /* No renderbuffers bound yet. */
    Context->renderbuffer = gcvNULL;

    /* No frame buffer objects. */
    gcmVERIFY_OK(gcoOS_ZeroMemory(&Context->renderbufferObjects,
                                  gcmSIZEOF(Context->renderbufferObjects)));
}
/*******************************************************************************
**	_DestroyVGProfiler
**
**	Initialize the profiler for the context provided.
**
**	Arguments:
**
**		VGContext Context
**			Pointer to a new VGContext object.
*/
void
DestroyVGProfiler(
	_VGContext * Context
	)
{
    gcoPROFILER_Destroy(Context->hal);

    if (Context->profiler.enable)
    {
	    Context->profiler.enable = gcvFALSE;
    	gcmVERIFY_OK(gcoPROFILER_Destroy(Context->hal));
	}
}
static GLRenderbuffer
_NewRenderbuffer(
    GLContext Context,
    GLuint Name
    )
{
    GLRenderbuffer renderbuffer;
    gctPOINTER pointer = gcvNULL;

    /* Allocate memory for the renderbuffer object. */
    if (gcmIS_ERROR(gcoOS_Allocate(gcvNULL,
                                   gcmSIZEOF(struct _GLRenderbuffer),
                                   &pointer)))
    {
        /* Out of memory error. */
        gcmFATAL("%s(%d): Out of memory", __FUNCTION__, __LINE__);
        gl2mERROR(GL_OUT_OF_MEMORY);
        return gcvNULL;
    }

    renderbuffer = pointer;

    /* Create a new object. */
    if (!_glshInsertObject(&Context->renderbufferObjects,
                           &renderbuffer->object,
                           GLObject_Renderbuffer,
                           Name))
    {
        /* Roll back. */
        gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, renderbuffer));

        /* Out of memory error. */
        gcmFATAL("%s(%d): Out of memory", __FUNCTION__, __LINE__);
        gl2mERROR(GL_OUT_OF_MEMORY);
        return gcvNULL;
    }

    /* The renderbuffer object is not yet bound. */
    renderbuffer->width       = 0;
    renderbuffer->height      = 0;
    renderbuffer->format      = GL_NONE;
    renderbuffer->surface     = gcvNULL;
    renderbuffer->combined    = gcvNULL;
    renderbuffer->eglUsed     = GL_FALSE;

    renderbuffer->object.reference = 1;

    /* Return the renderbuffer. */
    return renderbuffer;
}
gceSTATUS
gcoPROFILER_Destroy(
	IN gcoHAL Hal
	)
{
    gcmHEADER();

   	if (gcPLS.hal->profiler.enable == 1)
    {
#if gcdNEW_PROFILER_FILE
        gcmWRITE_CONST(VPG_END);
#else
    	gcmWRITE_STRING("</VProfile>\n");
#endif

        gcoPROFILER_Flush(gcvNULL);
        if (gcPLS.hal->profiler.useSocket)
        {
            /* Close the socket. */
            gcmVERIFY_OK(gcoOS_CloseSocket(gcvNULL, gcPLS.hal->profiler.sockFd));
        }
        else
        {
            /* Close the profiler file. */
            gcmVERIFY_OK(gcoOS_Close(gcvNULL, gcPLS.hal->profiler.file));
        }
        gcPLS.hal->profiler.enable = 0;
    }
    else
    {
        gcPLS.hal->profiler.enable--;
    }

    gcmFOOTER_NO();
    return gcvSTATUS_OK;
}
static gctBOOL
ReadSource(
    IN gcoOS Os,
    IN gctCONST_STRING FileName,
    OUT gctSIZE_T * SourceSize,
    OUT gctSTRING * Source
    )
{
    gceSTATUS   status;
    gctFILE     file;
    gctUINT32   count;
    gctSIZE_T   byteRead;
    gctSTRING   source;

    gcmASSERT(FileName);

    status = gcoOS_Open(Os, FileName, gcvFILE_READ, &file);

    if (gcmIS_ERROR(status))
    {
        printf("*ERROR* Failed to open input file: %s\n", FileName);
        return gcvFALSE;
    }

    gcmVERIFY_OK(gcoOS_Seek(Os, file, 0, gcvFILE_SEEK_END));
    gcmVERIFY_OK(gcoOS_GetPos(Os, file, &count));

    status = gcoOS_Allocate(Os, count + 1, (gctPOINTER *) &source);
    if (!gcmIS_SUCCESS(status))
    {
        printf("*ERROR* Not enough memory\n");
        gcmVERIFY_OK(gcoOS_Close(Os, file));
        return gcvFALSE;
    }

    gcmVERIFY_OK(gcoOS_SetPos(Os, file, 0));
    status = gcoOS_Read(Os, file, count, source, &byteRead);
    if (!gcmIS_SUCCESS(status) || byteRead != count)
    {
        printf("*ERROR* Failed to open input file: %s\n", FileName);
        gcmVERIFY_OK(gcoOS_Close(Os, file));
        return gcvFALSE;
    }

    source[count] = '\0';
    gcmVERIFY_OK(gcoOS_Close(Os, file));

    *SourceSize = count;
    *Source = source;
    return gcvTRUE;
}
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;
}
Example #20
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();
}
Example #21
0
static void
_DestroyThreadData(
    gcsTLS_PTR TLS
    )
{
    gcmHEADER_ARG("TLS=0x%x", TLS);

    if (TLS->context != gcvNULL)
    {
        /*VEGLThreadData thread;*/
        VEGLDisplay head;

        /*thread = (VEGLThreadData) TLS->context;*/

        head = (VEGLDisplay) gcoOS_GetPLSValue(gcePLS_VALUE_EGL_DISPLAY_INFO);

        while (head != EGL_NO_DISPLAY)
        {
            VEGLDisplay display = head;

            if (display->ownerThread == gcoOS_GetCurrentThreadID())
            {
                /* This thread has not eglTerminated the display.*/
                eglTerminate(display);
            }

            head = display->next;
            if (TLS->ProcessExiting)
            {
                gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, display));
                gcoOS_SetPLSValue(gcePLS_VALUE_EGL_DISPLAY_INFO, (gctPOINTER) head);
            }
        }

        TLS->context = gcvNULL;
    }

    gcmFOOTER_NO();
}
gctINT
slScanFieldSelection(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING Symbol,
	OUT slsLexToken * Token
	)
{
	gceSTATUS		status;
	sltPOOL_STRING	symbolInPool;

	gcmASSERT(Token);

	Token->lineNo	= LineNo;
	Token->stringNo	= StringNo;

	status = sloCOMPILER_AllocatePoolString(
											Compiler,
											Symbol,
											&symbolInPool);

	if (gcmIS_ERROR(status)) return T_EOF;

	Token->type = T_FIELD_SELECTION;
	Token->u.fieldSelection = symbolInPool;

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\" type=\"fieldSelection\" symbol=\"%s\" />",
								LineNo,
								StringNo,
								Token->u.fieldSelection));

	return T_FIELD_SELECTION;
}
static gctSIZE_T
_InitState(
    IN gcoVGHARDWARE Hardware,
    IN gcsVGCONTEXT_INIT_PTR InitInfo,
    IN gctSIZE_T BufferIndex,
    IN gctUINT32 StateIndex,
    IN gctUINT32 ResetValue,
    IN gctSIZE_T ValueCount
    )
{
    gctSIZE_T result;
    gctUINT32_PTR buffer;
    gcsVGCONTEXT_MAP_PTR mapPrev;
    gcsVGCONTEXT_MAP_PTR mapCurr;
    gctSIZE_T i;

    /* Create shortcuts. */
#ifndef __QNXNTO__
    buffer  = Hardware->context.buffer;
    mapPrev = Hardware->context.mapPrev;
    mapCurr = Hardware->context.mapCurr;
#else
    buffer  = Hardware->pContext->buffer;
    mapPrev = Hardware->pContext->mapPrev;
    mapCurr = Hardware->pContext->mapCurr;
#endif

    /* End of buffer alignemnt? */
    if (ValueCount == 0)
    {
        /* Determine if we need alignment. */
        gctSIZE_T align = BufferIndex & 1;

        /* Align in case when the previous state left the context
           buffer unaligned. */
        if (align)
        {
            /* Put a filler in place. */
            buffer[BufferIndex] = 0xDEADDEAD;

            /* Advance the index. */
            BufferIndex += 1;
        }

        /* Save information for this LoadState. */
        InitInfo->bufferIndex = BufferIndex;

        /* Return number of slots required. */
        result = 0;
    }
    else
    {
        /* Determnine map index. */
#ifndef __QNXNTO__
        gctUINT32 mapIndex = StateIndex - Hardware->context.mapFirst;
#else
        gctUINT32 mapIndex = StateIndex - Hardware->pContext->mapFirst;
#endif

        /* See if we can append this state to the previous one. */
        if (StateIndex == InitInfo->stateIndex)
        {
            /* Update last load state. */
            gcmVERIFY_OK(gcoVGHARDWARE_StateCommand(
                Hardware,
                &buffer[InitInfo->bufferIndex],
                InitInfo->loadIndex,
                InitInfo->valueCount + ValueCount,
                gcvNULL
                ));

            /* Walk all the states. */
            for (i = 0; i < ValueCount; ++i)
            {
                /* Set state to uninitialized value. */
                buffer[BufferIndex + i] = ResetValue;

                /* Set index in state mapping table. */
                mapPrev[mapIndex + i].index = BufferIndex + i;
                mapCurr[mapIndex + i].index = BufferIndex + i;
            }

            /* Update last address and size. */
            InitInfo->stateIndex += ValueCount;
            InitInfo->valueCount += ValueCount;

            /* Return number of slots required. */
            result = ValueCount;
        }
        else
        {
            /* Determine if we need alignment. */
            gctSIZE_T align = BufferIndex & 1;

            /* Align in case when the previous state left the context
               buffer unaligned. */
            if (align)
            {
                /* Put a filler in place. */
                buffer[BufferIndex] = 0xDEADDEAD;

                /* Advance the index. */
                BufferIndex += 1;
            }

            /* Assemble load state command. */
            gcmVERIFY_OK(gcoVGHARDWARE_StateCommand(
                Hardware,
                &buffer[BufferIndex],
                StateIndex,
                ValueCount,
                gcvNULL
                ));

            /* Walk all the states. */
            for (i = 0; i < ValueCount; ++i)
            {
                /* Set state to uninitialized value. */
                buffer[BufferIndex + 1 + i] = ResetValue;

                /* Set index in state mapping table. */
                mapPrev[mapIndex + i].index = BufferIndex + 1 + i;
                mapCurr[mapIndex + i].index = BufferIndex + 1 + i;
            }

            /* Save information for this LoadState. */
            InitInfo->loadIndex   = StateIndex;
            InitInfo->bufferIndex = BufferIndex;
            InitInfo->stateIndex  = StateIndex + ValueCount;
            InitInfo->valueCount  = ValueCount;

            /* Return number of slots required. */
            result = align + 1 + ValueCount;
        }
    }

    /* Return size for load state. */
    return result;
}
gceSTATUS
gcoPROFILER_Initialize(
	IN gcoHAL Hal
	)
{
    gceSTATUS status = gcvSTATUS_OK;
    char* fileName;
    char* filter = gcvNULL;
    gctSTRING portName;
    gctINT port;
	gcsHAL_INTERFACE iface;

    gcmHEADER();

    /* Check if already initialized. */
   	if (gcPLS.hal->profiler.enable)
    {
        gcPLS.hal->profiler.enable++;
        gcmFOOTER();
        return status;
    }

	/* Get profile setting. */
	iface.command = gcvHAL_GET_PROFILE_SETTING;

	/* Call the kernel. */
	status = gcoOS_DeviceControl(gcvNULL,
								 IOCTL_GCHAL_INTERFACE,
								 &iface, gcmSIZEOF(iface),
								 &iface, gcmSIZEOF(iface));

	if (gcmIS_ERROR(status) || !iface.u.GetProfileSetting.enable)
	{
    	gcPLS.hal->profiler.enable = 0;
        status = gcvSTATUS_GENERIC_IO;

        gcmFOOTER();
        return status;
	}

	gcmVERIFY_OK(gcoOS_ZeroMemory(&gcPLS.hal->profiler, gcmSIZEOF(gcPLS.hal->profiler)));

    gcoOS_GetEnv(gcvNULL,
                 "VP_COUNTER_FILTER",
                 &filter);

    /* Enable/Disable specific counters. */
    if ((filter != gcvNULL))
    {
        gctSIZE_T bitsLen;
        gcoOS_StrLen(filter, &bitsLen);
        if (bitsLen > 2)
        {
            gcPLS.hal->profiler.enableHal = (filter[2] == '1');
        }
        else
        {
            gcPLS.hal->profiler.enableHal = gcvTRUE;
        }

        if (bitsLen > 3)
        {
            gcPLS.hal->profiler.enableHW = (filter[3] == '1');
        }
        else
        {
            gcPLS.hal->profiler.enableHW = gcvTRUE;
        }

        if (bitsLen > 8)
        {
            gcPLS.hal->profiler.enableSH = (filter[8] == '1');
        }
        else
        {
            gcPLS.hal->profiler.enableSH = gcvTRUE;
        }
    }
    else
    {
        gcPLS.hal->profiler.enableHal = gcvTRUE;
        gcPLS.hal->profiler.enableHW = gcvTRUE;
        gcPLS.hal->profiler.enableSH = gcvTRUE;
    }

	gcoOS_GetEnv(gcvNULL,
				 "VPROFILER_OUTPUT",
				 &fileName);

    gcPLS.hal->profiler.useSocket = gcvFALSE;
	if (fileName && *fileName != '\0' && *fileName != ' ')
	{
        /* Extract port info. */
        gcoOS_StrFindReverse(fileName, ':', &portName);

        if (portName)
        {
            gcoOS_StrToInt(portName + 1, &port);

            if (port > 0)
            {
                /*status = gcoOS_Socket(gcvNULL, AF_INET, SOCK_STREAM, 0, &gcPLS.hal->profiler.sockFd);*/
                status = gcoOS_Socket(gcvNULL, 2, 1, 0, &gcPLS.hal->profiler.sockFd);

                if (gcmIS_SUCCESS(status))
                {
                    *portName = '\0';
                    status = gcoOS_Connect(gcvNULL,
                            gcPLS.hal->profiler.sockFd, fileName, port);
                    *portName = ':';

                    if (gcmIS_SUCCESS(status))
	                {
                        gcPLS.hal->profiler.useSocket = gcvTRUE;
                    }
                }
            }
        }
	}
    else
    {
		fileName = iface.u.GetProfileSetting.fileName;
    }

    if (! gcPLS.hal->profiler.useSocket)
	{
		status = gcoOS_Open(gcvNULL,
							fileName,
#ifdef gcdNEW_PROFILER_FILE
							gcvFILE_CREATE,
#else
							gcvFILE_CREATETEXT,
#endif
							&gcPLS.hal->profiler.file);
	}

    if (gcmIS_ERROR(status))
	{
    	gcPLS.hal->profiler.enable = 0;
        status = gcvSTATUS_GENERIC_IO;

        gcmFOOTER();
        return status;
	}

    gcPLS.hal->profiler.enable = 1;
	gcoOS_GetTime(&gcPLS.hal->profiler.frameStart);
	gcPLS.hal->profiler.frameStartTimeusec = gcPLS.hal->profiler.frameStart;
	gcPLS.hal->profiler.prevVSInstCount = 0;
	gcPLS.hal->profiler.prevVSBranchInstCount = 0;
	gcPLS.hal->profiler.prevVSTexInstCount = 0;
	gcPLS.hal->profiler.prevVSVertexCount = 0;
	gcPLS.hal->profiler.prevPSInstCount = 0;
	gcPLS.hal->profiler.prevPSBranchInstCount = 0;
	gcPLS.hal->profiler.prevPSTexInstCount = 0;
	gcPLS.hal->profiler.prevPSPixelCount = 0;

#if gcdNEW_PROFILER_FILE
    gcmWRITE_CONST(VPHEADER);
    gcmWRITE_BUFFER(4, "VP12");
#else
	gcmWRITE_STRING("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<VProfile>\n");
#endif

    /* Success. */
    gcmFOOTER();
    return status;
}
/*******************************************************************************
**
**  gcoBUFFER_Commit
**
**  Commit the command buffer to the hardware.
**
**  INPUT:
**
**      gcoBUFFER Buffer
**          Pointer to a gcoBUFFER object.
**
**      gcePIPE_SELECT CurrentPipe
**          Current graphics pipe.
**
**      gcsSTATE_DELTA_PTR StateDelta
**          Pointer to the state delta.
**
**      gcoQUEUE Queue
**          Pointer to a gcoQUEUE object.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoBUFFER_Commit(
    IN gcoBUFFER Buffer,
    IN gcePIPE_SELECT CurrentPipe,
    IN gcsSTATE_DELTA_PTR StateDelta,
    IN gcoQUEUE Queue
    )
{
    gcsHAL_INTERFACE iface;
    gceSTATUS status;
    gcoCMDBUF current;

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

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

    /* Grab current command buffer. */
    current = Buffer->currentCommandBuffer;

    if (current == gcvNULL)
    {
        /* No command buffer, done. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    if (current->offset - current->startOffset <= Buffer->info.reservedHead)
    {
        /* Commit the event queue. */
        status = gcoQUEUE_Commit(Queue);
        gcmFOOTER();
        return status;
    }

    /* Make sure the tail got aligned properly. */
    current->offset = gcmALIGN(current->offset, Buffer->info.alignment);

    if (gcPLS.hal->dump != gcvNULL)
    {
        /* Dump the command buffer. */
        gcmVERIFY_OK(
            gcoDUMP_DumpData(gcPLS.hal->dump,
                             gcvTAG_COMMAND,
                             0,
                             current->offset
                             - current->startOffset
                             - Buffer->info.reservedHead,
                             (gctUINT8_PTR) current->logical
                             + current->startOffset
                             + Buffer->info.reservedHead));
    }

    /* The current pipe becomes the exit pipe for the current command buffer. */
    current->exitPipe = CurrentPipe;

    /* Send command and context buffer to hardware. */
    iface.command = gcvHAL_COMMIT;
    iface.u.Commit.context       =
#ifndef VIVANTE_NO_3D
        (current->using2D && !current->using3D) ? gcvNULL : Buffer->context;
#else
        gcvNULL;
#endif

    iface.u.Commit.commandBuffer = current;
    iface.u.Commit.delta         = StateDelta;
    iface.u.Commit.queue         = Queue->head;

    /* Call kernel service. */
    gcmONERROR(
        gcoOS_DeviceControl(gcvNULL,
                            IOCTL_GCHAL_INTERFACE,
                            &iface, gcmSIZEOF(iface),
                            &iface, gcmSIZEOF(iface)));

    gcmONERROR(iface.status);

    /* Free the event queue. */
    gcmONERROR(gcoQUEUE_Free(Queue));

    /* Advance the offset for next commit. */
    current->startOffset = current->offset + Buffer->info.reservedTail;

    if (current->bytes - current->startOffset > Buffer->totalReserved)
    {
        /* Adjust buffer offset and size. */
        current->offset = current->startOffset + Buffer->info.reservedHead;
        current->free   = current->bytes - current->offset
                        - Buffer->info.alignment
                        - Buffer->info.reservedTail;
    }
    else
    {
        /* Buffer is full. */
        current->startOffset = current->bytes;
        current->offset      = current->bytes;
        current->free        = 0;
    }

    /* The exit pipe becomes the entry pipe for the next command buffer. */
    current->entryPipe = current->exitPipe;

#if gcdSECURE_USER
    /* Reset the state array tail. */
    current->hintArrayTail = current->hintArray;
#endif

    /* Reset usage flags. */
    current->using2D         = gcvFALSE;
    current->using3D         = gcvFALSE;
    current->usingFilterBlit = gcvFALSE;
    current->usingPalette    = gcvFALSE;

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

OnError:
    /* Return the status. */
    gcmFOOTER();
    return status;
}
/*******************************************************************************
**
**  gcoBUFFER_Construct
**
**  Construct a new gcoBUFFER object.
**
**  INPUT:
**
**      gcoHAL Hal
**          Pointer to a gcoHAL object.
**
**      gcoHARDWARE Hardware
**          Pointer to a gcoHARDWARE object.
**
**      gckCONTEXT Context
**          Pointer to a gckCONTEXT object.
**
**      gctSIZE_T MaxSize
**          Maximum size of buffer.
**
**  OUTPUT:
**
**      gcoBUFFER * Buffer
**          Pointer to a variable that will hold the the gcoBUFFER object
**          pointer.
*/
gceSTATUS
gcoBUFFER_Construct(
    IN gcoHAL Hal,
    IN gcoHARDWARE Hardware,
    IN gckCONTEXT Context,
    IN gctSIZE_T MaxSize,
    OUT gcoBUFFER * Buffer
    )
{
    gceSTATUS status;
    gcoBUFFER buffer = gcvNULL;
    gctUINT i = 0;
    gctPOINTER pointer = gcvNULL;

    gcmHEADER_ARG("Hal=0x%x Hardware=0x%x Context=0x%x MaxSize=%lu",
                  Hal, Hardware, Context, MaxSize);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Hal, gcvOBJ_HAL);
    gcmVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
    gcmDEBUG_VERIFY_ARGUMENT(Buffer != gcvNULL);

    /***************************************************************************
    ** Allocate and reset the gcoBUFFER object.
    */

    gcmONERROR(gcoOS_Allocate(
        gcvNULL, gcmSIZEOF(struct _gcoBUFFER), &pointer
        ));

    buffer = pointer;

    /* Initialize the gcoBUFFER object. */
    buffer->object.type = gcvOBJ_BUFFER;
    buffer->hal         = Hal;
    buffer->context     = Context;

    /* Maximum size of buffer. */
    buffer->size    = 0;
    buffer->maxSize = MaxSize;

    /* Zero the command buffers. */
    for (i = 0; i < gcmCOUNTOF(buffer->commandBuffers); ++i)
    {
        buffer->commandBuffers[i] = gcvNULL;
        buffer->signal[i]         = gcvNULL;
    }


    /***************************************************************************
    ** Query alignment.
    */

    gcmONERROR(gcoHARDWARE_QueryCommandBuffer(
        &buffer->info.alignment,
        &buffer->info.reservedHead,
        &buffer->info.reservedTail
        ));

    buffer->totalReserved
        = buffer->info.reservedHead
        + buffer->info.reservedTail
        + buffer->info.alignment;


    /***************************************************************************
    ** Initialize the command buffers.
    */

    for (i = 0; i < gcdCMD_BUFFERS; ++i)
    {
        /* Construct a command buffer. */
        gcmONERROR(gcoCMDBUF_Construct(
            gcvNULL,
            gcvNULL,
            buffer->maxSize,
            &buffer->info,
            &buffer->commandBuffers[i]
            ));

        /* Create the signal. */
        gcmONERROR(gcoOS_CreateSignal(
            gcvNULL, gcvFALSE, &buffer->signal[i]
            ));

        gcmTRACE_ZONE(
            gcvLEVEL_INFO, gcvZONE_SIGNAL,
            "%s(%d): buffer %d signal created 0x%08X",
            __FUNCTION__, __LINE__,
            i, buffer->signal[i]
            );

        /* Mark the buffer as available. */
        gcmONERROR(gcoOS_Signal(
            gcvNULL, buffer->signal[i], gcvTRUE\
            ));
    }

    /* Number of buffers initialized. */
    buffer->count = gcdCMD_BUFFERS;

    /* Grab the first command buffer. */
    buffer->currentCommandBuffer = gcvNULL;
    gcmONERROR(gcoBUFFER_GetCMDBUF(buffer));

    /* Return pointer to the gcoBUFFER object. */
    *Buffer = buffer;

    /* Success. */
    gcmFOOTER_ARG("*Buffer=0x%x", *Buffer);
    return gcvSTATUS_OK;

OnError:
    if (buffer != gcvNULL)
    {
        gcmVERIFY_OK(gcoBUFFER_FreeObjects(buffer));
    }

    /* Return the status. */
    gcmFOOTER();
    return status;
}
/*******************************************************************************
**
**  gcoCMDBUF_Construct
**
**  Construct a new gcoCMDBUF object.
**
**  INPUT:
**
**      gcoOS Os
**          Pointer to a gcoOS object.
**
**      gcoHARDWARE Hardware
**          Pointer to a gcoHARDWARE object.
**
**      gctSIZE_T Bytes
**          Number of bytes for the buffer.
**
**      gcsCOMMAND_BUFFER_PTR Info
**          Alignment and head/tail information.
**
**  OUTPUT:
**
**      gcoCMDBUF * CommandBuffer
**          Pointer to a variable that will hold the the gcoCMDBUF object
**          pointer.
*/
gceSTATUS
gcoCMDBUF_Construct(
    IN gcoOS Os,
    IN gcoHARDWARE Hardware,
    IN gctSIZE_T Bytes,
    IN gcsCOMMAND_INFO_PTR Info,
    OUT gcoCMDBUF * CommandBuffer
    )
{
    gceSTATUS status;
    gcoCMDBUF commandBuffer = gcvNULL;
    gctSIZE_T objectSize;

#ifdef __QNXNTO__
    gctPHYS_ADDR physical;
#else
    gctPOINTER pointer = gcvNULL;
#endif

    gcmHEADER_ARG("Bytes=%lu Info=0x%x", Bytes, Info);

    /* Verify the arguments. */
    gcmDEBUG_VERIFY_ARGUMENT(Bytes > 0);
    gcmDEBUG_VERIFY_ARGUMENT(CommandBuffer != gcvNULL);

    /* Set the size of the object. */
    objectSize = gcmSIZEOF(struct _gcoCMDBUF);

    /* Allocate the gcoCMDBUF object. */
#ifdef __QNXNTO__
    /* gcoCMDBUF object needs to be accessible from the kernel; to avoid
       copying of the data for each access, allocate the object from the
       kernel non-paged memory. */
    gcmONERROR(gcoOS_AllocateNonPagedMemory(
        gcvNULL, gcvTRUE, &objectSize, &physical, (gctPOINTER *) &commandBuffer
        ));
#else
    /* Currently in most OS we are able to access the user-side data from
       the kernel by simple memory mapping, therefore here we allocate the
       object from the cached user memory. */
    gcmONERROR(gcoOS_Allocate(gcvNULL, objectSize, &pointer));

    commandBuffer = pointer;
#endif

    /* Reset the command buffer object. */
    gcmONERROR(gcoOS_ZeroMemory(commandBuffer, objectSize));

    /* Initialize the gcoCMDBUF object. */
    commandBuffer->object.type = gcvOBJ_COMMANDBUFFER;
    commandBuffer->bytes       = Bytes;

    /* Allocate the physical buffer for the command. */
    gcmONERROR(gcoOS_AllocateContiguous(
        gcvNULL, gcvTRUE,
        &commandBuffer->bytes,
        &commandBuffer->physical,
        &commandBuffer->logical
        ));

    /* Initialize command buffer. */
    commandBuffer->free = commandBuffer->bytes;

#if gcdSECURE_USER
    /* Determine the size of the state array. */
    commandBuffer->hintArraySize = Bytes;

    /* Allocate the state array. */
#ifdef __QNXNTO__
    gcmONERROR(gcoOS_AllocateNonPagedMemory(
        gcvNULL, gcvTRUE,
        &commandBuffer->hintArraySize,
        &physical,
        (gctPOINTER *) &commandBuffer->hintArray
        ));
#else
    gcmONERROR(gcoOS_Allocate(
        gcvNULL,
        commandBuffer->hintArraySize,
        &pointer
        ));

    commandBuffer->hintArray = pointer;
#endif

    /* Initialize the state array tail pointer. */
    commandBuffer->hintArrayTail = commandBuffer->hintArray;
#endif

    /* Return pointer to the gcoCMDBUF object. */
    *CommandBuffer = commandBuffer;

    /* Success. */
    gcmFOOTER_ARG("*CommandBuffer=0x%x", *CommandBuffer);
    return gcvSTATUS_OK;

OnError:
    /* Roll back. */
    if (commandBuffer != gcvNULL)
    {
        if (commandBuffer->logical != gcvNULL)
        {
            gcmVERIFY_OK(gcoOS_FreeContiguous(
                gcvNULL,
                commandBuffer->physical,
                commandBuffer->logical,
                commandBuffer->bytes
                ));
        }

#if gcdSECURE_USER
        if (commandBuffer->hintArray != gcvNULL)
        {
#ifdef __QNXNTO__
            gcmVERIFY_OK(gcoOS_FreeNonPagedMemory(
                gcvNULL,
                commandBuffer->hintArraySize,
                gcvNULL,
                commandBuffer->hintArray
                ));
#else
            gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, commandBuffer->hintArray));
#endif
        }
#endif

#ifdef __QNXNTO__
        gcmVERIFY_OK(gcoOS_FreeNonPagedMemory(
            gcvNULL, objectSize, gcvNULL, commandBuffer
            ));
#else
        gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, commandBuffer));
#endif
    }

    /* Return the status. */
    gcmFOOTER();
    return status;
}
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;
}
gceSTATUS
gcoQUEUE_Construct(
    IN gcoOS Os,
    OUT gcoQUEUE * Queue
    )
{
    gcoQUEUE queue = gcvNULL;
    gceSTATUS status;
#ifdef __QNXNTO__
    gctSIZE_T allocationSize;
    gctPHYS_ADDR physAddr;
#endif
    gctPOINTER pointer = gcvNULL;

    gcmHEADER();

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

    /* Create the queue. */
    gcmONERROR(
        gcoOS_Allocate(gcvNULL,
                       gcmSIZEOF(struct _gcoQUEUE),
                       &pointer));
    queue = pointer;

    /* Initialize the object. */
    queue->object.type = gcvOBJ_QUEUE;

    /* Nothing in the queue yet. */
    queue->head = queue->tail = gcvNULL;

    queue->recordCount = 0;

#ifdef __QNXNTO__
    /* Allocate buffer of records. */
    allocationSize = BUFFER_SIZE;
    physAddr = 0;
    gcmONERROR(
        gcoOS_AllocateNonPagedMemory(gcvNULL,
                                     gcvTRUE,
                                     &allocationSize,
                                     &physAddr,
                                     (gctPOINTER *) &queue->records));
    queue->freeBytes = allocationSize;
    queue->offset = 0;
#else
    queue->freeList = gcvNULL;
#endif

    /* Return gcoQUEUE pointer. */
    *Queue = queue;

    /* Success. */
    gcmFOOTER_ARG("*Queue=0x%x", *Queue);
    return gcvSTATUS_OK;

OnError:
    if (queue != gcvNULL)
    {
        /* Roll back. */
        gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, queue));
    }

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