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