sl@0: // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "SERVER.H" sl@0: #include "BackGroundCompression.h" sl@0: sl@0: _LIT(KFbsBgCompThrdName, "FbsBgCompressThread"); sl@0: const TInt KFbsBgCompThrdStackSize = 4096; sl@0: sl@0: sl@0: CFbsBackgroundCompressionQueueElement::CFbsBackgroundCompressionQueueElement(CBitmapObject* aSrcObj, TBitmapfileCompressionScheme aScheme): sl@0: iSourceObject(aSrcObj), sl@0: iCompressionScheme(aScheme) sl@0: { sl@0: __ASSERT_DEBUG(aSrcObj->iCompressionQueueElement == NULL, User::Invariant()); sl@0: aSrcObj->iCompressionQueueElement = this; sl@0: } sl@0: sl@0: CFbsBackgroundCompressionQueueElement::~CFbsBackgroundCompressionQueueElement() sl@0: { sl@0: iLink.Deque(); sl@0: iSourceObject->iCompressionQueueElement = NULL; sl@0: if (!iMessage.IsNull()) sl@0: iMessage.Complete(KErrNone); sl@0: } sl@0: sl@0: void CFbsBackgroundCompressionQueueElement::CompleteOutstandingRequestAndDestroy(TInt aReason) sl@0: { sl@0: if (!iMessage.IsNull()) sl@0: iMessage.Complete(aReason); sl@0: delete this; sl@0: } sl@0: sl@0: void CFbsBackgroundCompressionQueueElement::CompleteOutstandingRequest(const CSession2* aSession) sl@0: { sl@0: if (!iMessage.IsNull() && iMessage.Session() == aSession) sl@0: iMessage.Complete(KErrDisconnected); sl@0: } sl@0: sl@0: sl@0: CFbsBackgroundCompression* CFbsBackgroundCompression::NewL(CFbTop& aFbTop) sl@0: { sl@0: CFbsBackgroundCompression* self = new(ELeave) CFbsBackgroundCompression(aFbTop); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CFbsBackgroundCompression::CFbsBackgroundCompression(CFbTop& aFbTop): sl@0: CActive(CActive::EPriorityIdle), sl@0: iFbTop(aFbTop), sl@0: iCompressionQueue(_FOFF(CFbsBackgroundCompressionQueueElement, iLink)) sl@0: { sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: void CFbsBackgroundCompression::ConstructL() sl@0: { sl@0: TThreadCreateInfo threadCreateInfo(KFbsBgCompThrdName, (TThreadFunction)ThreadFunction, KFbsBgCompThrdStackSize, this); sl@0: threadCreateInfo.SetUseHeap(NULL); sl@0: threadCreateInfo.SetOwner(EOwnerProcess); sl@0: threadCreateInfo.SetPaging(TThreadCreateInfo::EUnspecified); //Use the creating process's paging attributes. sl@0: User::LeaveIfError(iThread.Create(threadCreateInfo)); sl@0: iThreadCreated = ETrue; sl@0: iThread.SetPriority(EPriorityAbsoluteVeryLow); sl@0: User::LeaveIfError(iThreadGo.CreateLocal(0)); sl@0: User::LeaveIfError(iThreadMutex.CreateLocal()); sl@0: iThread.Resume(); sl@0: } sl@0: sl@0: CFbsBackgroundCompression::~CFbsBackgroundCompression() sl@0: { sl@0: // destructor should be called only after all sessions with the server have been closed sl@0: // so there should not be any bitmap objects left sl@0: __ASSERT_DEBUG(iCompressionQueue.IsEmpty(), User::Invariant()); sl@0: __ASSERT_DEBUG(iBitmapObject == NULL, User::Invariant()); sl@0: if (iThreadCreated) sl@0: { sl@0: iThread.Kill(KErrNone); sl@0: iThread.Close(); sl@0: iThreadGo.Close(); sl@0: iThreadMutex.Close(); sl@0: } sl@0: } sl@0: sl@0: TInt CFbsBackgroundCompression::AddToCompressionQueue(CBitmapObject* aSrcObj, TBitmapfileCompressionScheme aScheme, const RMessage2* aMessage) sl@0: { sl@0: __ASSERT_DEBUG(aSrcObj != NULL, User::Invariant()); sl@0: CFbsBackgroundCompressionQueueElement* element = new CFbsBackgroundCompressionQueueElement(aSrcObj, aScheme); sl@0: if (element == NULL) sl@0: return KErrNoMemory; sl@0: iCompressionQueue.AddLast(*element); sl@0: if (!IsActive()) sl@0: { sl@0: TInt ret = PrepareCompression(); sl@0: if (ret != KErrNone) sl@0: { sl@0: delete element; sl@0: return ret; sl@0: } sl@0: SetActive(); sl@0: iThread.Rendezvous(iStatus); sl@0: iThreadGo.Signal(); sl@0: } sl@0: sl@0: if (aMessage != NULL) sl@0: element->iMessage = *aMessage; sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CFbsBackgroundCompression::RemoveFromCompressionQueue(CBitmapObject* aSrcObj) sl@0: { sl@0: __ASSERT_DEBUG(aSrcObj != NULL, User::Invariant()); sl@0: CFbsBackgroundCompressionQueueElement* element = aSrcObj->iCompressionQueueElement; sl@0: if (element != NULL) sl@0: { sl@0: if (iBitmapObject != NULL && iCompressionQueue.IsFirst(element)) sl@0: { sl@0: iThreadMutex.Wait(); sl@0: iBitmapObject->Close(); sl@0: iBitmapObject = NULL; sl@0: iThreadMutex.Signal(); sl@0: } sl@0: delete element; sl@0: } sl@0: } sl@0: sl@0: void CFbsBackgroundCompression::CompleteOutstandingRequests(const CSession2* aSession) sl@0: { sl@0: TDblQueIter iterator(iCompressionQueue); sl@0: CFbsBackgroundCompressionQueueElement* element; sl@0: while ((element = iterator++) != NULL) sl@0: element->CompleteOutstandingRequest(aSession); sl@0: } sl@0: sl@0: void CFbsBackgroundCompression::CompressAll() sl@0: { sl@0: if (iBitmapObject != NULL) // check if a compression is in progress sl@0: { sl@0: User::WaitForRequest(iStatus); sl@0: FinalizeCompression(iStatus); sl@0: TRequestStatus* status = &iStatus; sl@0: User::RequestComplete(status, KErrCompletion); sl@0: } sl@0: while (!iCompressionQueue.IsEmpty()) sl@0: { sl@0: TInt ret = PrepareCompression(); sl@0: if (ret != KErrNone) sl@0: { sl@0: iCompressionQueue.First()->CompleteOutstandingRequestAndDestroy(ret); sl@0: continue; sl@0: } sl@0: TRequestStatus status; sl@0: iThread.Rendezvous(status); sl@0: iThreadGo.Signal(); sl@0: User::WaitForRequest(status); sl@0: FinalizeCompression(status); sl@0: } sl@0: } sl@0: sl@0: TInt CFbsBackgroundCompression::PrepareCompression() sl@0: { sl@0: __ASSERT_DEBUG(!iCompressionQueue.IsEmpty(), User::Invariant()); sl@0: __ASSERT_DEBUG(iBitmapObject == NULL, User::Invariant()); sl@0: CFbsBackgroundCompressionQueueElement* element = iCompressionQueue.First(); sl@0: CBitwiseBitmap* srcBmp = element->iSourceObject->Address(); sl@0: CBitmapObject* bmpObj = NULL; sl@0: TRAPD(ret, bmpObj = iFbTop.CreateBitmapL(srcBmp->SizeInPixels(), srcBmp->DisplayMode(), KUidCFbsBitmapCreation, ETrue)); sl@0: if (ret != KErrNone) sl@0: return ret; sl@0: ret = bmpObj->Address()->CopyData(*srcBmp); sl@0: if (ret != KErrNone) sl@0: { sl@0: bmpObj->Close(); sl@0: return ret; sl@0: } sl@0: iThreadMutex.Wait(); sl@0: iBitmapObject = bmpObj; sl@0: iCompressionScheme = element->iCompressionScheme; sl@0: iThreadMutex.Signal(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CFbsBackgroundCompression::FinalizeCompression(const TRequestStatus& aStatus) sl@0: { sl@0: __ASSERT_DEBUG(!iCompressionQueue.IsEmpty(), User::Invariant()); sl@0: __ASSERT_DEBUG(iBitmapObject != NULL, User::Invariant()); sl@0: iThreadMutex.Wait(); sl@0: CFbsBackgroundCompressionQueueElement* element = iCompressionQueue.First(); sl@0: if (aStatus == KErrNone) sl@0: { sl@0: element->iSourceObject->SetCleanBitmap(iBitmapObject); sl@0: iFbTop.NotifyDirtyBitmap(*element->iSourceObject, NULL); sl@0: } sl@0: else sl@0: { sl@0: iBitmapObject->Close(); sl@0: } sl@0: iBitmapObject = NULL; sl@0: element->CompleteOutstandingRequestAndDestroy(aStatus.Int()); sl@0: iThreadMutex.Signal(); sl@0: } sl@0: sl@0: void CFbsBackgroundCompression::RunL() sl@0: { sl@0: // check if CompressAll() or RemoveFromCompressionQueue() have been called before sl@0: if (iBitmapObject != NULL) sl@0: { sl@0: FinalizeCompression(iStatus); sl@0: } sl@0: while (!iCompressionQueue.IsEmpty()) sl@0: { sl@0: TInt ret = PrepareCompression(); sl@0: if (ret == KErrNone) sl@0: { sl@0: SetActive(); sl@0: iThread.Rendezvous(iStatus); sl@0: iThreadGo.Signal(); sl@0: return; sl@0: } sl@0: iCompressionQueue.First()->CompleteOutstandingRequestAndDestroy(ret); sl@0: } sl@0: } sl@0: sl@0: void CFbsBackgroundCompression::DoCancel() sl@0: { sl@0: iThread.RendezvousCancel(iStatus); sl@0: } sl@0: sl@0: TInt CFbsBackgroundCompression::ThreadFunction(CFbsBackgroundCompression* aSelf) sl@0: { sl@0: TBool notDone = ETrue; // to suppress compiler warning sl@0: // coverity[dead_error_condition] sl@0: // coverity[loop_condition] sl@0: while (notDone) sl@0: { sl@0: aSelf->iThreadGo.Wait(); sl@0: aSelf->iThreadMutex.Wait(); sl@0: if (aSelf->iBitmapObject != NULL) sl@0: { sl@0: TInt ret = aSelf->iBitmapObject->Address()->CompressData(aSelf->iCompressionScheme); sl@0: RThread::Rendezvous(ret); sl@0: } sl@0: else sl@0: { sl@0: // bitmap removed from queue before background thread had a chance to compress it sl@0: RThread::Rendezvous(KErrAbort); sl@0: } sl@0: aSelf->iThreadMutex.Signal(); sl@0: } sl@0: // coverity[dead_error_line] sl@0: return KErrNone; sl@0: }