// ---------------------------------------------------------------------------
// CMMCScBkupReadDataTransferRequestBase::ProcessChunkOfDataL()
// 
// 
// ---------------------------------------------------------------------------
TBool CMMCScBkupReadDataTransferRequestBase::ProcessChunkOfDataL()
    {
    __ASSERT_ALWAYS( iCurrentIndex >= 0, User::Invariant() );

    TBool callAgain = EFalse;

    // Do we need to move to the next entry?
    TBool entryAvailable = ( iCurrentIndex < iEntries->Count() );
    if  ( entryAvailable )
        {
        // At least one more entry left to process.. but have we finished
        // the current entry? If we've read all the data, then the
        // answer is yes...
        const TMMCScBkupArchiveDriveAndVector& entry = (*iEntries)[ iCurrentIndex ];
        const TInt endOffset = entry.iVector.EndOffset();

#ifdef __MMCSCBKUPLOGGING_ENABLED__
		if ( ElementType() == EMMCScBkupOwnerDataTypeJavaData )
			{
			HBufC* hash = MMCScBkupSBEUtils::JavaHashFromGenericLC( DataOwner().Owner().Identifier() );
			__LOG6("CMMCScBkupReadDataTransferRequestBase::ProcessChunkOfDataL() - START - JavaHash: %S, ElementType: %S, offset: %8d, length: %8d, endOffset: %8d, drive: %c:", hash, &MMCScBkupLogger::DataType( ElementType() ), entry.iVector.Offset(), entry.iVector.Length(), endOffset, entry.iDrive + 'A' );
			CleanupStack::PopAndDestroy( hash );
			}
		else
			{
			__LOG6("CMMCScBkupReadDataTransferRequestBase::ProcessChunkOfDataL() - START - DO: 0x%08x, ElementType: %S, offset: %8d, length: %8d, endOffset: %8d, drive: %c:", DataOwner().SecureId().iId, &MMCScBkupLogger::DataType( ElementType() ), entry.iVector.Offset(), entry.iVector.Length(), endOffset, entry.iDrive + 'A' );
			}
#endif

        // Check bounds
        if  ( CurrentOffset() < 0 || CurrentOffset() > endOffset )
            {
            ASSERT( EFalse );
            User::Leave( KErrCorrupt );
            }
        //
        if  ( iCurrentOffset == endOffset )
            {
            // We're done with this entry - move to the next
            entryAvailable = PrepareForNextEntry();
            }
        }
    //
    if  ( entryAvailable )
        {
        // We need to read more archive data in order to transfer this
        // entry to the SBE
        callAgain = DoProcessChunkOfDataL();
        }
    else
        {
        // No more left to process - we're finished!
        SetState( EFinished );
        CompleteSelf();
        }
    //
    return callAgain;
    }
