/*!
 * Memory copy using HW engines. 
 * The table below describes the supported copy modes that 
 * reference by the data input/output buffers: 
 *  
 *  ----------------------------------------------
 *  |  DataIn_ptr  |         DataOut_ptr         |
 *  |--------------------------------------------|
 *  | SRAM         | DCACHE/SRAM/DLLI/MLLI       |
 *  | ICACHE       | DCACHE/SRAM/DLLI/MLLI       |
 *  | DCACHE       | DCACHE/SRAM/DLLI/MLLI       |
 *  | DLLI         | DCACHE/SRAM/DLLI            |
 *  | MLLI         | DCACHE/SRAM/MLLI            |
 *  ----------------------------------------------
 *   
 * \param DataIn_ptr This is the source buffer which need to copy from. 
 *      	It may be a SeP local address or a DMA Object handle as described
 *      	in the table above. 
 * \param DataSize In bytes
 * \param DataOut_ptr This is the destination buffer which need to copy to. 
 *      	It may be a SeP local address or a DMA Object handle as described
 *      	in the table above.
 *  
 * Restriction: MLLI refers to DMA oject in System memory space.
 * 
 * \return CRYSError_t On success CRYS_OK is returned, on failure an error according to
 *                       CRYS_Bypass_error.h
 */
