fbs/fontandbitmapserver/sfbs/BackGroundCompression.CPP
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     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 	}