|
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 } |