Bool VIV2DGPUBlitComplete(GALINFOPTR galInfo, Bool wait) {
    TRACE_ENTER();
    gceSTATUS status = gcvSTATUS_OK;
    VIVGPUPtr gpuctx = (galInfo->mGpu);
    gctBOOL stall = wait ? gcvTRUE : gcvFALSE;
    status = gcoHAL_Commit(gpuctx->mDriver->mHal, stall);
    if (status != gcvSTATUS_OK) {
        TRACE_ERROR("HAL commit Failed\n");
        TRACE_EXIT(FALSE);
    }
    TRACE_EXIT(TRUE);
}
gceSTATUS
gcoPROFILER_EndDraw(
    IN gcoHAL Hal,
    IN gctBOOL FirstDraw
    )
{
/*#if	(PROFILE_HAL_COUNTERS || PROFILE_HW_COUNTERS)*/
	gcsHAL_INTERFACE iface;
    gceSTATUS status;
    static gcsPROFILER previous;
    static gcsPROFILER_COUNTERS    precounters;

/*#endif*/

    gcmHEADER();

	if (!gcPLS.hal->profiler.enable)
	{
        gcmFOOTER_NO();
		return gcvSTATUS_OK;
	}

/*#if PROFILE_HAL_COUNTERS*/
    if (gcPLS.hal->profiler.enableHal)
    {
#if gcdNEW_PROFILER_FILE
        if(FirstDraw == gcvTRUE)
            {
            gcoOS_ZeroMemory(&previous, gcmSIZEOF(previous));
            }

        gcmWRITE_CONST(VPG_HAL);

        gcmWRITE_COUNTER(VPC_HALVERTBUFNEWBYTEALLOC, gcPLS.hal->profiler.vertexBufferNewBytesAlloc-previous.vertexBufferNewBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALVERTBUFTOTALBYTEALLOC, gcPLS.hal->profiler.vertexBufferTotalBytesAlloc-previous.vertexBufferTotalBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALVERTBUFNEWOBJALLOC, gcPLS.hal->profiler.vertexBufferNewObjectsAlloc-previous.vertexBufferNewObjectsAlloc);
        gcmWRITE_COUNTER(VPC_HALVERTBUFTOTALOBJALLOC, gcPLS.hal->profiler.vertexBufferTotalObjectsAlloc-previous.vertexBufferTotalObjectsAlloc);

        gcmWRITE_COUNTER(VPC_HALINDBUFNEWBYTEALLOC, gcPLS.hal->profiler.indexBufferNewBytesAlloc-previous.indexBufferNewBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALINDBUFTOTALBYTEALLOC, gcPLS.hal->profiler.indexBufferTotalBytesAlloc-previous.indexBufferTotalBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALINDBUFNEWOBJALLOC, gcPLS.hal->profiler.indexBufferNewObjectsAlloc-previous.indexBufferNewObjectsAlloc);
        gcmWRITE_COUNTER(VPC_HALINDBUFTOTALOBJALLOC, gcPLS.hal->profiler.indexBufferTotalObjectsAlloc-previous.indexBufferTotalObjectsAlloc);

        gcmWRITE_COUNTER(VPC_HALTEXBUFNEWBYTEALLOC, gcPLS.hal->profiler.textureBufferNewBytesAlloc-previous.textureBufferNewBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALTEXBUFTOTALBYTEALLOC, gcPLS.hal->profiler.textureBufferTotalBytesAlloc-previous.textureBufferTotalBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALTEXBUFNEWOBJALLOC, gcPLS.hal->profiler.textureBufferNewObjectsAlloc-previous.textureBufferNewObjectsAlloc);
        gcmWRITE_COUNTER(VPC_HALTEXBUFTOTALOBJALLOC, gcPLS.hal->profiler.textureBufferTotalObjectsAlloc-previous.textureBufferTotalObjectsAlloc);

        gcmWRITE_CONST(VPG_END);
        gcoOS_MemCopy(&previous,&gcPLS.hal->profiler,gcmSIZEOF(gcsPROFILER));
#else
    	gcmWRITE_STRING("<HALCounters>\n");

	    gcmPRINT_XML_COUNTER(vertexBufferNewBytesAlloc);
    	gcmPRINT_XML_COUNTER(vertexBufferTotalBytesAlloc);
	    gcmPRINT_XML_COUNTER(vertexBufferNewObjectsAlloc);
    	gcmPRINT_XML_COUNTER(vertexBufferTotalObjectsAlloc);

	    gcmPRINT_XML_COUNTER(indexBufferNewBytesAlloc);
    	gcmPRINT_XML_COUNTER(indexBufferTotalBytesAlloc);
	    gcmPRINT_XML_COUNTER(indexBufferNewObjectsAlloc);
    	gcmPRINT_XML_COUNTER(indexBufferTotalObjectsAlloc);

	    gcmPRINT_XML_COUNTER(textureBufferNewBytesAlloc);
    	gcmPRINT_XML_COUNTER(textureBufferTotalBytesAlloc);
	    gcmPRINT_XML_COUNTER(textureBufferNewObjectsAlloc);
    	gcmPRINT_XML_COUNTER(textureBufferTotalObjectsAlloc);

	    gcmWRITE_STRING("</HALCounters>\n");
#endif

	    /* Reset per-frame counters. */
	}
/*#endif*/

/*#if PROFILE_HW_COUNTERS*/
    /* gcvHAL_READ_ALL_PROFILE_REGISTERS. */
    if (gcPLS.hal->profiler.enableHW)
    {
		if (gcPLS.hal->profiler.isSyncMode)
			gcoHAL_Commit(gcvNULL, gcvTRUE);
#if VIVANTE_PROFILER_PERDRAW
            /* Set Register clear Flag. */
            iface.command = gcvHAL_READ_PROFILER_REGISTER_SETTING;
            iface.u.SetProfilerRegisterClear.bclear = gcvFALSE;

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

		/* Verify result. */
		if (gcmIS_ERROR(status))    return gcvSTATUS_GENERIC_IO;
#endif
		iface.command = gcvHAL_READ_ALL_PROFILE_REGISTERS;

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

		/* Verify result. */
		if (gcmNO_ERROR(status))
		{
        #define gcmCOUNTERCOMPARE(name)    ((iface.u.RegisterProfileData.counters.name) - (precounters.name))
        #define gcmDRAWCOUNTERPRE(name)   (precounters.name)

#if gcdNEW_PROFILER_FILE
            if(FirstDraw == gcvFALSE)
                {
                gcoOS_ZeroMemory(&precounters, gcmSIZEOF(precounters));

                gcmDRAWCOUNTERPRE(vs_inst_counter) =   gcPLS.hal->profiler.prevVSInstCount;
		   gcmDRAWCOUNTERPRE(vtx_branch_inst_counter) =	gcPLS.hal->profiler.prevVSBranchInstCount ;
		   gcmDRAWCOUNTERPRE(vtx_texld_inst_counter) = gcPLS.hal->profiler.prevVSTexInstCount;
                gcmDRAWCOUNTERPRE(rendered_vertice_counter) =	gcPLS.hal->profiler.prevVSVertexCount;

                gcmDRAWCOUNTERPRE(ps_inst_counter) =gcPLS.hal->profiler.prevPSInstCount;
                gcmDRAWCOUNTERPRE(pxl_branch_inst_counter) = gcPLS.hal->profiler.prevPSBranchInstCount;
                gcmDRAWCOUNTERPRE(pxl_texld_inst_counter) =	gcPLS.hal->profiler.prevPSTexInstCount;
                gcmDRAWCOUNTERPRE(rendered_pixel_counter) = gcPLS.hal->profiler.prevPSPixelCount;
                }
            gcmWRITE_CONST(VPG_HW);
            gcmWRITE_CONST(VPG_GPU);
            gcmWRITE_COUNTER(VPC_GPUREAD64BYTE, gcmCOUNTERCOMPARE(gpuTotalRead64BytesPerFrame));
            gcmWRITE_COUNTER(VPC_GPUWRITE64BYTE, gcmCOUNTERCOMPARE(gpuTotalWrite64BytesPerFrame));
            gcmWRITE_COUNTER(VPC_GPUCYCLES, gcmCOUNTERCOMPARE(gpuCyclesCounter));
            gcmWRITE_COUNTER(VPC_GPUTOTALCYCLES, gcmCOUNTERCOMPARE(gpuTotalCyclesCounter));
            gcmWRITE_COUNTER(VPC_GPUIDLECYCLES, gcmCOUNTERCOMPARE(gpuIdleCyclesCounter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_VS);
            gcmWRITE_COUNTER(VPC_VSINSTCOUNT, gcmCOUNTERCOMPARE(vs_inst_counter));
            gcmWRITE_COUNTER(VPC_VSBRANCHINSTCOUNT, gcmCOUNTERCOMPARE(vtx_branch_inst_counter));
            gcmWRITE_COUNTER(VPC_VSTEXLDINSTCOUNT, gcmCOUNTERCOMPARE(vtx_texld_inst_counter));
            gcmWRITE_COUNTER(VPC_VSRENDEREDVERTCOUNT, gcmCOUNTERCOMPARE(rendered_vertice_counter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_PA);
            gcmWRITE_COUNTER(VPC_PAINVERTCOUNT, gcmCOUNTERCOMPARE(pa_input_vtx_counter));
            gcmWRITE_COUNTER(VPC_PAINPRIMCOUNT, gcmCOUNTERCOMPARE(pa_input_prim_counter));
            gcmWRITE_COUNTER(VPC_PAOUTPRIMCOUNT, gcmCOUNTERCOMPARE(pa_output_prim_counter));
            gcmWRITE_COUNTER(VPC_PADEPTHCLIPCOUNT, gcmCOUNTERCOMPARE(pa_depth_clipped_counter));
            gcmWRITE_COUNTER(VPC_PATRIVIALREJCOUNT, gcmCOUNTERCOMPARE(pa_trivial_rejected_counter));
            gcmWRITE_COUNTER(VPC_PACULLCOUNT, gcmCOUNTERCOMPARE(pa_culled_counter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_SETUP);
            gcmWRITE_COUNTER(VPC_SETRIANGLECOUNT, gcmCOUNTERCOMPARE(se_culled_triangle_count));
            gcmWRITE_COUNTER(VPC_SELINECOUNT, gcmCOUNTERCOMPARE(se_culled_lines_count));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_RA);
            gcmWRITE_COUNTER(VPC_RAVALIDPIXCOUNT, gcmCOUNTERCOMPARE(ra_valid_pixel_count));
            gcmWRITE_COUNTER(VPC_RATOTALQUADCOUNT, gcmCOUNTERCOMPARE(ra_total_quad_count));
            gcmWRITE_COUNTER(VPC_RAVALIDQUADCOUNTEZ, gcmCOUNTERCOMPARE(ra_valid_quad_count_after_early_z));
            gcmWRITE_COUNTER(VPC_RATOTALPRIMCOUNT, gcmCOUNTERCOMPARE(ra_total_primitive_count));
            gcmWRITE_COUNTER(VPC_RAPIPECACHEMISSCOUNT, gcmCOUNTERCOMPARE(ra_pipe_cache_miss_counter));
            gcmWRITE_COUNTER(VPC_RAPREFCACHEMISSCOUNT, gcmCOUNTERCOMPARE(ra_prefetch_cache_miss_counter));
            gcmWRITE_COUNTER(VPC_RAEEZCULLCOUNT, gcmCOUNTERCOMPARE(ra_eez_culled_counter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_TX);
            gcmWRITE_COUNTER(VPC_TXTOTBILINEARREQ, gcmCOUNTERCOMPARE(tx_total_bilinear_requests));
            gcmWRITE_COUNTER(VPC_TXTOTTRILINEARREQ, gcmCOUNTERCOMPARE(tx_total_trilinear_requests));
            gcmWRITE_COUNTER(VPC_TXTOTTEXREQ, gcmCOUNTERCOMPARE(tx_total_texture_requests));
            gcmWRITE_COUNTER(VPC_TXMEMREADCOUNT, gcmCOUNTERCOMPARE(tx_mem_read_count));
            gcmWRITE_COUNTER(VPC_TXMEMREADIN8BCOUNT, gcmCOUNTERCOMPARE(tx_mem_read_in_8B_count));
            gcmWRITE_COUNTER(VPC_TXCACHEMISSCOUNT, gcmCOUNTERCOMPARE(tx_cache_miss_count));
            gcmWRITE_COUNTER(VPC_TXCACHEHITTEXELCOUNT, gcmCOUNTERCOMPARE(tx_cache_hit_texel_count));
            gcmWRITE_COUNTER(VPC_TXCACHEMISSTEXELCOUNT, gcmCOUNTERCOMPARE(tx_cache_miss_texel_count));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_PS);
            gcmWRITE_COUNTER(VPC_PSINSTCOUNT, gcmCOUNTERCOMPARE(ps_inst_counter));
            gcmWRITE_COUNTER(VPC_PSBRANCHINSTCOUNT, gcmCOUNTERCOMPARE(pxl_branch_inst_counter));
            gcmWRITE_COUNTER(VPC_PSTEXLDINSTCOUNT, gcmCOUNTERCOMPARE(pxl_texld_inst_counter));
       	gcmWRITE_COUNTER(VPC_PSRENDEREDPIXCOUNT, gcmCOUNTERCOMPARE(rendered_pixel_counter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_PE);
            gcmWRITE_COUNTER(VPC_PEKILLEDBYCOLOR, gcmCOUNTERCOMPARE(pe_pixel_count_killed_by_color_pipe));
            gcmWRITE_COUNTER(VPC_PEKILLEDBYDEPTH, gcmCOUNTERCOMPARE(pe_pixel_count_killed_by_depth_pipe));
            gcmWRITE_COUNTER(VPC_PEDRAWNBYCOLOR, gcmCOUNTERCOMPARE(pe_pixel_count_drawn_by_color_pipe));
            gcmWRITE_COUNTER(VPC_PEDRAWNBYDEPTH, gcmCOUNTERCOMPARE(pe_pixel_count_drawn_by_depth_pipe));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_MC);
            gcmWRITE_COUNTER(VPC_MCREADREQ8BPIPE, gcmCOUNTERCOMPARE(mc_total_read_req_8B_from_pipeline));
            gcmWRITE_COUNTER(VPC_MCREADREQ8BIP, gcmCOUNTERCOMPARE(mc_total_read_req_8B_from_IP));
            gcmWRITE_COUNTER(VPC_MCWRITEREQ8BPIPE, gcmCOUNTERCOMPARE(mc_total_write_req_8B_from_pipeline));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_AXI);
            gcmWRITE_COUNTER(VPC_AXIREADREQSTALLED, gcmCOUNTERCOMPARE(hi_axi_cycles_read_request_stalled));
            gcmWRITE_COUNTER(VPC_AXIWRITEREQSTALLED, gcmCOUNTERCOMPARE(hi_axi_cycles_write_request_stalled));
            gcmWRITE_COUNTER(VPC_AXIWRITEDATASTALLED, gcmCOUNTERCOMPARE(hi_axi_cycles_write_data_stalled));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_END);
            gcoOS_MemCopy(&precounters,&iface.u.RegisterProfileData.counters,gcmSIZEOF(precounters));
#else
		    gcmWRITE_STRING("<HWCounters>\n");

	        gcmPRINT_XML("<read_64Byte value=\"%u\"/>\n",
    	    			 gcmCOUNTER(gpuTotalRead64BytesPerFrame));
        	gcmPRINT_XML("<write_64Byte value=\"%u\"/>\n",
	        			 gcmCOUNTER(gpuTotalWrite64BytesPerFrame));
	        gcmPRINT_XML("<gpu_cycles value=\"%u\"/>\n",
    	    			 gcmCOUNTER(gpuCyclesCounter));
        	gcmPRINT_XML("<pe_pixel_count_killed_by_color_pipe value=\"%u\"/>\n",
        				 gcmCOUNTER(pe_pixel_count_killed_by_color_pipe));
	        gcmPRINT_XML("<pe_pixel_count_killed_by_depth_pipe value=\"%u\"/>\n",
    	    			 gcmCOUNTER(pe_pixel_count_killed_by_depth_pipe));
        	gcmPRINT_XML("<pe_pixel_count_drawn_by_color_pipe value=\"%u\"/>\n",
						 gcmCOUNTER(pe_pixel_count_drawn_by_color_pipe));
	        gcmPRINT_XML("<pe_pixel_count_drawn_by_depth_pipe value=\"%u\"/>\n",
						 gcmCOUNTER(pe_pixel_count_drawn_by_depth_pipe));
        	gcmPRINT_XML("<ps_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(ps_inst_counter));
	        gcmPRINT_XML("<rendered_pixel_counter value=\"%u\"/>\n",
						 gcmCOUNTER(rendered_pixel_counter));
        	gcmPRINT_XML("<vs_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(vs_inst_counter));
	        gcmPRINT_XML("<rendered_vertice_counter value=\"%u\"/>\n",
						 gcmCOUNTER(rendered_vertice_counter));
        	gcmPRINT_XML("<vtx_branch_inst_counter value=\"%u\"/>\n",
					 gcmCOUNTER(vtx_branch_inst_counter));
	        gcmPRINT_XML("<vtx_texld_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(vtx_texld_inst_counter));
        	gcmPRINT_XML("<pxl_branch_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pxl_branch_inst_counter));
	        gcmPRINT_XML("<pxl_texld_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pxl_texld_inst_counter));
        	gcmPRINT_XML("<pa_input_vtx_counter value=\"%u\"/>\n",
					 gcmCOUNTER(pa_input_vtx_counter));
	        gcmPRINT_XML("<pa_input_prim_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pa_input_prim_counter));
        	gcmPRINT_XML("<pa_output_prim_counter value=\"%u\"/>\n",
					 gcmCOUNTER(pa_output_prim_counter));
	        gcmPRINT_XML("<pa_depth_clipped_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pa_depth_clipped_counter));
        	gcmPRINT_XML("<pa_trivial_rejected_counter value=\"%u\"/>\n",
					 gcmCOUNTER(pa_trivial_rejected_counter));
	        gcmPRINT_XML("<pa_culled_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pa_culled_counter));
        	gcmPRINT_XML("<se_culled_triangle_count value=\"%u\"/>\n",
						 gcmCOUNTER(se_culled_triangle_count));
	        gcmPRINT_XML("<se_culled_lines_count value=\"%u\"/>\n",
						 gcmCOUNTER(se_culled_lines_count));
        	gcmPRINT_XML("<ra_valid_pixel_count value=\"%u\"/>\n",
					 gcmCOUNTER(ra_valid_pixel_count));
	        gcmPRINT_XML("<ra_total_quad_count value=\"%u\"/>\n",
						 gcmCOUNTER(ra_total_quad_count));
        	gcmPRINT_XML("<ra_valid_quad_count_after_early_z value=\"%u\"/>\n",
					 gcmCOUNTER(ra_valid_quad_count_after_early_z));
	        gcmPRINT_XML("<ra_total_primitive_count value=\"%u\"/>\n",
						 gcmCOUNTER(ra_total_primitive_count));
        	gcmPRINT_XML("<ra_pipe_cache_miss_counter value=\"%u\"/>\n",
						 gcmCOUNTER(ra_pipe_cache_miss_counter));
	        gcmPRINT_XML("<ra_prefetch_cache_miss_counter value=\"%u\"/>\n",
						 gcmCOUNTER(ra_prefetch_cache_miss_counter));
        	gcmPRINT_XML("<ra_eez_culled_counter value=\"%u\"/>\n",
					 gcmCOUNTER(ra_eez_culled_counter));
	        gcmPRINT_XML("<tx_total_bilinear_requests value=\"%u\"/>\n",
						 gcmCOUNTER(tx_total_bilinear_requests));
        	gcmPRINT_XML("<tx_total_trilinear_requests value=\"%u\"/>\n",
					 gcmCOUNTER(tx_total_trilinear_requests));
	        gcmPRINT_XML("<tx_total_discarded_texture_requests value=\"%u\"/>\n",
						 gcmCOUNTER(tx_total_discarded_texture_requests));
        	gcmPRINT_XML("<tx_total_texture_requests value=\"%u\"/>\n",
						 gcmCOUNTER(tx_total_texture_requests));
    	    gcmPRINT_XML("<tx_mem_read_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_mem_read_count));
	        gcmPRINT_XML("<tx_mem_read_in_8B_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_mem_read_in_8B_count));
        	gcmPRINT_XML("<tx_cache_miss_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_cache_miss_count));
    	    gcmPRINT_XML("<tx_cache_hit_texel_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_cache_hit_texel_count));
	        gcmPRINT_XML("<tx_cache_miss_texel_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_cache_miss_texel_count));
        	gcmPRINT_XML("<mc_total_read_req_8B_from_pipeline value=\"%u\"/>\n",
						 gcmCOUNTER(mc_total_read_req_8B_from_pipeline));
    	    gcmPRINT_XML("<mc_total_read_req_8B_from_IP value=\"%u\"/>\n",
						 gcmCOUNTER(mc_total_read_req_8B_from_IP));
	        gcmPRINT_XML("<mc_total_write_req_8B_from_pipeline value=\"%u\"/>\n",
						 gcmCOUNTER(mc_total_write_req_8B_from_pipeline));
	        gcmPRINT_XML("<hi_axi_cycles_read_request_stalled value=\"%u\"/>\n",
						 gcmCOUNTER(hi_axi_cycles_read_request_stalled));
	        gcmPRINT_XML("<hi_axi_cycles_write_request_stalled value=\"%u\"/>\n",
						 gcmCOUNTER(hi_axi_cycles_write_request_stalled));
        	gcmPRINT_XML("<hi_axi_cycles_write_data_stalled value=\"%u\"/>\n",
						 gcmCOUNTER(hi_axi_cycles_write_data_stalled));

	    	gcmWRITE_STRING("</HWCounters>\n");
#endif
		}
	}
/*#endif*/

	/* Success. */
    gcmFOOTER_NO();
    return gcvSTATUS_OK;
}
/**
 *
 * @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);
}
gceSTATUS
_StretchBlitPE1x(
    IN gcsCOPYBIT_CONTEXT * Context,
    IN struct copybit_image_t const  * Dest,
    IN struct copybit_image_t const  * Source,
    IN struct copybit_rect_t const   * DestRect,
    IN struct copybit_rect_t const   * SourceRect,
    IN struct copybit_region_t const * Clip)
{
    gceSTATUS status = gcvSTATUS_OK;

    gceSURF_FORMAT siFormat;
    gceSURF_FORMAT diFormat;

    gctUINT32      diPhysical = ~0;
    gctUINT32      diAlignedWidth;
    gctUINT32      diAlignedHeight;
    gctINT         diStride;

    gcsRECT srcRect;
    gcsRECT dstRect;
    copybit_rect_t rect;

    gctUINT32      srcPhysical = ~0;
    gctINT         srcStride;
    gctUINT32      srcAlignedWidth;
    gctUINT32      srcAlignedHeight;
    gceSURF_FORMAT srcFormat;

    gctUINT32      dstPhysical = ~0;
    gctINT         dstStride;
    gctUINT32      dstAlignedWidth;
    gctUINT32      dstAlignedHeight;
    gceSURF_FORMAT dstFormat;

    gctBOOL stretch   = gcvFALSE;
    gctBOOL yuvFormat = gcvFALSE;
    gctBOOL perpixelAlpha;

    gc_private_handle_t* dsthnd = (gc_private_handle_t *) Dest->handle;
    gc_private_handle_t* srchnd = (gc_private_handle_t *) Source->handle;

    LOGV("Blit from Source hnd=%p, to Dest hnd=%p", srchnd, dsthnd);

    if (gc_private_handle_t::validate(dsthnd) < 0)
    {
        gcmTRACE(gcvLEVEL_ERROR,
                 "Invalid hnd in funciton %s",
                 __func__);

        return gcvSTATUS_INVALID_ARGUMENT;
    }

    siFormat = (gceSURF_FORMAT) srchnd->format;
    diFormat = (gceSURF_FORMAT) dsthnd->format;

    if ((siFormat == gcvSURF_UNKNOWN)
    ||  (diFormat == gcvSURF_UNKNOWN)
    )
    {
        gcmTRACE(gcvLEVEL_ERROR,
                 "Image format not support in copybit!");

        return gcvSTATUS_INVALID_ARGUMENT;
    }

    /* Convert to supported Source format. */
    siFormat = (siFormat == gcvSURF_A8B8G8R8) ? gcvSURF_A8R8G8B8 : siFormat;
    siFormat = (siFormat == gcvSURF_X8B8G8R8) ? gcvSURF_X8R8G8B8 : siFormat;

    /* Convert to supported Dest format. */
    diFormat = (diFormat == gcvSURF_A8B8G8R8) ? gcvSURF_A8R8G8B8 : diFormat;
    diFormat = (diFormat == gcvSURF_X8B8G8R8) ? gcvSURF_X8R8G8B8 : diFormat;

    do
    {
        srcPhysical = srchnd->phys;
        gcoSURF_GetAlignedSize((gcoSURF) srchnd->surface,
                               &srcAlignedWidth,
                               &srcAlignedHeight,
                               &srcStride);

        diPhysical = dsthnd->phys;
        gcoSURF_GetAlignedSize((gcoSURF) dsthnd->surface,
                               &diAlignedWidth,
                               &diAlignedHeight,
                               &diStride);

        if  ((((gcoSURF)srchnd->surface)->info.type == gcvSURF_BITMAP) &&
            !(srchnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER))
        {
            /* Clean the CPU cache. Source would've been rendered by the CPU. */
            gcmERR_BREAK(
                gcoSURF_CPUCacheOperation(
                            (gcoSURF) srchnd->surface,
                            gcvCACHE_CLEAN
                            )
            );
        }

        perpixelAlpha = _HasAlpha(siFormat) &&
                 (dsthnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
                 !(srchnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER);

        if (Context->perpixelAlpha != perpixelAlpha)
        {
            Context->perpixelAlpha = perpixelAlpha;

            if (Context->planeAlpha == 0xff)
            {
                Context->dirty.s.alphaKey = 1;
            }
        }

        /* Need temp surface if source has alpha channel, but dest not. */
        Context->needAlphaDest = Context->perpixelAlpha &&
                !_HasAlpha(diFormat);

        if (Context->needAlphaDest)
        {
            gcsRECT tempRect;

            tempRect.left   = gcmMAX(0, DestRect->l);
            tempRect.top    = gcmMAX(0, DestRect->t);
            tempRect.right  = gcmMIN((int32_t) Dest->w, DestRect->r);
            tempRect.bottom = gcmMIN((int32_t) Dest->h, DestRect->b);

            gcmERR_BREAK(
                _FitSurface(Context,
                            &Context->alphaDest,
                            Dest->w,
                            Dest->h));

            if (Context->alphaDest.surface == gcvNULL)
            {
                gcmTRACE(gcvLEVEL_ERROR,
                         "fail to construct tmp surface for per_pixel_alpha");

                break;
            }

            /* Copy dest surface to temp surface. */
            gcmERR_BREAK(
                _MonoBlit(Context,
                          diPhysical,
                          diStride,
                          diFormat,
                          Context->alphaDest.physical,
                          Context->alphaDest.stride,
                          Context->alphaDest.format,
                          &tempRect));
        }

        gcmERR_BREAK(
            _UploadStates(Context));

        if (Context->needAlphaDest)
        {
            dstPhysical      = Context->alphaDest.physical;
            dstStride        = Context->alphaDest.stride;
            dstAlignedWidth  = Context->alphaDest.alignedWidth;
            dstAlignedHeight = Context->alphaDest.alignedHeight;
            dstFormat        = Context->alphaDest.format;
        }
        else
        {
            dstPhysical      = diPhysical;
            dstStride        = diStride;
            dstAlignedWidth  = diAlignedWidth;
            dstAlignedHeight = diAlignedHeight;
            dstFormat        = diFormat;
        }

        srcFormat = siFormat;

        if (Context->transform == COPYBIT_TRANSFORM_ROT_270)
        {
            srcRect.left   = SourceRect->t;
            srcRect.top    = Source->w - SourceRect->r;
            srcRect.right  = SourceRect->b;
            srcRect.bottom = Source->w - SourceRect->l;
        }
        else
        {
            srcRect.left   = SourceRect->l;
            srcRect.top    = SourceRect->t;
            srcRect.right  = SourceRect->r;
            srcRect.bottom = SourceRect->b;
        }

        if (Context->transform ==  COPYBIT_TRANSFORM_ROT_90)
        {
            dstRect.left   = DestRect->t;
            dstRect.top    = Dest->w - DestRect->r;
            dstRect.right  = DestRect->b;
            dstRect.bottom = Dest->w - DestRect->l;
        }
        else
        {
            dstRect.left   = DestRect->l;
            dstRect.top    = DestRect->t;
            dstRect.right  = DestRect->r;
            dstRect.bottom = DestRect->b;
        }

        /* Check yuv format. */
        yuvFormat = (srcFormat == gcvSURF_YUY2 || srcFormat == gcvSURF_UYVY);

        stretch =
            (srcRect.right - srcRect.left) != (dstRect.right - dstRect.left) ||
            (srcRect.bottom - srcRect.top) != (dstRect.bottom - dstRect.top);

        /* Upload stretch factor. */
        if (stretch)
        {
            int hFactor;
            int vFactor;

            if ((dstRect.right-dstRect.left) > 1 && (dstRect.bottom-dstRect.top) > 1)
            {
                hFactor = ((srcRect.right - srcRect.left - 1) << 16) /
                        (dstRect.right - dstRect.left - 1);

                vFactor = ((srcRect.bottom - srcRect.top - 1) << 16) /
                        (dstRect.bottom - dstRect.top - 1);
            }
            else
            {
                hFactor = 0;
                vFactor = 0;
            }

            gcmERR_BREAK(
                gco2D_SetStretchFactors(Context->engine,
                                        hFactor,
                                        vFactor));
        }

        /* Prepare source and target for normal blit. */
        gcmERR_BREAK(
            gco2D_SetColorSource(Context->engine,
                                 srcPhysical,
                                 srcStride,
                                 srcFormat,
                                 Context->srcRotation,
                                 srcAlignedWidth,
                                 gcvFALSE,
                                 gcvSURF_OPAQUE,
                                 0));

        gcmERR_BREAK(
            gco2D_SetSource(Context->engine,
                            &srcRect));

        gcmERR_BREAK(
            gco2D_SetTarget(Context->engine,
                            dstPhysical,
                            dstStride,
                            Context->dstRotation,
                            dstAlignedWidth));

        gcsRECT srcRectBackup = srcRect;
        gcsRECT dstRectBackup = dstRect;

        /* Go though all clip rectangles. */
        while (Clip->next(Clip, &rect))
        {
            gcsRECT clipRect;

            srcRect = srcRectBackup;
            dstRect = dstRectBackup;

            if (Context->transform ==  COPYBIT_TRANSFORM_ROT_90)
            {
                clipRect.left   = rect.t;
                clipRect.top    = Dest->w - rect.r;
                clipRect.right  = rect.b;
                clipRect.bottom = Dest->w - rect.l;
            }
            else if (Context->transform == COPYBIT_TRANSFORM_ROT_180)
            {
                float hfactor = (float) (SourceRect->r - SourceRect->l)
                                 / (DestRect->r - DestRect->l);

                float vfactor = (float) (SourceRect->b - SourceRect->t)
                                 / (DestRect->b - DestRect->t);

                /* Intersect. */
                clipRect.left   = gcmMAX(dstRect.left, rect.l);
                clipRect.top    = gcmMAX(dstRect.top, rect.t);
                clipRect.right  = gcmMIN(dstRect.right, rect.r);
                clipRect.bottom = gcmMIN(dstRect.bottom, rect.b);

                /* Adjust src rectangle. */
                srcRect.left   += (int) ((dstRect.right - clipRect.right) * hfactor);
                srcRect.top    += (int) ((dstRect.bottom - clipRect.bottom) * vfactor);
                srcRect.right  -= (int) ((clipRect.left - dstRect.left) * hfactor);
                srcRect.bottom -= (int) ((clipRect.top - dstRect.top) * vfactor);

                /* Set dstRect to clip rectangle. */
                dstRect = clipRect;

                if ((srcRect.left   != srcRectBackup.left)
                ||  (srcRect.right  != srcRectBackup.right)
                ||  (srcRect.top    != srcRectBackup.top)
                ||  (srcRect.bottom != srcRectBackup.bottom)
                )
                {
                    gcmERR_BREAK(
                        gco2D_SetSource(Context->engine,
                                        &srcRect));
                }
            }
            else
            {
                clipRect.left   = rect.l;
                clipRect.top    = rect.t;
                clipRect.right  = rect.r;
                clipRect.bottom = rect.b;
            }

            /* Clamp clip rectangle. */
            if (clipRect.right > dstRect.right)
                clipRect.right = dstRect.right;

            if (clipRect.bottom > dstRect.bottom)
                clipRect.bottom = dstRect.bottom;

            if (clipRect.left < dstRect.left)
                clipRect.left = dstRect.left;

            if (clipRect.top < dstRect.top)
                clipRect.top = dstRect.top;

            gcmERR_BREAK(
                gco2D_SetClipping(Context->engine,
                                  &clipRect));

            if (yuvFormat)
            {
                /* TODO: FilterBlit does not support rotation before PE20. */
                /* Video filter blit */
                /* 1. SetClipping() has no effect for FilterBlit()
                 *    so we use dstSubRect to realize clipping effect
                 * 2. Only FilterBlit support yuv format covertion.
                 */
                gcsRECT dstSubRect;
                int dstWidth   = dstRect.right   - dstRect.left;
                int dstHeight  = dstRect.bottom  - dstRect.top;
                int clipWidth  = clipRect.right  - clipRect.left;
                int clipHeight = clipRect.bottom - clipRect.top;

                dstSubRect.left   = clipRect.left - dstRect.left;
                dstSubRect.top    = clipRect.top - dstRect.top;
                dstSubRect.right  = dstWidth < clipWidth ?
                        dstSubRect.left + dstWidth :
                        dstSubRect.left + clipWidth;
                dstSubRect.bottom = dstHeight < clipHeight ?
                        dstSubRect.top  + dstHeight :
                        dstSubRect.top  + clipHeight;

                gcmERR_BREAK(
                    gco2D_SetKernelSize(Context->engine,
                                        gcdFILTER_BLOCK_SIZE,
                                        gcdFILTER_BLOCK_SIZE));

                gcmERR_BREAK(
                    gco2D_SetFilterType(Context->engine,
                                        gcvFILTER_SYNC));

                gcmERR_BREAK(
                    gco2D_FilterBlit(Context->engine,
                                     srcPhysical,
                                     srcStride,
                                     0, 0, 0, 0,
                                     srcFormat,
                                     Context->srcRotation,
                                     srcAlignedWidth,
                                     &srcRect,
                                     dstPhysical,
                                     dstStride,
                                     dstFormat,
                                     Context->dstRotation,
                                     dstAlignedWidth,
                                     &dstRect,
                                     &dstSubRect));
            }
            else if (Context->blur)
            {
                /* TODO: FilterBlit does not support rotation before PE20. */
                gcsRECT dstSubRect;
                dstSubRect.left  = 0;
                dstSubRect.top   = 0;
                dstSubRect.right = dstRect.right - dstRect.left;
                dstSubRect.bottom = dstRect.bottom - dstRect.top;

                /* Blur blit. */
                gcmERR_BREAK(
                    gco2D_SetKernelSize(Context->engine,
                                        gcdFILTER_BLOCK_SIZE,
                                        gcdFILTER_BLOCK_SIZE));

                gcmERR_BREAK(
                    gco2D_SetFilterType(Context->engine,
                                        gcvFILTER_BLUR));

                gcmERR_BREAK(
                    gco2D_FilterBlit(Context->engine,
                                     srcPhysical,
                                     srcStride,
                                     0, 0, 0, 0,
                                     srcFormat,
                                     gcvSURF_0_DEGREE,
                                     srcAlignedWidth,
                                     &srcRect,
                                     dstPhysical,
                                     dstStride,
                                     dstFormat,
                                     gcvSURF_0_DEGREE,
                                     dstAlignedWidth,
                                     &dstRect,
                                     &dstSubRect));

                gcmERR_BREAK(
                    gco2D_FilterBlit(Context->engine,
                                     dstPhysical,
                                     dstStride,
                                     0, 0, 0, 0,
                                     dstFormat,
                                     gcvSURF_0_DEGREE,
                                     dstAlignedWidth,
                                     &dstRect,
                                     dstPhysical,
                                     dstStride,
                                     dstFormat,
                                     gcvSURF_0_DEGREE,
                                     dstAlignedWidth,
                                     &dstRect,
                                     &dstSubRect));

                /* TODO: surfaceflinger set blur issue. */
                Context->blur = COPYBIT_DISABLE;
            }
            else if (stretch == gcvFALSE)
            {
                /* BitBlit. */
                gcmERR_BREAK(
                    gco2D_Blit(Context->engine,
                               1,
                               &dstRect,
                               0xCC,
                               0xCC,
                               dstFormat));
            }
            else
            {
                /* Normal stretch blit. */
                gcmERR_BREAK(
                    gco2D_StretchBlit(Context->engine,
                                      1,
                                      &dstRect,
                                      0xCC,
                                      0xCC,
                                      dstFormat));
            }
        }

        if (gcmIS_ERROR(status))
        {
            break;
        }

        if (Context->needAlphaDest)
        {
            gcsRECT tempRect;

            tempRect.left   = gcmMAX(0, DestRect->l);
            tempRect.top    = gcmMAX(0, DestRect->t);
            tempRect.right  = gcmMIN((int32_t) Dest->w, DestRect->r);
            tempRect.bottom = gcmMIN((int32_t) Dest->h, DestRect->b);

            /* Blit back to actual dest. */
            gcmERR_BREAK(
                _MonoBlit(Context,
                          Context->alphaDest.physical,
                          Context->alphaDest.stride,
                          Context->alphaDest.format,
                          diPhysical,
                          diStride,
                          diFormat,
                          &tempRect));
        }

        /* Flush and commit. */
        gcmERR_BREAK(
            gco2D_Flush(Context->engine));

        gcmERR_BREAK(
            gcoHAL_Commit(gcvNULL, gcvFALSE));
    }
    while (gcvFALSE);

    return status;
}