CIMPORT_C CRYSError_t CRYS_Bypass(DxUint8_t*     DataIn_ptr,        
				  DxUint32_t     DataSize,         
				  DxUint8_t*     DataOut_ptr)
{
	/* The return error identifiers */
	CRYSError_t Error = CRYS_OK;
	int symRc = DX_RET_OK;
	

	DxUint32_t ctxBuff[CRYS_BYPASS_BUFF_OF_WORDS] = {0x0};
	/* pointer on SEP AES context struct*/
	struct sep_ctx_generic *pSepContext = (struct sep_ctx_generic *)DX_InitUserCtxLocation(ctxBuff,
								      sizeof(ctxBuff),
								      sizeof(struct sep_ctx_generic));
	
	/* data size must be a positive number and a block size mult */
	if (DataSize == 0 )
		return DX_SUCCESS;
	
	/* if the users Data In pointer is illegal return an error */
	if ( DataIn_ptr == DX_NULL )
		return CRYS_BYPASS_INVALID_INPUT_POINTER_ERROR;
	
	/* if the users Data Out pointer is illegal return an error */
	if ( DataOut_ptr == DX_NULL )
		return CRYS_BYPASS_INVALID_OUTPUT_POINTER_ERROR;
	
	Error = validateParams(DataIn_ptr, DataSize);
	if ( Error != CRYS_OK ) {
		return Error;
	}
	
	Error = validateParams(DataOut_ptr, DataSize);
	if ( Error != CRYS_OK ) {
		return Error;
	}
	
	pSepContext->alg = SEP_CRYPTO_ALG_BYPASS;
	symRc = SymDriverAdaptorProcess(pSepContext,DataIn_ptr, DataOut_ptr, DataSize);

	return DX_CRYS_RETURN_ERROR(symRc, 0, SymAdaptor2CrysBypassErr);
}
// generate and save a bitmap for use by ATLC
int EdgeCoupledEmbeddedMicrostrip2B1AWindow::drawBitmap()
{
	if(!validateParams())
		return -1;

	double boardHeight = params["H1"]->value() + params["H2"]->value() + params["H3"]->value() + params["T1"]->value() * 2;
	double tlineWidth = fmax(params["W1"]->value(), params["W2"]->value()) + params["S1"]->value();
	calcScale(boardHeight, tlineWidth);

	int substrate1HeightPix = scale_factor * params["H1"]->value();
	int substrate2HeightPix = scale_factor * params["H2"]->value();
	int substrate3HeightPix = scale_factor * params["H3"]->value();
	int traceThicknessPix = scale_factor * params["T1"]->value();
	int traceSeparationPix = scale_factor * params["S1"]->value();
	int lowerTraceWidthPix = scale_factor * params["W1"]->value();
	int upperTraceWidthPix = scale_factor * params["W2"]->value();
	
	// create the BMP that ATLC will use
	MakeBitmap bmp(width, height);

	// bottom copper (arbitrary thickness)
	bmp.drawRect(0, 0, width, traceThicknessPix, COLOR_COPPER_GND);

	// laminate
	bmp.drawRect(0, traceThicknessPix, width, substrate1HeightPix, COLOR_LAM1);
	bmp.drawRect(0, traceThicknessPix+substrate1HeightPix, width, substrate2HeightPix, COLOR_LAM2);
	bmp.drawRect(0, traceThicknessPix+substrate1HeightPix+substrate2HeightPix, width, substrate3HeightPix, COLOR_LAM3);

	// microstrip copper above second laminate
	bmp.drawTrapezoid(	(width - 2*lowerTraceWidthPix - traceSeparationPix)/2,
				traceThicknessPix+substrate1HeightPix+substrate2HeightPix,
				lowerTraceWidthPix, 
				upperTraceWidthPix,
				traceThicknessPix,
				COLOR_COPPER_POS);

	bmp.drawTrapezoid(	(width - 2*lowerTraceWidthPix - traceSeparationPix)/2 + traceSeparationPix + lowerTraceWidthPix,
				traceThicknessPix+substrate1HeightPix+substrate2HeightPix,
				lowerTraceWidthPix, 
				upperTraceWidthPix,
				traceThicknessPix,
				COLOR_COPPER_NEG);

	// draw enclosing boundary
	bmp.drawRectOutline(0, 0, width-1, height-1, 1, COLOR_COPPER_GND);

	// save bitmap file
	atlc->setEr(COLOR_LAM1, params["Er1"]->value());
	atlc->setEr(COLOR_LAM2, params["Er2"]->value());
	atlc->setEr(COLOR_LAM3, params["Er3"]->value());
	bmp.save(atlc->simBitmap());
	return 0;
}
bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list) {

    sCopyBitDraw = false;

    int compositionType =
        qdutils::QCCompositionType::getInstance().getCompositionType();

    if ((compositionType == qdutils::COMPOSITION_TYPE_GPU) ||
        (compositionType == qdutils::COMPOSITION_TYPE_CPU))   {
        //GPU/CPU composition, don't change layer composition type
        return true;
    }

    if(!(validateParams(ctx, list))) {
       ALOGE("%s:Invalid Params", __FUNCTION__);
       return false;
    }

    if(sIsSkipLayerPresent) {
        //GPU will be anyways used
        return false;
    }

    bool useCopybitForYUV = canUseCopybitForYUV(ctx);
    bool useCopybitForRGB = canUseCopybitForRGB(ctx, list);

    for (int i=list->numHwLayers-1; i >= 0 ; i--) {
        private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;

        if (hnd->bufferType == BUFFER_TYPE_VIDEO) {
          //YUV layer, check, if copybit can be used
          // mark the video layer to gpu when all layer is
          // going to gpu in case of dynamic composition.
          if (useCopybitForYUV && useCopybitForRGB) {
              list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
              sCopyBitDraw = true;
          }
       } else if (hnd->bufferType == BUFFER_TYPE_UI) {
          //RGB layer, check, if copybit can be used
          if (useCopybitForRGB) {
              list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
              sCopyBitDraw = true;
          }
       }
    }
    return true;
}
bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list) {

    int compositionType =
        qdutils::QCCompositionType::getInstance().getCompositionType();

    if ((compositionType & qdutils::COMPOSITION_TYPE_GPU) ||
        (compositionType & qdutils::COMPOSITION_TYPE_CPU))   {
        //GPU/CPU composition, don't change layer composition type
        return true;
    }

    bool useCopybitForYUV = canUseCopybitForYUV(ctx);
    bool useCopybitForRGB = canUseCopybitForRGB(ctx, list);

    if(!(validateParams(ctx, list))) {
       ALOGE("%s:Invalid Params", __FUNCTION__);
       return false;
    }
    sCopyBitDraw = false;
    for (int i=list->numHwLayers-1; i >= 0 ; i--) {
        private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;

        if (isSkipLayer(&list->hwLayers[i])) {
            return true;
        } else if (hnd->bufferType == BUFFER_TYPE_VIDEO) {
          //YUV layer, check, if copybit can be used
          if (useCopybitForYUV) {
              list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
              sCopyBitDraw = true;
          }
       } else if (hnd->bufferType == BUFFER_TYPE_UI) {
          //RGB layer, check, if copybit can be used
          if (useCopybitForRGB) {
              list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
              sCopyBitDraw = true;
          }
       }
    }
    return true;
}
bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list, int dpy) {

    if(mEngine == NULL) {
        // No copybit device found - cannot use copybit
        return false;
    }
    int compositionType = qdutils::QCCompositionType::
                                    getInstance().getCompositionType();

    if ((compositionType == qdutils::COMPOSITION_TYPE_GPU) ||
        (compositionType == qdutils::COMPOSITION_TYPE_CPU))   {
        //GPU/CPU composition, don't change layer composition type
        return true;
    }

    if(!(validateParams(ctx, list))) {
        ALOGE("%s:Invalid Params", __FUNCTION__);
        return false;
    }

    if(ctx->listStats[dpy].skipCount) {
        //GPU will be anyways used
        return false;
    }
    
    if (ctx->listStats[dpy].numAppLayers > MAX_NUM_LAYERS) {
        // Reached max layers supported by HWC.
        return false;
    }
    
    if (!ctx->mFBUpdate[dpy]->isUsed())
        return false;

    bool useCopybitForYUV = canUseCopybitForYUV(ctx);
    bool useCopybitForRGB = canUseCopybitForRGB(ctx, list, dpy);
    LayerProp *layerProp = ctx->layerProp[dpy];
    size_t fbLayerIndex = ctx->listStats[dpy].fbLayerIndex;
    hwc_layer_1_t *fbLayer = &list->hwLayers[fbLayerIndex];
    private_handle_t *fbHnd = (private_handle_t *)fbLayer->handle;

    //Allocate render buffers if they're not allocated
    if (useCopybitForYUV || useCopybitForRGB) {
        int ret = allocRenderBuffers(fbHnd->width,
                                     fbHnd->height,
                                     fbHnd->format);
        if (ret < 0) {
            return false;
        }
    }

    int i;
    if (useCopybitForYUV) {
        for (i = 0; i < ctx->listStats[dpy].numAppLayers; i++) {
            if (list->hwLayers[i].compositionType == HWC_FRAMEBUFFER) {
                private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
                if (hnd->bufferType == BUFFER_TYPE_VIDEO) {
                    layerProp[i].mFlags |= HWC_COPYBIT;
                    list->hwLayers[i].compositionType = HWC_OVERLAY;
                    list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB;
                    mCopyBitDraw = true;
                }
            }
        }
    }
    if (useCopybitForRGB || mCopyBitDraw) {
        for (i = 0; i < ctx->listStats[dpy].numAppLayers; i++) {
            if (list->hwLayers[i].compositionType == HWC_FRAMEBUFFER) {
                private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
                if (hnd->bufferType == BUFFER_TYPE_UI) {
                    layerProp[i].mFlags |= HWC_COPYBIT;
                    list->hwLayers[i].compositionType = HWC_OVERLAY;
                    list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB;
                    mCopyBitDraw = true;
                }
            }
        }
    }
    
    if (mCopyBitDraw) {
        mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) % NUM_RENDER_BUFFERS;
    }
    
    return true;
}
bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
                                                            int dpy) {

    if(mEngine == NULL) {
        // No copybit device found - cannot use copybit
        return false;
    }
    int compositionType = qdutils::QCCompositionType::
                                    getInstance().getCompositionType();

    if ((compositionType == qdutils::COMPOSITION_TYPE_GPU) ||
        (compositionType == qdutils::COMPOSITION_TYPE_CPU))   {
        //GPU/CPU composition, don't change layer composition type
        return true;
    }

    if(!(validateParams(ctx, list))) {
        ALOGE("%s:Invalid Params", __FUNCTION__);
        return false;
    }

    if(ctx->listStats[dpy].skipCount) {
        //GPU will be anyways used
        return false;
    }

    if (ctx->listStats[dpy].numAppLayers > MAX_NUM_LAYERS) {
        // Reached max layers supported by HWC.
        return false;
    }

    bool useCopybitForYUV = canUseCopybitForYUV(ctx);
    bool useCopybitForRGB = canUseCopybitForRGB(ctx, list, dpy);
    LayerProp *layerProp = ctx->layerProp[dpy];
    size_t fbLayerIndex = ctx->listStats[dpy].fbLayerIndex;
    hwc_layer_1_t *fbLayer = &list->hwLayers[fbLayerIndex];
    private_handle_t *fbHnd = (private_handle_t *)fbLayer->handle;



    //Allocate render buffers if they're not allocated
    if (useCopybitForYUV || useCopybitForRGB) {
        int ret = allocRenderBuffers(fbHnd->width,
                                     fbHnd->height,
                                     fbHnd->format);
        if (ret < 0) {
            return false;
        } else {
            mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) %
                NUM_RENDER_BUFFERS;
        }
    }


    // numAppLayers-1, as we iterate till 0th layer index
    for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
        private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;

        if ((hnd->bufferType == BUFFER_TYPE_VIDEO && useCopybitForYUV) ||
            (hnd->bufferType == BUFFER_TYPE_UI && useCopybitForRGB)) {
            layerProp[i].mFlags |= HWC_COPYBIT;
            list->hwLayers[i].compositionType = HWC_OVERLAY;
            mCopyBitDraw = true;
        } else {
            // We currently cannot mix copybit layers with layers marked to
            // be drawn on the framebuffer or that are on the layer cache.
            mCopyBitDraw = false;
            //There is no need to reset layer properties here as we return in
            //draw if mCopyBitDraw is false
        }
    }
    return true;
}