fbs/fontandbitmapserver/sfbs/BackGroundCompression.CPP
changeset 0 5d03bc08d59c
--- /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;
+	}