// ---------------------------------------------------------------------------
// CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL()
// 
// 
// ---------------------------------------------------------------------------
TBool CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL()
    {
    MMMCScBkupDriver& driver = Driver();
    const TInt startingOffset = CurrentOffset();
    const TInt finalOffset = CurrentReadInfo().EndOffset();

    // Calculate how much data is remaining
    const TInt amountOfDataStillToBeRead = finalOffset - startingOffset;

    __LOG4("CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL() - START - startingOffset: 0x%08x, finalOffset: 0x%08x, amountToBeRead: %8d, iFinishedSupplyingData: %d", 
        startingOffset, finalOffset, amountOfDataStillToBeRead, iFinishedSupplyingData);

    // Get a handle to the received data - but only if we don't already
    // have a handle to it! Calling this method resets whatever is already
    // in the transfer chunk - hence we must only call it once (at the beginning
    // of a multi-chunked transfer)
    if  ( iTransferChunkPointer == NULL )
        {
        iTransferChunkPointer = &driver.DrvSecureBackupClient().TransferDataAddressL();
        }

    // How much space is available?
    const TInt spaceAvailable = iTransferChunkPointer->MaxLength() - iTransferChunkPointer->Length();
    const TInt amountToRead = Min( spaceAvailable, Min( iReadChunkSize, amountOfDataStillToBeRead ) );
    __LOG2("CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL() - xfer space available: %8d, amountToRead: %8d", spaceAvailable, amountToRead);

    // Do the read
    ReadChunkL( *iTransferChunkPointer, amountToRead );

    // Was this the last time we needed to perform a read?
    const TBool lastReadFromArchive = ( CurrentOffset() == finalOffset );
    __LOG1("CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL() - read data okay - lastReadFromArchive: %d", lastReadFromArchive);

    // Check to see if the data sink chunk is full. If so then we need to let 
    // the SBE process what we've prepared so far, then we'll fill it with more 
    // data. 
    iFinishedSupplyingData = lastReadFromArchive;
    TBool moreToBeRead = !lastReadFromArchive;
    if  ( !iFinishedSupplyingData && iTransferChunkPointer->Length() == iTransferChunkPointer->MaxLength() )
        {
        // Also cope with the boundary condition that the sink is full
        // but we've also just given it the last byte anyway. In which case,
        // we don't need to request a repeat transfer. This is actually
        // all the data in one go.
        moreToBeRead = EFalse;
        }
    //
    __LOG1("CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL() - END - more to read: %d", moreToBeRead);
    return moreToBeRead;
    }
	bool initVertexArray()
	{
		glGenVertexArrays(vertex_format::MAX, &VertexArrayName[0]);
		glBindBuffer(GL_ARRAY_BUFFER, BufferName[buffer::VERTEX]);

		std::size_t CurrentOffset(0);
		glBindVertexArray(VertexArrayName[vertex_format::F32]);
		glVertexAttribPointer(semantic::attr::POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), BUFFER_OFFSET(CurrentOffset));
		glEnableVertexAttribArray(semantic::attr::POSITION);
		
		CurrentOffset += PositionSizeF32;
		glBindVertexArray(VertexArrayName[vertex_format::I8]);
		glVertexAttribPointer(semantic::attr::POSITION, 2, GL_BYTE, GL_FALSE, sizeof(glm::u8vec2), BUFFER_OFFSET(CurrentOffset));
		glEnableVertexAttribArray(semantic::attr::POSITION);

		CurrentOffset += PositionSizeI8;
		glBindVertexArray(VertexArrayName[vertex_format::I32]);
		glVertexAttribPointer(semantic::attr::POSITION, 2, GL_INT, GL_FALSE, sizeof(glm::i32vec2), BUFFER_OFFSET(CurrentOffset));
		glEnableVertexAttribArray(semantic::attr::POSITION);

		CurrentOffset += PositionSizeI32;
		glBindVertexArray(VertexArrayName[vertex_format::RGB10A2]);
		glVertexAttribPointer(semantic::attr::POSITION, 4, GL_INT_2_10_10_10_REV, GL_TRUE, sizeof(glm::uint), BUFFER_OFFSET(CurrentOffset));
		glEnableVertexAttribArray(semantic::attr::POSITION);

		CurrentOffset += PositionSizeRGB10A2;
		glBindVertexArray(VertexArrayName[vertex_format::F16]);
		glVertexAttribPointer(semantic::attr::POSITION, 2, GL_HALF_FLOAT, GL_FALSE, sizeof(glm::uint16) * 2, BUFFER_OFFSET(CurrentOffset));
		glEnableVertexAttribArray(semantic::attr::POSITION);

		CurrentOffset += PositionSizeRG11FB10F;
		glBindVertexArray(VertexArrayName[vertex_format::RG11B10F]);
		glVertexAttribPointer(semantic::attr::POSITION, 3, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FALSE, sizeof(glm::uint), BUFFER_OFFSET(CurrentOffset));
		glEnableVertexAttribArray(semantic::attr::POSITION);
		
		glBindVertexArray(0);
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		return this->checkError("initVertexArray");
	}