os/graphics/fbs/fontandbitmapserver/sfbs/BackGroundCompression.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "SERVER.H"
    17 #include "BackGroundCompression.h"
    18 
    19 _LIT(KFbsBgCompThrdName, "FbsBgCompressThread");
    20 const TInt KFbsBgCompThrdStackSize = 4096;
    21 
    22 
    23 CFbsBackgroundCompressionQueueElement::CFbsBackgroundCompressionQueueElement(CBitmapObject* aSrcObj, TBitmapfileCompressionScheme aScheme):
    24 	iSourceObject(aSrcObj),
    25 	iCompressionScheme(aScheme)
    26 	{
    27 	__ASSERT_DEBUG(aSrcObj->iCompressionQueueElement == NULL, User::Invariant());
    28 	aSrcObj->iCompressionQueueElement = this;
    29 	}
    30 
    31 CFbsBackgroundCompressionQueueElement::~CFbsBackgroundCompressionQueueElement()
    32 	{
    33 	iLink.Deque();
    34 	iSourceObject->iCompressionQueueElement = NULL;
    35 	if (!iMessage.IsNull())
    36 		iMessage.Complete(KErrNone);
    37 	}
    38 
    39 void CFbsBackgroundCompressionQueueElement::CompleteOutstandingRequestAndDestroy(TInt aReason)
    40 	{
    41 	if (!iMessage.IsNull())
    42 		iMessage.Complete(aReason);
    43 	delete this;
    44 	}
    45 
    46 void CFbsBackgroundCompressionQueueElement::CompleteOutstandingRequest(const CSession2* aSession)
    47 	{
    48 	if (!iMessage.IsNull() && iMessage.Session() == aSession)
    49 		iMessage.Complete(KErrDisconnected);
    50 	}
    51 
    52 
    53 CFbsBackgroundCompression* CFbsBackgroundCompression::NewL(CFbTop& aFbTop)
    54 	{
    55 	CFbsBackgroundCompression* self = new(ELeave) CFbsBackgroundCompression(aFbTop);
    56 	CleanupStack::PushL(self);
    57 	self->ConstructL();
    58 	CleanupStack::Pop(self);
    59 	return self;
    60 	}
    61 
    62 CFbsBackgroundCompression::CFbsBackgroundCompression(CFbTop& aFbTop):
    63 	CActive(CActive::EPriorityIdle),
    64 	iFbTop(aFbTop),
    65 	iCompressionQueue(_FOFF(CFbsBackgroundCompressionQueueElement, iLink))
    66 	{
    67 	CActiveScheduler::Add(this);
    68 	}
    69 
    70 void CFbsBackgroundCompression::ConstructL()
    71 	{
    72 	TThreadCreateInfo threadCreateInfo(KFbsBgCompThrdName, (TThreadFunction)ThreadFunction, KFbsBgCompThrdStackSize, this);
    73 	threadCreateInfo.SetUseHeap(NULL);
    74 	threadCreateInfo.SetOwner(EOwnerProcess);
    75 	threadCreateInfo.SetPaging(TThreadCreateInfo::EUnspecified); //Use the creating process's paging attributes.
    76 	User::LeaveIfError(iThread.Create(threadCreateInfo));
    77 	iThreadCreated = ETrue;
    78 	iThread.SetPriority(EPriorityAbsoluteVeryLow);
    79 	User::LeaveIfError(iThreadGo.CreateLocal(0));
    80 	User::LeaveIfError(iThreadMutex.CreateLocal());
    81 	iThread.Resume();
    82 	}
    83 
    84 CFbsBackgroundCompression::~CFbsBackgroundCompression()
    85 	{
    86 	// destructor should be called only after all sessions with the server have been closed
    87 	// so there should not be any bitmap objects left
    88 	__ASSERT_DEBUG(iCompressionQueue.IsEmpty(), User::Invariant());
    89 	__ASSERT_DEBUG(iBitmapObject == NULL, User::Invariant());
    90 	if (iThreadCreated)
    91 		{
    92 		iThread.Kill(KErrNone);
    93 		iThread.Close();
    94 		iThreadGo.Close();
    95 		iThreadMutex.Close();
    96 		}
    97 	}
    98 
    99 TInt CFbsBackgroundCompression::AddToCompressionQueue(CBitmapObject* aSrcObj, TBitmapfileCompressionScheme aScheme, const RMessage2* aMessage)
   100 	{
   101 	__ASSERT_DEBUG(aSrcObj != NULL, User::Invariant());
   102 	CFbsBackgroundCompressionQueueElement* element = new CFbsBackgroundCompressionQueueElement(aSrcObj, aScheme);
   103 	if (element == NULL)
   104 		return KErrNoMemory;
   105 	iCompressionQueue.AddLast(*element);
   106 	if (!IsActive())
   107 		{
   108 		TInt ret = PrepareCompression();
   109 		if (ret != KErrNone)
   110 			{
   111 			delete element;
   112 			return ret;
   113 			}
   114 		SetActive();
   115 		iThread.Rendezvous(iStatus);
   116 		iThreadGo.Signal();
   117 		}
   118 
   119 	if (aMessage != NULL)
   120 		element->iMessage = *aMessage;
   121 
   122 	return KErrNone;
   123 	}
   124 
   125 void CFbsBackgroundCompression::RemoveFromCompressionQueue(CBitmapObject* aSrcObj)
   126 	{
   127 	__ASSERT_DEBUG(aSrcObj != NULL, User::Invariant());
   128 	CFbsBackgroundCompressionQueueElement* element = aSrcObj->iCompressionQueueElement;
   129 	if (element != NULL)
   130 		{
   131 		if (iBitmapObject != NULL && iCompressionQueue.IsFirst(element))
   132 			{
   133 			iThreadMutex.Wait();
   134 			iBitmapObject->Close();
   135 			iBitmapObject = NULL;
   136 			iThreadMutex.Signal();
   137 			}
   138 		delete element;
   139 		}
   140 	}
   141 
   142 void CFbsBackgroundCompression::CompleteOutstandingRequests(const CSession2* aSession)
   143 	{
   144 	TDblQueIter<CFbsBackgroundCompressionQueueElement> iterator(iCompressionQueue);
   145 	CFbsBackgroundCompressionQueueElement* element;
   146 	while ((element = iterator++) != NULL)
   147 		element->CompleteOutstandingRequest(aSession);
   148 	}
   149 
   150 void CFbsBackgroundCompression::CompressAll()
   151 	{
   152 	if (iBitmapObject != NULL) // check if a compression is in progress
   153 		{
   154 		User::WaitForRequest(iStatus);
   155 		FinalizeCompression(iStatus);
   156 		TRequestStatus* status = &iStatus;
   157 		User::RequestComplete(status, KErrCompletion);
   158 		}
   159 	while (!iCompressionQueue.IsEmpty())
   160 		{
   161 		TInt ret = PrepareCompression();
   162 		if (ret != KErrNone)
   163 			{
   164 			iCompressionQueue.First()->CompleteOutstandingRequestAndDestroy(ret);
   165 			continue;
   166 			}
   167 		TRequestStatus status;
   168 		iThread.Rendezvous(status);
   169 		iThreadGo.Signal();
   170 		User::WaitForRequest(status);
   171 		FinalizeCompression(status);
   172 		}
   173 	}
   174 
   175 TInt CFbsBackgroundCompression::PrepareCompression()
   176 	{
   177 	__ASSERT_DEBUG(!iCompressionQueue.IsEmpty(), User::Invariant());
   178 	__ASSERT_DEBUG(iBitmapObject == NULL, User::Invariant());
   179 	CFbsBackgroundCompressionQueueElement* element = iCompressionQueue.First();
   180 	CBitwiseBitmap* srcBmp = element->iSourceObject->Address();
   181 	CBitmapObject* bmpObj = NULL;
   182 	TRAPD(ret, bmpObj = iFbTop.CreateBitmapL(srcBmp->SizeInPixels(), srcBmp->DisplayMode(), KUidCFbsBitmapCreation, ETrue));
   183 	if (ret != KErrNone)
   184 		return ret;
   185 	ret = bmpObj->Address()->CopyData(*srcBmp);
   186 	if (ret != KErrNone)
   187 		{
   188 		bmpObj->Close();
   189 		return ret;
   190 		}
   191 	iThreadMutex.Wait();
   192 	iBitmapObject = bmpObj;
   193 	iCompressionScheme = element->iCompressionScheme;
   194 	iThreadMutex.Signal();
   195 	return KErrNone;
   196 	}
   197 
   198 void CFbsBackgroundCompression::FinalizeCompression(const TRequestStatus& aStatus)
   199 	{
   200 	__ASSERT_DEBUG(!iCompressionQueue.IsEmpty(), User::Invariant());
   201 	__ASSERT_DEBUG(iBitmapObject != NULL, User::Invariant());
   202 	iThreadMutex.Wait();
   203 	CFbsBackgroundCompressionQueueElement* element = iCompressionQueue.First();
   204 	if (aStatus == KErrNone)
   205 		{
   206 		element->iSourceObject->SetCleanBitmap(iBitmapObject);
   207 		iFbTop.NotifyDirtyBitmap(*element->iSourceObject, NULL);
   208 		}
   209 	else
   210 		{
   211 		iBitmapObject->Close();
   212 		}
   213 	iBitmapObject = NULL;
   214 	element->CompleteOutstandingRequestAndDestroy(aStatus.Int());
   215 	iThreadMutex.Signal();
   216 	}
   217 
   218 void CFbsBackgroundCompression::RunL()
   219 	{
   220 	// check if CompressAll() or RemoveFromCompressionQueue() have been called before
   221 	if (iBitmapObject != NULL)
   222 		{
   223 		FinalizeCompression(iStatus);
   224 		}
   225 	while (!iCompressionQueue.IsEmpty())
   226 		{
   227 		TInt ret = PrepareCompression();
   228 		if (ret == KErrNone)
   229 			{
   230 			SetActive();
   231 			iThread.Rendezvous(iStatus);
   232 			iThreadGo.Signal();
   233 			return;
   234 			}
   235 		iCompressionQueue.First()->CompleteOutstandingRequestAndDestroy(ret);
   236 		}
   237 	}
   238 
   239 void CFbsBackgroundCompression::DoCancel()
   240 	{
   241 	iThread.RendezvousCancel(iStatus);
   242 	}
   243 
   244 TInt CFbsBackgroundCompression::ThreadFunction(CFbsBackgroundCompression* aSelf)
   245 	{
   246 	TBool notDone = ETrue; // to suppress compiler warning
   247 	// coverity[dead_error_condition]
   248 	// coverity[loop_condition]
   249 	while (notDone)
   250 		{
   251 		aSelf->iThreadGo.Wait();
   252 		aSelf->iThreadMutex.Wait();
   253 		if (aSelf->iBitmapObject != NULL)
   254 			{
   255 			TInt ret = aSelf->iBitmapObject->Address()->CompressData(aSelf->iCompressionScheme);
   256 			RThread::Rendezvous(ret);
   257 			}
   258 		else
   259 			{
   260 			// bitmap removed from queue before background thread had a chance to compress it
   261 			RThread::Rendezvous(KErrAbort);
   262 			}
   263 		aSelf->iThreadMutex.Signal();
   264 		}
   265 	// coverity[dead_error_line]
   266 	return KErrNone;
   267 	}