|
1 /* |
|
2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implementation of CHuiTextureManager, texture objects loading |
|
15 * and management. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 #include <eikenv.h> |
|
22 #include <eikappui.h> |
|
23 #include <eikapp.h> |
|
24 |
|
25 #include "uiacceltk/HuiTextureManager.h" // Class definition |
|
26 #include "uiacceltk/HuiTextureProcessor.h" |
|
27 #include "HuiRenderPlugin.h" |
|
28 #include "uiacceltk/HuiEnv.h" |
|
29 #include "uiacceltk/HuiTexture.h" |
|
30 #include "uiacceltk/HuiFont.h" |
|
31 #include "uiacceltk/HuiUtil.h" |
|
32 #include "uiacceltk/HuiPanic.h" |
|
33 #include "uiacceltk/HuiDisplay.h" |
|
34 #include "huitextureanimationstate.h" |
|
35 |
|
36 /** |
|
37 * Granularity of CHuiTextureManager::iAnimations and |
|
38 * CHuiTextureManager::iAnimatedTextureGroupItems arrays. |
|
39 */ |
|
40 const TInt KHuiAnimationsGranularity = 4; |
|
41 |
|
42 EXPORT_C MHuiBitmapProvider::~MHuiBitmapProvider() |
|
43 { |
|
44 } |
|
45 |
|
46 EXPORT_C CHuiTextureManager::CHuiTextureManager(CHuiEnv& aEnv) |
|
47 : CActive(EPriorityHigh), |
|
48 iEnv(aEnv), iState(EIdle), iReleaseState(ENormal), iFS(CHuiStatic::FsSession()), |
|
49 iAnimatedTextureGroupItems( KHuiAnimationsGranularity ), |
|
50 iAnimations( KHuiAnimationsGranularity ), |
|
51 iEnableTexMemCalculation( EFalse ) //Texture memory calculation is disabled by default |
|
52 {} |
|
53 |
|
54 |
|
55 EXPORT_C void CHuiTextureManager::BaseConstructL() |
|
56 { |
|
57 iEnv.SetTextureManager(*this); |
|
58 |
|
59 SetImagePathL(_L("")); |
|
60 |
|
61 // Create a small initial bitmaps for decoder output. |
|
62 iBitmap = new (ELeave) CFbsBitmap(); |
|
63 User::LeaveIfError( iBitmap->Create(TSize(4, 4), EColor64K) ); |
|
64 iMaskBitmap = new (ELeave) CFbsBitmap(); |
|
65 User::LeaveIfError( iMaskBitmap->Create(TSize(4, 4), EGray256) ); |
|
66 |
|
67 // Create blank texture |
|
68 iBlankTexture = CHuiStatic::Renderer().CreateTextureL(); |
|
69 iBlankTexture->SetImageFileNameL(_L("blank")); |
|
70 |
|
71 CActiveScheduler::Add(this); |
|
72 |
|
73 // Enabling logging will cause diagnostics and debugging messages to be |
|
74 // printed to a file. |
|
75 CHuiStatic::EnableLogging(EFalse); |
|
76 } |
|
77 |
|
78 |
|
79 EXPORT_C CHuiTextureManager::~CHuiTextureManager() |
|
80 { |
|
81 Cancel(); |
|
82 |
|
83 delete iAnimationWithoutGroup; |
|
84 iAnimatedTextureGroupItems.Close(); |
|
85 iAnimations.ResetAndDestroy(); |
|
86 iAnimations.Close(); |
|
87 |
|
88 // Delete the texture processor. |
|
89 delete iProcessor; |
|
90 |
|
91 // Clear any remaining entries in the load queue. |
|
92 for(TInt i = 0; i < iLoadQueue.Count(); ++i) |
|
93 { |
|
94 delete iLoadQueue[i].iDecoder; |
|
95 iLoadQueue[i].iDecoder = 0; |
|
96 } |
|
97 iLoadQueue.Reset(); |
|
98 |
|
99 delete iBlankTexture; |
|
100 |
|
101 // Remove all texture entries (from last to first -order) |
|
102 /*while (iTextures.Count()>0)*/ |
|
103 for(TInt i = iTextures.Count()-1; i >= 0; --i) |
|
104 { |
|
105 CTextureEntry * te = iTextures[i]; |
|
106 |
|
107 if (te->iTexture) |
|
108 { |
|
109 delete te->iTexture; |
|
110 } |
|
111 else |
|
112 { |
|
113 // This texture was defined but never loaded. |
|
114 HUI_DEBUG2(_L("CHuiTextureManager::~CHuiTextureManager() - Notice, texture id %i (\"%S\") was never loaded!"), te->iId, te->iFileName); |
|
115 } |
|
116 } |
|
117 |
|
118 iTextures.ResetAndDestroy(); |
|
119 iStateObservers.Close(); |
|
120 iLoadObservers.Close(); |
|
121 iAnimatedTextures.Close(); |
|
122 iTextureAutoSizeObservers.Close(); |
|
123 |
|
124 delete iBitmap; |
|
125 delete iMaskBitmap; |
|
126 delete iImagePath; |
|
127 } |
|
128 |
|
129 |
|
130 EXPORT_C CHuiEnv& CHuiTextureManager::Env() |
|
131 { |
|
132 return iEnv; |
|
133 } |
|
134 |
|
135 |
|
136 EXPORT_C CHuiTexture* CHuiTextureManager::Texture(TInt aId) |
|
137 { |
|
138 TInt index = CheckTexture(aId); |
|
139 if(index == -1) |
|
140 { |
|
141 HUI_DEBUG1(_L("CHuiTextureManager::Texture() - Texture id %i not found! Returning blank."), aId); |
|
142 // NOTE: there is a danger of editing the blank texture |
|
143 // instead of the real texture.. |
|
144 return &BlankTexture(); |
|
145 } |
|
146 CHuiTexture * texture = iTextures[index]->iTexture; |
|
147 if(texture) |
|
148 { |
|
149 return texture; |
|
150 } |
|
151 else |
|
152 { |
|
153 HUI_ASSERT(EFalse); // texture exists but is not loaded! (defined but not loaded) |
|
154 return &BlankTexture(); |
|
155 } |
|
156 } |
|
157 |
|
158 |
|
159 EXPORT_C const CHuiTexture* CHuiTextureManager::Texture(TInt aId) const |
|
160 { |
|
161 TInt id = CheckTexture(aId); |
|
162 if(id == -1) |
|
163 { |
|
164 return &BlankTexture(); |
|
165 } |
|
166 const CHuiTexture * texture = iTextures[id]->iTexture; |
|
167 if(texture) |
|
168 { |
|
169 return texture; |
|
170 } |
|
171 else |
|
172 { |
|
173 HUI_ASSERT(EFalse); // texture exists but is not loaded! (defined but not loaded) |
|
174 return &BlankTexture(); |
|
175 } |
|
176 } |
|
177 |
|
178 |
|
179 EXPORT_C CHuiTexture* CHuiTextureManager::TextureL(TInt aId) |
|
180 { |
|
181 // try to get the index for the texture id |
|
182 TInt index = CheckTexture(aId); |
|
183 if(index != -1) |
|
184 { |
|
185 // If the texture has content and a filename, we can do a load-on-demand. |
|
186 if(!iTextures[index]->iTexture->HasContent() && iTextures[index]->iFileName) |
|
187 { |
|
188 // we don't want to return textures without content |
|
189 // so load-on-demand |
|
190 |
|
191 // texture has an entry but the |
|
192 // actual texture object has not been loaded yet |
|
193 |
|
194 // we can load the texture if there's a filename |
|
195 // available for this id |
|
196 return &LoadTextureL(aId); |
|
197 } |
|
198 |
|
199 // texture found |
|
200 return iTextures[index]->iTexture; |
|
201 } |
|
202 |
|
203 User::Leave(KErrNotFound); |
|
204 return NULL; // never |
|
205 } |
|
206 |
|
207 |
|
208 EXPORT_C void CHuiTextureManager::SetImagePathL(const TDesC& aPath) |
|
209 { |
|
210 delete iImagePath; |
|
211 iImagePath = NULL; |
|
212 |
|
213 TParsePtrC parse(aPath); |
|
214 CEikonEnv* coe = CEikonEnv::Static(); |
|
215 if (aPath.Length() && !parse.DrivePresent() && coe && coe->EikAppUi() && coe->EikAppUi()->Application()) |
|
216 { |
|
217 iImagePath = HBufC::NewL(aPath.Size()+2); // two extra characters for drive |
|
218 TPtr ptr = iImagePath->Des(); |
|
219 ptr.Append(coe->EikAppUi()->Application()->AppFullName().Left(2)); |
|
220 ptr.Append(aPath); |
|
221 } |
|
222 else |
|
223 { |
|
224 iImagePath = aPath.AllocL(); |
|
225 } |
|
226 } |
|
227 |
|
228 EXPORT_C const TDesC& CHuiTextureManager::ImagePath() const |
|
229 { |
|
230 return *iImagePath; |
|
231 } |
|
232 |
|
233 |
|
234 EXPORT_C const CHuiTexture& CHuiTextureManager::BlankTexture() const |
|
235 { |
|
236 HUI_ASSERT(iBlankTexture!=NULL); // this MUST have a valid pointer otherwise access violation will follow.. |
|
237 return *iBlankTexture; |
|
238 } |
|
239 |
|
240 |
|
241 EXPORT_C CHuiTexture& CHuiTextureManager::BlankTexture() |
|
242 { |
|
243 HUI_ASSERT(iBlankTexture!=NULL); // this MUST have a valid pointer otherwise access violation will follow.. |
|
244 return *iBlankTexture; |
|
245 } |
|
246 |
|
247 |
|
248 EXPORT_C TBool CHuiTextureManager::SetTextureId(CHuiTexture* aTexture, TInt aId) |
|
249 { |
|
250 |
|
251 if(!aTexture) |
|
252 { |
|
253 // Cannot set texture ID for null texture. |
|
254 return EFalse; |
|
255 } |
|
256 |
|
257 // Iterate through all the managed textures to find the one we |
|
258 // are interested in, and then set its texture ID. |
|
259 for(TInt i = 0; i < iTextures.Count(); ++i) |
|
260 { |
|
261 if(iTextures[i]->iTexture == aTexture) |
|
262 { |
|
263 // Texture was found in the list, so set the new identifier. |
|
264 iTextures[i]->iId = aId; |
|
265 return ETrue; |
|
266 } |
|
267 } |
|
268 |
|
269 // Texture was not found in the manager's list. |
|
270 return EFalse; |
|
271 } |
|
272 |
|
273 EXPORT_C TBool CHuiTextureManager::IsLoaded(const CHuiTexture * texture) const |
|
274 { |
|
275 if(texture != NULL && texture->HasContent() && !IsInLoadQueue(texture)) |
|
276 { |
|
277 return ETrue; |
|
278 } |
|
279 return EFalse; |
|
280 } |
|
281 |
|
282 |
|
283 EXPORT_C TBool CHuiTextureManager::IsLoaded(const TDesC& aImageName, const TInt aFrameNumber) const |
|
284 { |
|
285 TFileName fileName = *iImagePath; |
|
286 fileName.Append(aImageName); |
|
287 TInt index = CheckTexture(fileName, aFrameNumber); |
|
288 if(index < 0) |
|
289 { |
|
290 HUI_DEBUG1(_L("CHuiTextureManager::IsLoaded() - Texture \"%S\" was not found. Assuming not loaded."), &aImageName); |
|
291 return EFalse; |
|
292 } |
|
293 return IsLoaded(iTextures[index]->iTexture); |
|
294 } |
|
295 |
|
296 |
|
297 EXPORT_C TBool CHuiTextureManager::IsLoaded(TInt aId) const |
|
298 { |
|
299 HUI_ASSERT(aId!=0); |
|
300 TInt index = CheckTexture(aId); |
|
301 if(index < 0) |
|
302 { |
|
303 HUI_DEBUG1(_L("CHuiTextureManager::IsLoaded() - Texture having id %i was not found. Assuming not loaded."), aId); |
|
304 return EFalse; |
|
305 } |
|
306 return IsLoaded(iTextures[index]->iTexture); |
|
307 } |
|
308 |
|
309 |
|
310 EXPORT_C void CHuiTextureManager::AppendTextureL(CHuiTexture* aTexture, TInt aId) |
|
311 { |
|
312 // Panic if the manager is currently restoring or releasing textures. |
|
313 if(iReleaseState == EReleasing) |
|
314 { |
|
315 THuiPanic::Panic(THuiPanic::ETextureManagerTextureDestroyedDuringRelease); |
|
316 } |
|
317 else if(iReleaseState == ERestoring) |
|
318 { |
|
319 THuiPanic::Panic(THuiPanic::ETextureManagerTextureConstructedDuringRestore); |
|
320 } |
|
321 else |
|
322 { |
|
323 // for PC lint |
|
324 } |
|
325 |
|
326 HUI_ASSERT(aTexture != NULL); |
|
327 |
|
328 #ifdef _DEBUG |
|
329 // Look for an existing entry for this. |
|
330 // There must not be any duplicates present! |
|
331 for(TInt i = 0; i < iTextures.Count(); ++i) |
|
332 { |
|
333 if(iTextures[i]->iTexture == aTexture) |
|
334 { |
|
335 User::Leave(KErrAlreadyExists); |
|
336 } |
|
337 } |
|
338 #endif |
|
339 |
|
340 // Create a new texture entry |
|
341 CTextureEntry * te = new (ELeave) CTextureEntry(aId, aTexture); |
|
342 CleanupStack::PushL(te); |
|
343 // Add the new entry to the list of new textures |
|
344 User::LeaveIfError( iTextures.Append(te) ); |
|
345 CleanupStack::Pop(); // pop the texture entry |
|
346 |
|
347 HUI_DEBUG1(_L("CHuiTextureManager::AppendTextureL() - Registered texture 0x%x."), aTexture); |
|
348 } |
|
349 |
|
350 |
|
351 EXPORT_C void CHuiTextureManager::RemoveTexture(CHuiTexture& aTexture) |
|
352 { |
|
353 // Panic if the manager is currently restoring or releasing textures. |
|
354 if(iReleaseState == EReleasing) |
|
355 { |
|
356 THuiPanic::Panic(THuiPanic::ETextureManagerTextureDestroyedDuringRelease); |
|
357 } |
|
358 else if(iReleaseState == ERestoring) |
|
359 { |
|
360 THuiPanic::Panic(THuiPanic::ETextureManagerTextureDestroyedDuringRestore); |
|
361 } |
|
362 else |
|
363 { |
|
364 // for PC lint |
|
365 } |
|
366 |
|
367 // Cancel loading of the texture to be removed. |
|
368 CancelLoadingOfTexture(aTexture); |
|
369 |
|
370 // Manual sequential search. |
|
371 for(TInt index = iTextures.Count() - 1; index >= 0; --index) |
|
372 { |
|
373 if(iTextures[index]->iTexture == &aTexture) |
|
374 { |
|
375 CTextureEntry * entry = iTextures[index]; |
|
376 if ( entry->iFileName ) |
|
377 { |
|
378 HUI_DEBUG4(_L("CHuiTextureManager::RemoveTexture() - Removing texture 0x%x (Name: \"%S\", Id: %i). Number of textures after deleting: %i."), |
|
379 &aTexture, &(aTexture.ImageFileName()), entry->iId, iTextures.Count()-1); |
|
380 } |
|
381 else |
|
382 { |
|
383 HUI_DEBUG3(_L("CHuiTextureManager::RemoveTexture() - Removing unnamed texture 0x%x ( Id: %i). Number of textures after deleting: %i."), |
|
384 &aTexture, entry->iId, iTextures.Count()-1); |
|
385 } |
|
386 |
|
387 iTextures.Remove(index); |
|
388 delete entry; |
|
389 return; |
|
390 } |
|
391 } |
|
392 |
|
393 HUI_DEBUG2(_L("CHuiTextureManager::RemoveTexture() - Error! Failed to remove texture 0x%x \"%S\". Texture not found."), &aTexture, &aTexture.ImageFileName()); |
|
394 // this is a programming error.. texturemanager is aware of all textures in the toolkit!! |
|
395 #ifdef _DEBUG |
|
396 HUI_PANIC(THuiPanic::ETextureNotValid) |
|
397 #endif |
|
398 } |
|
399 |
|
400 |
|
401 EXPORT_C CHuiTexture& CHuiTextureManager::LoadTextureL( |
|
402 const TDesC& aImageName, |
|
403 THuiTextureUploadFlags aFlags, |
|
404 TInt aId, |
|
405 TInt aFrameNumber) |
|
406 { |
|
407 return LoadTextureL(aImageName, TSize(0, 0), aFlags, aId, aFrameNumber); |
|
408 } |
|
409 |
|
410 |
|
411 EXPORT_C CHuiTexture& CHuiTextureManager::LoadTextureL(const TInt aId, |
|
412 const TSize& aTextureMaxSize, |
|
413 THuiTextureUploadFlags aFlags) |
|
414 { |
|
415 return LoadTextureL(KNullDesC(), aTextureMaxSize, aFlags, aId); |
|
416 } |
|
417 |
|
418 |
|
419 EXPORT_C CHuiTexture& CHuiTextureManager::LoadTextureL(const TDesC& aImageName, |
|
420 const TSize& aTextureMaxSize, |
|
421 THuiTextureUploadFlags aFlags, |
|
422 TInt aId, |
|
423 TInt aFrameNumber) |
|
424 { |
|
425 // Ignore EHuiTextureFlagAllowDirectBitmapUsage flag |
|
426 aFlags = (THuiTextureUploadFlags)(aFlags & ~EHuiTextureFlagAllowDirectBitmapUsage); |
|
427 |
|
428 TFileName fileName; |
|
429 |
|
430 CTextureEntry * entry = NULL; |
|
431 |
|
432 // If the name is invalid, and there was no filename available |
|
433 // based on id, return a dummy texture. |
|
434 if((aImageName.Length() == 0) && (aId == 0)) |
|
435 { |
|
436 HUI_DEBUG(_L("CHuiTextureManager::LoadTextureL() - No filename or id provided for texture. Returning blank.")); |
|
437 return BlankTexture(); |
|
438 } |
|
439 |
|
440 // add path to filename if filename has been passed |
|
441 if(aImageName.Length() > 0) |
|
442 { |
|
443 // assume relative pathname and prepend the image path to get full filename |
|
444 fileName = aImageName; |
|
445 PrependImagePath(fileName); |
|
446 } |
|
447 |
|
448 // if no name has been passed as a parameter but |
|
449 // a nonzero id has been passed, we |
|
450 // can assume that there's a predefined name available |
|
451 if((aImageName.Length() == 0) && (aId != 0)) |
|
452 { |
|
453 // search for a texture filename based on the id. |
|
454 TInt index = CheckTexture(aId); |
|
455 if(index >=0) |
|
456 { |
|
457 entry = iTextures[index]; |
|
458 HUI_ASSERT(entry->iFileName); |
|
459 fileName = *(entry->iFileName); |
|
460 } |
|
461 else |
|
462 { |
|
463 HUI_DEBUG1(_L("CHuiTextureManager::LoadTextureL() - Unable to load texture without filename or pre-defined id (filename definition for id %i not found)."), aId); |
|
464 User::Leave(KErrNotFound); |
|
465 } |
|
466 } |
|
467 |
|
468 // a guarantee that there's a filename available |
|
469 HUI_ASSERT( fileName.Length()>0 ); |
|
470 |
|
471 // Reuse pre-existing entries: |
|
472 // try first finding an entry based on id |
|
473 if(entry == NULL && aId != 0) |
|
474 { |
|
475 TInt previouslyLoadedIndex = CheckTexture(aId); |
|
476 if (previouslyLoadedIndex >= 0) |
|
477 { |
|
478 entry = iTextures[previouslyLoadedIndex]; |
|
479 } |
|
480 } |
|
481 |
|
482 // We are not allowed to change required texture id so we can't |
|
483 // try again with the filename unless user does not care about id |
|
484 if(aId == 0 && entry == NULL) |
|
485 { |
|
486 TInt previouslyLoadedIndex = CheckTexture(fileName, aFrameNumber); |
|
487 if (previouslyLoadedIndex >= 0) |
|
488 { |
|
489 entry = iTextures[previouslyLoadedIndex]; |
|
490 } |
|
491 } |
|
492 |
|
493 // create new texture entry if there's not one |
|
494 // available at this point |
|
495 if(entry == NULL) |
|
496 { |
|
497 HUI_DEBUG(_L("CHuiTextureManager::LoadTextureL() - Creating new texture.")); |
|
498 |
|
499 // in the case that a previously loaded slot was not found, |
|
500 // create a new texture, which automatically registers a new |
|
501 // texture entry in the iTextures list. |
|
502 CHuiTexture::NewL(); |
|
503 |
|
504 // we assume that the newest entry was added the last |
|
505 entry = iTextures[iTextures.Count()-1]; |
|
506 |
|
507 entry->iId = aId; |
|
508 } |
|
509 else |
|
510 { |
|
511 // We have a valid texture name and ID. |
|
512 HUI_ASSERT(entry->iTexture); |
|
513 |
|
514 // we have a pre-existing texture, |
|
515 // but check that the texture is loaded ok, we can also |
|
516 // return unloaded textures that are in the load queue |
|
517 if (entry->iTexture->HasContent() || IsInLoadQueue(entry->iTexture)) |
|
518 { |
|
519 // a previous texture exists! |
|
520 HUI_ASSERT(entry->iTexture!=NULL); |
|
521 |
|
522 HUI_DEBUG3(_L("CHuiTextureManager::LoadTextureL() - Reusing texture 0x%x (\"%S\", id: %i) No need to load."), |
|
523 entry->iTexture, &entry->iTexture->ImageFileName(), entry->iId); |
|
524 return *(entry->iTexture); |
|
525 } |
|
526 } |
|
527 |
|
528 HUI_ASSERT(entry!=NULL); |
|
529 HUI_ASSERT(entry->iTexture!=NULL); |
|
530 |
|
531 // replace filename |
|
532 // File names are relative to the image path. |
|
533 entry->SetFileName(fileName); |
|
534 entry->iTexture->SetImageFileNameL(fileName); |
|
535 entry->iTexture->EnableShadow((aFlags & EHuiTextureUploadFlagGenerateShadow) != 0); |
|
536 entry->iFrameNumber = aFrameNumber; |
|
537 |
|
538 // add a content observer so that we can reload the texture |
|
539 // during restoring |
|
540 if (entry->iTexture->iContentObservers.Count()==0) |
|
541 { |
|
542 HUI_DEBUG2(_L("CHuiTextureManager::LoadTextureL() - Adding content observer 0x%x for texture 0x%x."), entry, entry->iTexture); |
|
543 entry->iTexture->iContentObservers.AppendL(*entry); |
|
544 } |
|
545 |
|
546 HUI_DEBUG3(_L("CHuiTextureManager::LoadTextureL() - Enqueuing texture 0x%x (Name: \"%S\", Id: %i)."), |
|
547 entry->iTexture, &entry->iTexture->ImageFileName(), entry->iId); |
|
548 |
|
549 // Prepare for loading by creating a load queue entry. |
|
550 SLoadQueueEntry loadqentry; |
|
551 Mem::FillZ(&loadqentry, sizeof(loadqentry)); |
|
552 loadqentry.iLoading = entry; |
|
553 entry->iMaxTextureSize = aTextureMaxSize; |
|
554 entry->iFlags = aFlags; |
|
555 |
|
556 // Textures are loaded one at a time, in the order they were requested. |
|
557 User::LeaveIfError( iLoadQueue.Append(loadqentry) ); |
|
558 |
|
559 // Start loading images. |
|
560 if(iState == EIdle) |
|
561 { |
|
562 StartLoading(); |
|
563 |
|
564 if(iState == ELoading) |
|
565 { |
|
566 // Notify observers that loading has started. |
|
567 NotifyStateChange(); |
|
568 } |
|
569 } |
|
570 |
|
571 return *entry->iTexture; |
|
572 } |
|
573 |
|
574 EXPORT_C CHuiTexture& |
|
575 CHuiTextureManager::CreateTextureL(TInt aId, |
|
576 MHuiBitmapProvider* aBitmapProvider, |
|
577 THuiTextureUploadFlags aFlags) |
|
578 { |
|
579 CHuiTexture* tex; |
|
580 |
|
581 // can't create texture without id (or filename) |
|
582 if (aId==0) |
|
583 { |
|
584 HUI_DEBUG(_L("CHuiTextureManager::CreateTextureL() - ERROR! Can't create texture without valid id. Please use nonzero ids.")); |
|
585 User::Leave(KErrArgument); |
|
586 } |
|
587 |
|
588 // Provide an already created texture if such exists. |
|
589 CHuiTexture* texture = NULL; |
|
590 TRAPD(err, texture = TextureL(aId)); |
|
591 if(err == KErrNone) |
|
592 { |
|
593 ASSERT( texture ); |
|
594 |
|
595 // Update flags here because there is no other way to change flags. |
|
596 CTextureEntry* entry = TextureEntry(CheckTexture(aId)); |
|
597 if (entry) |
|
598 { |
|
599 entry->iFlags = aFlags; |
|
600 } |
|
601 |
|
602 return *texture; |
|
603 } |
|
604 |
|
605 // Assert that the bitmap provider object exists. |
|
606 HUI_ASSERT(aBitmapProvider != NULL); |
|
607 |
|
608 HUI_DEBUG1(_L("CHuiTextureManager::CreateTextureL() - Requesting bitmap content from provider 0x%x .."), aBitmapProvider); |
|
609 |
|
610 // Initialize bitmap and mask bitmap pointers to zero. |
|
611 CFbsBitmap* bitmap = NULL; |
|
612 CFbsBitmap* maskBitmap = NULL; |
|
613 |
|
614 // Call the bitmapProvider method to load the bitmaps. |
|
615 ASSERT( aBitmapProvider ); |
|
616 aBitmapProvider->ProvideBitmapL(aId, bitmap, maskBitmap); |
|
617 |
|
618 // Error if main bitmap could not be loaded |
|
619 User::LeaveIfNull(bitmap); |
|
620 CleanupStack::PushL(bitmap); |
|
621 |
|
622 UpdateFlags(*bitmap, maskBitmap, aFlags); |
|
623 |
|
624 if (maskBitmap) |
|
625 { |
|
626 // A mask was provided, so pass this to texture creation. |
|
627 CleanupStack::PushL(maskBitmap); |
|
628 // create textures right away for these bitmaps |
|
629 tex = &CreateTextureL(*bitmap, maskBitmap, aFlags, aId); |
|
630 // get rid of bitmap and mask |
|
631 CleanupStack::PopAndDestroy(maskBitmap); |
|
632 } |
|
633 else |
|
634 { |
|
635 // No mask, so create texture without one. |
|
636 // create textures right away for these bitmaps |
|
637 tex = &CreateTextureL(*bitmap, NULL, aFlags, aId); |
|
638 } |
|
639 |
|
640 CleanupStack::PopAndDestroy(bitmap); |
|
641 |
|
642 // store the provider with the texture for Restore operations |
|
643 HUI_ASSERT(CheckTexture(aId)>=0); |
|
644 CTextureEntry * entry = TextureEntry(CheckTexture(aId)); |
|
645 entry->iBitmapProvider = aBitmapProvider; |
|
646 entry->iFlags = aFlags; |
|
647 |
|
648 HUI_ASSERT(entry->iTexture); |
|
649 |
|
650 // add a content observer so that we can reload the texture |
|
651 // during restoring |
|
652 if (entry->iTexture->iContentObservers.Count()==0) |
|
653 { |
|
654 HUI_DEBUG2(_L("CHuiTextureManager::CreateTextureL() - Adding content observer 0x%x for texture 0x%x."), entry, entry->iTexture); |
|
655 entry->iTexture->iContentObservers.AppendL(*entry); |
|
656 } |
|
657 |
|
658 return *tex; |
|
659 } |
|
660 |
|
661 EXPORT_C CHuiTexture& CHuiTextureManager::CreateTextureL(CFbsBitmap& aBitmap, |
|
662 const CFbsBitmap* aMask, |
|
663 THuiTextureUploadFlags aFlags, |
|
664 TInt aId) |
|
665 { |
|
666 TBool hasAlpha = (aMask != NULL); |
|
667 TSize bitmapSize = aBitmap.SizeInPixels(); |
|
668 |
|
669 CHuiStatic::Tic(2); |
|
670 |
|
671 // Verify that the bitmap size is same as the mask size. |
|
672 if(hasAlpha && (bitmapSize != aMask->SizeInPixels())) |
|
673 { |
|
674 HUI_DEBUG(_L("CHuiTextureManager::CreateTextureL() - Bitmap size is not compatible with the mask bitmap!")); |
|
675 User::Leave(KErrArgument); |
|
676 } |
|
677 |
|
678 // Leave if the name and the id are empty. |
|
679 if(aId==0) |
|
680 { |
|
681 HUI_DEBUG(_L("CHuiTextureManager::CreateTextureL() - ERROR! Can't create texture without valid id or name.")); |
|
682 User::Leave(KErrArgument); |
|
683 } |
|
684 |
|
685 // If the texture has already been loaded, just return a reference. |
|
686 TInt previouslyLoadedIndex = CheckTexture(aId); |
|
687 |
|
688 if((previouslyLoadedIndex != -1) && IsLoaded(aId)) |
|
689 { |
|
690 CHuiTexture * tex = iTextures[previouslyLoadedIndex]->iTexture; |
|
691 HUI_ASSERT(tex); |
|
692 HUI_DEBUG3(_L("CHuiTextureManager::CreateTextureL() - Reusing previously loaded texture (0x%x, \"%S\", id: %i)."), |
|
693 tex, &tex->ImageFileName(), iTextures[previouslyLoadedIndex]->iId); |
|
694 return *tex; |
|
695 } |
|
696 |
|
697 // create and append to the textures list (automatic) |
|
698 CHuiTexture* texture = CHuiTexture::NewL(); |
|
699 // Set texture name |
|
700 texture->SetImageFileNameL(_L("")); |
|
701 // Set the texture id. |
|
702 HUI_ASSERT(TextureEntryCount()>0); |
|
703 CTextureEntry * te = TextureEntry(TextureEntryCount()-1); |
|
704 te->iId = aId; |
|
705 |
|
706 HUI_DEBUG3(_L("CHuiTextureManager::CreateTextureL() - Created new texture 0x%x (\"%S\", id: %i)."), |
|
707 texture, &texture->ImageFileName(), aId); |
|
708 |
|
709 // Let the texture know its size as soon as possible. |
|
710 texture->SetSize(bitmapSize); |
|
711 |
|
712 HUI_DEBUG6(_L("CHuiTextureManager::CreateTextureL() - Image for texture 0x%x is \"%S\": w=%i, h=%i, dm=%i, mdm=%i"), |
|
713 texture, |
|
714 &texture->ImageFileName(), |
|
715 bitmapSize.iWidth, |
|
716 bitmapSize.iHeight, |
|
717 aBitmap.DisplayMode(), |
|
718 (aMask != NULL ? aMask->DisplayMode() : ENone)); |
|
719 |
|
720 // Enable texture shadow. |
|
721 texture->EnableShadow((aFlags & EHuiTextureUploadFlagGenerateShadow) != 0); |
|
722 |
|
723 if (bitmapSize.iWidth != 0 && bitmapSize.iHeight != 0) |
|
724 { |
|
725 if (aFlags & EHuiTextureFlagAllowDirectBitmapUsage) |
|
726 { |
|
727 texture->UploadDirectL(aBitmap, aMask, aFlags); |
|
728 } |
|
729 else |
|
730 { |
|
731 texture->UploadL(aBitmap, aMask, aFlags); |
|
732 } |
|
733 |
|
734 } |
|
735 |
|
736 HUI_DEBUG1(_L("CHuiTextureManager::CreateTextureL() - Upload for texture 0x%x done, notifying possible observers.."), texture); |
|
737 |
|
738 // Store bits per pixel info to calculate texture memory usage |
|
739 te->iBitDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel( aBitmap.DisplayMode() ); |
|
740 if( aMask ) |
|
741 { |
|
742 te->iBitDepth = te->iBitDepth + TDisplayModeUtils::NumDisplayModeBitsPerPixel( aMask->DisplayMode() ); |
|
743 } |
|
744 |
|
745 // Notify the observers |
|
746 NotifyTextureLoaded(*texture, aId, KErrNone); |
|
747 |
|
748 HUI_DEBUG2(_L("CHuiTextureManager::CreateTextureL() - Finished with texture 0x%x, toc: %f seconds"), texture, CHuiStatic::Toc(2)); |
|
749 return *texture; |
|
750 } |
|
751 |
|
752 |
|
753 EXPORT_C void CHuiTextureManager::UpdateTextureFromBitmapL(TInt aId, MHuiBitmapProvider* aBitmapProvider) |
|
754 { |
|
755 TInt previouslyLoadedIndex = CheckTexture(aId); |
|
756 if (previouslyLoadedIndex == KErrNotFound) |
|
757 { |
|
758 User::Leave(KErrNotFound); |
|
759 } |
|
760 |
|
761 // Unload |
|
762 |
|
763 UnloadTexture(aId); |
|
764 |
|
765 // Upload with the new content |
|
766 |
|
767 CTextureEntry* entry = iTextures[previouslyLoadedIndex]; |
|
768 |
|
769 HUI_DEBUG1(_L("CHuiTextureManager::UpdateTextureFromBitmapL() - Requesting bitmap content from provider 0x%x .."), aBitmapProvider); |
|
770 |
|
771 // Initialize bitmap and mask bitmap pointers to zero. |
|
772 CFbsBitmap* bitmap = NULL; |
|
773 CFbsBitmap* maskBitmap = NULL; |
|
774 |
|
775 // Call the bitmapProvider method to load the bitmaps. |
|
776 if (!aBitmapProvider) |
|
777 { |
|
778 aBitmapProvider = entry->iBitmapProvider; |
|
779 } |
|
780 if (aBitmapProvider) |
|
781 { |
|
782 aBitmapProvider->ProvideBitmapL(aId, bitmap, maskBitmap); |
|
783 } |
|
784 |
|
785 // Error if main bitmap could not be loaded |
|
786 if (!bitmap) |
|
787 { |
|
788 User::Leave(KErrNotFound); |
|
789 } |
|
790 CleanupStack::PushL(bitmap); |
|
791 |
|
792 if (maskBitmap) |
|
793 { |
|
794 CleanupStack::PushL(maskBitmap); |
|
795 } |
|
796 |
|
797 TBool hasAlpha = (maskBitmap != NULL); |
|
798 TSize bitmapSize = bitmap->SizeInPixels(); |
|
799 |
|
800 CHuiStatic::Tic(2); |
|
801 |
|
802 // Verify that the bitmap size is same as the mask size. |
|
803 if(hasAlpha && (bitmapSize != maskBitmap->SizeInPixels())) |
|
804 { |
|
805 HUI_DEBUG(_L("CHuiTextureManager::UpdateTextureFromBitmapL() - Bitmap size is not compatible with the mask bitmap!")); |
|
806 User::Leave(KErrArgument); |
|
807 } |
|
808 |
|
809 CHuiTexture* texture = entry->iTexture; |
|
810 // Set texture name |
|
811 texture->SetImageFileNameL(_L("")); |
|
812 |
|
813 HUI_DEBUG6(_L("CHuiTextureManager::UpdateTextureFromBitmapL() - Image for texture 0x%x is \"%S\": w=%i, h=%i, dm=%i, mdm=%i"), |
|
814 texture, |
|
815 &texture->ImageFileName(), |
|
816 bitmapSize.iWidth, |
|
817 bitmapSize.iHeight, |
|
818 bitmap->DisplayMode(), |
|
819 (maskBitmap != NULL ? maskBitmap->DisplayMode() : ENone)); |
|
820 |
|
821 UpdateFlags(*bitmap, maskBitmap, entry->iFlags); |
|
822 |
|
823 if (bitmapSize.iWidth != 0 && bitmapSize.iHeight != 0) |
|
824 { |
|
825 if (entry->iFlags & EHuiTextureFlagAllowDirectBitmapUsage) |
|
826 { |
|
827 texture->UploadDirectL(*bitmap, maskBitmap, entry->iFlags); |
|
828 } |
|
829 else |
|
830 { |
|
831 texture->UploadL(*bitmap, maskBitmap, entry->iFlags); |
|
832 } |
|
833 } |
|
834 HUI_DEBUG2(_L("CHuiTextureManager::UpdateTextureFromBitmapL() - Finished with texture 0x%x, toc: %f seconds"), texture, CHuiStatic::Toc(2)); |
|
835 |
|
836 // Store bits per pixel info to calculate texture memory usage |
|
837 entry->iBitDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel( bitmap->DisplayMode() ); |
|
838 if (maskBitmap) |
|
839 { |
|
840 entry->iBitDepth = entry->iBitDepth + TDisplayModeUtils::NumDisplayModeBitsPerPixel( maskBitmap->DisplayMode() ); |
|
841 } |
|
842 |
|
843 if (maskBitmap) |
|
844 { |
|
845 CleanupStack::PopAndDestroy(maskBitmap); |
|
846 } |
|
847 |
|
848 CleanupStack::PopAndDestroy(bitmap); |
|
849 |
|
850 // Store provider in case it has changed |
|
851 if (aBitmapProvider) |
|
852 { |
|
853 entry->iBitmapProvider = aBitmapProvider; |
|
854 } |
|
855 } |
|
856 |
|
857 |
|
858 void CHuiTextureManager::UpdateFlags(const CFbsBitmap& aBitmap, const CFbsBitmap* aMaskBitmap, |
|
859 THuiTextureUploadFlags& aFlags) |
|
860 { |
|
861 // Update EHuiTextureFlagUseBitmapDirectly flag if needed |
|
862 |
|
863 if (aFlags & EHuiTextureFlagAllowDirectBitmapUsage) |
|
864 { |
|
865 TBool isDirectBitmapOk = !aBitmap.IsCompressedInRAM() && |
|
866 (!aMaskBitmap || !aMaskBitmap->IsCompressedInRAM()); |
|
867 // Check texture formats from the display |
|
868 // Note: if there is no display the check cannot be done |
|
869 if (isDirectBitmapOk) |
|
870 { |
|
871 isDirectBitmapOk = EFalse; |
|
872 if (CHuiStatic::Env().DisplayCount() > 0) |
|
873 { |
|
874 RPointerArray<CHuiDisplay::CTextureBitmapFormat> formatArray; |
|
875 TInt err = CHuiStatic::Env().PrimaryDisplay().GetPreferredTextureFormats(formatArray); |
|
876 if (!err) |
|
877 { |
|
878 for (TInt i = 0; i < formatArray.Count(); i++) |
|
879 { |
|
880 if ((aBitmap.DisplayMode() == formatArray[i]->iImage) && |
|
881 ((!aMaskBitmap) || (aMaskBitmap->DisplayMode() == formatArray[i]->iMask))) |
|
882 { |
|
883 isDirectBitmapOk = ETrue; |
|
884 } |
|
885 } |
|
886 } |
|
887 formatArray.ResetAndDestroy(); |
|
888 } |
|
889 } |
|
890 // Update |
|
891 if (!isDirectBitmapOk) |
|
892 { |
|
893 aFlags = (THuiTextureUploadFlags)(aFlags & ~EHuiTextureFlagAllowDirectBitmapUsage); |
|
894 } |
|
895 } |
|
896 } |
|
897 |
|
898 |
|
899 RFs& CHuiTextureManager::FsSession() const |
|
900 { |
|
901 return iFS; |
|
902 } |
|
903 |
|
904 |
|
905 EXPORT_C void CHuiTextureManager::PrependImagePath(TDes& aFileName) const |
|
906 { |
|
907 TFileName buf; |
|
908 |
|
909 //allow app to load textures from different drive with complete path |
|
910 TParse p1; |
|
911 p1.Set(aFileName,0,0); |
|
912 |
|
913 if (p1.DrivePresent()) |
|
914 { |
|
915 return; |
|
916 } |
|
917 |
|
918 if(aFileName.Find(*iImagePath) == KErrNotFound) |
|
919 { |
|
920 buf = *iImagePath; |
|
921 buf.Append(aFileName); |
|
922 aFileName = buf; |
|
923 } |
|
924 } |
|
925 |
|
926 |
|
927 EXPORT_C void CHuiTextureManager::UnloadTexture(const TDesC& aImageName, const TInt aFrameNumber) |
|
928 { |
|
929 TFileName fileName = aImageName; |
|
930 PrependImagePath(fileName); |
|
931 TInt index = CheckTexture(fileName, aFrameNumber); |
|
932 if (index >= 0) |
|
933 { |
|
934 HUI_DEBUG2(_L("CHuiTextureManager::UnloadTexture() - Unloading texture 0x%x (id: %i)."), |
|
935 iTextures[index]->iTexture, |
|
936 iTextures[index]->iId); |
|
937 DoUnload(index); |
|
938 return; |
|
939 } |
|
940 HUI_DEBUG1(_L("CHuiTextureManager::UnloadTexture() - Warning! Unable to unload \"%S\" - No such texture(s) found. Already unloaded?"), &fileName); |
|
941 } |
|
942 |
|
943 |
|
944 EXPORT_C void CHuiTextureManager::UnloadTexture(TInt aId) |
|
945 { |
|
946 TInt index = CheckTexture(aId); |
|
947 if (index >= 0) |
|
948 { |
|
949 HUI_DEBUG2(_L("CHuiTextureManager::UnloadTexture() - Unloading texture 0x%x (id: %i)."), |
|
950 iTextures[index]->iTexture, |
|
951 iTextures[index]->iId); |
|
952 DoUnload(index); |
|
953 return; |
|
954 } |
|
955 HUI_DEBUG1(_L("CHuiTextureManager::UnloadTexture() - Warning! Unable to unload id %i. No texture with such id. Already unloaded?"), aId); |
|
956 } |
|
957 |
|
958 |
|
959 EXPORT_C void CHuiTextureManager::DefineFileNameL(TInt aId, |
|
960 const TDesC& aImageName) |
|
961 { |
|
962 if (aId==0) |
|
963 { |
|
964 HUI_DEBUG(_L("CHuiTextureManager::DefineFileNameL() - ERROR! Defining filename for texture id 0 is not allowed. Please use nonzero ids.")); |
|
965 User::Leave(KErrArgument); // can't specify filename for "no id" |
|
966 } |
|
967 |
|
968 // Look for an existing entry for the id. |
|
969 for(TInt i = 0; i < iTextures.Count(); ++i) |
|
970 { |
|
971 if(iTextures[i]->iId == aId) |
|
972 { |
|
973 // Just set the new image name. |
|
974 iTextures[i]->SetFileName(aImageName); |
|
975 return; |
|
976 } |
|
977 } |
|
978 |
|
979 // create a new texture, which automatically registers a new |
|
980 // texture entry in the iTextures list. |
|
981 CHuiTexture::NewL(); |
|
982 // we assume that the newest entry was added last |
|
983 CTextureEntry* entry = iTextures[iTextures.Count()-1]; |
|
984 entry->iId = aId; |
|
985 entry->SetFileName(aImageName); |
|
986 } |
|
987 |
|
988 |
|
989 EXPORT_C TInt CHuiTextureManager::CheckTexture(const TDesC& aImageName, TInt aFrameNumber) const |
|
990 { |
|
991 if(aImageName.Length()==0) |
|
992 { |
|
993 // name empty, can't check |
|
994 return -1; |
|
995 } |
|
996 for(TInt i = 0; i < iTextures.Count(); ++i) |
|
997 { |
|
998 CTextureEntry * te = iTextures[i]; |
|
999 // compare against texture manager entry filename (iFileName) |
|
1000 if((te->iFileName != NULL) |
|
1001 && (aImageName.Compare(*(te->iFileName)) == 0) |
|
1002 && te->iFrameNumber == aFrameNumber) |
|
1003 { |
|
1004 return i; |
|
1005 } |
|
1006 |
|
1007 // compare against texture object imagefilename |
|
1008 if( te->iTexture |
|
1009 && te->iTexture->ImageFileName().Compare(aImageName) == 0 |
|
1010 && te->iTexture->iFrameNumber == aFrameNumber) |
|
1011 { |
|
1012 return i; |
|
1013 } |
|
1014 } |
|
1015 // not found |
|
1016 return -1; |
|
1017 } |
|
1018 |
|
1019 |
|
1020 EXPORT_C TInt CHuiTextureManager::CheckTexture(TInt aId) const |
|
1021 { |
|
1022 if(aId == 0) |
|
1023 { |
|
1024 // id not defined, can't search |
|
1025 return -1; |
|
1026 } |
|
1027 for(TInt i = 0; i < iTextures.Count(); ++i) |
|
1028 { |
|
1029 if(iTextures[i]->iId == aId) |
|
1030 { |
|
1031 return i; |
|
1032 } |
|
1033 } |
|
1034 // not found: |
|
1035 return -1; |
|
1036 } |
|
1037 |
|
1038 |
|
1039 TBool CHuiTextureManager::IsInLoadQueue(const CHuiTexture * texture) const |
|
1040 { |
|
1041 |
|
1042 if (texture == NULL) |
|
1043 { |
|
1044 return EFalse; |
|
1045 } |
|
1046 |
|
1047 // textures in the load queue are not loaded yet, |
|
1048 // the others are assumed to be loaded.. |
|
1049 for(TInt i = 0; i < iLoadQueue.Count(); ++i) |
|
1050 { |
|
1051 CTextureEntry* textureEntry = iLoadQueue[i].iLoading; |
|
1052 if(textureEntry->iTexture == texture) |
|
1053 { |
|
1054 // Still in the queue. |
|
1055 return ETrue; |
|
1056 } |
|
1057 } |
|
1058 return EFalse; |
|
1059 } |
|
1060 |
|
1061 TBool CHuiTextureManager::IsInLoadQueue(TInt id) const |
|
1062 { |
|
1063 // textures in the load queue are not loaded yet, |
|
1064 // the others are assumed to be loaded.. |
|
1065 for(TInt i = 0; i < iLoadQueue.Count(); ++i) |
|
1066 { |
|
1067 if(iLoadQueue[i].iLoading->iId == id) |
|
1068 { |
|
1069 // Still in the queue. |
|
1070 return ETrue; |
|
1071 } |
|
1072 } |
|
1073 return EFalse; |
|
1074 } |
|
1075 |
|
1076 |
|
1077 void CHuiTextureManager::StartLoading() |
|
1078 { |
|
1079 // Start the texture load active object if we're not loading |
|
1080 if(iState == EIdle) |
|
1081 { |
|
1082 HUI_DEBUG(_L("CHuiTextureManager::StartLoading() - Starting load queue.")); |
|
1083 |
|
1084 // loop that finds next entry to load |
|
1085 while (1) |
|
1086 { |
|
1087 HUI_DEBUG(_L("CHuiTextureManager::StartLoading() - Find next to be loaded.")); |
|
1088 |
|
1089 // try to schedule next image for loading.. |
|
1090 TRAPD(err, DoLoadNextL()); |
|
1091 // ok? |
|
1092 |
|
1093 if(err != KErrNone) |
|
1094 { |
|
1095 HUI_DEBUG(_L("CHuiTextureManager::StartLoading() - Found an error.")); |
|
1096 |
|
1097 HUI_ASSERT(iLoadQueue.Count()>0); |
|
1098 // remove the entry from the queue |
|
1099 SLoadQueueEntry entry = PopLoadedQueueEntry(); |
|
1100 switch (err) |
|
1101 { |
|
1102 case KErrNoMemory: |
|
1103 { |
|
1104 HUI_DEBUG3( _L("CHuiTextureManager::StartLoading() - Unable to start loading \"%S\" (id %i): Out of memory. Trying to continue with %i items in the queue.."), &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId, iLoadQueue.Count()); |
|
1105 break; |
|
1106 } |
|
1107 default: |
|
1108 { |
|
1109 HUI_DEBUG4( _L("CHuiTextureManager::StartLoading() - Unable to start loading \"%S\" (id %i): Leave error code %i. Trying to continue with %i items in the queue.."), &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId, err, iLoadQueue.Count()); |
|
1110 break; |
|
1111 } |
|
1112 } |
|
1113 // Notify observers about the image loading error |
|
1114 NotifyTextureLoaded(*entry.iLoading->iTexture, entry.iLoading->iId, err); |
|
1115 // Image loading has been completed. |
|
1116 iState = EIdle; |
|
1117 continue; |
|
1118 } |
|
1119 else |
|
1120 { |
|
1121 HUI_DEBUG(_L("CHuiTextureManager::StartLoading() - Found next texture to load.")); |
|
1122 if(iLoadQueue.Count() == 0 && iLoadQueueHadValidTexture) |
|
1123 { |
|
1124 // During the load loop that has passed we have succesfully started to load |
|
1125 // at least one texture. So the state has been changed to ELoading, thus |
|
1126 // it is now changed back to EIdle. |
|
1127 NotifyStateChange(); |
|
1128 iLoadQueueHadValidTexture = EFalse; |
|
1129 } |
|
1130 } |
|
1131 |
|
1132 // leave the loop if we had no trouble scheduling the next |
|
1133 // image decode |
|
1134 break; |
|
1135 } |
|
1136 |
|
1137 HUI_DEBUG(_L("CHuiTextureManager::StartLoading() - Load queue started.")); |
|
1138 } |
|
1139 } |
|
1140 |
|
1141 |
|
1142 CHuiTextureManager::SLoadQueueEntry CHuiTextureManager::PopLoadedQueueEntry() |
|
1143 { |
|
1144 SLoadQueueEntry entry = iLoadQueue[0]; |
|
1145 HUI_DEBUG2( _L("CHuiTextureManager::PopLoadedQueueEntry() - Cleaning up load queue entry for \"%S\" (id %i)."), |
|
1146 &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId); |
|
1147 iLoadQueue.Remove(0); |
|
1148 // Delete the decoder. |
|
1149 delete entry.iDecoder; |
|
1150 entry.iDecoder = 0; |
|
1151 return entry; |
|
1152 } |
|
1153 |
|
1154 |
|
1155 void CHuiTextureManager::DoLoadNextL() |
|
1156 { |
|
1157 HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - Going into assert.")); |
|
1158 __ASSERT_ALWAYS(iState == EIdle, THuiPanic::Panic(THuiPanic::EInternal)); |
|
1159 HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - Survived assert.")); |
|
1160 |
|
1161 // Any loading tasks left? |
|
1162 if(iLoadQueue.Count() == 0) |
|
1163 { |
|
1164 HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - No more items to load. Changing state to idle.")); |
|
1165 return; // nothing else to be loaded. |
|
1166 } |
|
1167 |
|
1168 // Start timing |
|
1169 CHuiStatic::Tic(2); |
|
1170 |
|
1171 // Manager is now busy. |
|
1172 iState = ELoading; |
|
1173 |
|
1174 HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - Fetching next load queue entry.")); |
|
1175 |
|
1176 // Fetch a load queue entry |
|
1177 SLoadQueueEntry& entry = iLoadQueue[0]; |
|
1178 CHuiTexture* texture = entry.iLoading->iTexture; |
|
1179 HUI_ASSERT(texture != NULL); |
|
1180 HUI_DEBUG1(_L("CHuiTextureManager::DoLoadNext() - Starting to decode %S"), &texture->ImageFileName()); |
|
1181 |
|
1182 // Create a new image decoder for loading the image. |
|
1183 TFileName imageFileName = texture->ImageFileName(); // does not include image path |
|
1184 PrependImagePath(imageFileName); |
|
1185 |
|
1186 delete entry.iDecoder; |
|
1187 entry.iDecoder = NULL; |
|
1188 |
|
1189 TRAPD( err, entry.iDecoder = CImageDecoder::FileNewL(FsSession(), imageFileName, CImageDecoder::EOptionAlwaysThread) ); |
|
1190 |
|
1191 // check for errors.. |
|
1192 if(err != KErrNone) |
|
1193 { |
|
1194 // Try to cancel the decoding (if possible) |
|
1195 if(entry.iDecoder) |
|
1196 { |
|
1197 entry.iDecoder->Cancel(); |
|
1198 } |
|
1199 switch (err) |
|
1200 { |
|
1201 case KEComErrNoInterfaceIdentified: |
|
1202 { |
|
1203 HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". No plugin decoders were found."), &texture->ImageFileName() ); |
|
1204 User::Leave(err); // re-leave with the error |
|
1205 } |
|
1206 case KErrPathNotFound: |
|
1207 { |
|
1208 HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Path not found."), &texture->ImageFileName() ); |
|
1209 User::Leave(err); // re-leave with the error |
|
1210 } |
|
1211 case KErrAccessDenied: |
|
1212 case KErrPermissionDenied: |
|
1213 { |
|
1214 HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Access denied."), &texture->ImageFileName() ); |
|
1215 User::Leave(err); // re-leave with the error |
|
1216 } |
|
1217 case KErrNotFound: |
|
1218 { |
|
1219 HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Resource not found."), &texture->ImageFileName() ); |
|
1220 User::Leave(err); // re-leave with the error |
|
1221 } |
|
1222 case KErrUnderflow: |
|
1223 { |
|
1224 HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Not enough data in file to identify which plugin decoder to use."), &texture->ImageFileName() ); |
|
1225 User::Leave(err); // re-leave with the error |
|
1226 } |
|
1227 case KErrNotSupported: |
|
1228 { |
|
1229 HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Format not supported."), &texture->ImageFileName() ); |
|
1230 User::Leave(err); // re-leave with the error |
|
1231 } |
|
1232 default: |
|
1233 { |
|
1234 HUI_DEBUG2( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Unknown error (code %i)."), &texture->ImageFileName(), err ); |
|
1235 User::Leave(err); // re-leave with the error |
|
1236 } |
|
1237 } |
|
1238 } |
|
1239 |
|
1240 entry.iDecoder->SetDecoderThreadPriority(EPriorityAbsoluteBackgroundNormal); |
|
1241 |
|
1242 // There is a valid texture in the load queue that we now start to load. |
|
1243 iLoadQueueHadValidTexture = ETrue; |
|
1244 |
|
1245 // from decoder's frame info retrieve the framesize |
|
1246 const TInt frameCount = entry.iDecoder->FrameCount(); |
|
1247 entry.iLoading->iFrameCount = frameCount; |
|
1248 if (frameCount && entry.iLoading->iFrameNumber>frameCount) |
|
1249 { |
|
1250 entry.iLoading->iFrameNumber = frameCount-1; |
|
1251 } |
|
1252 |
|
1253 CHuiTextureAnimationState* textureAnimationState = NULL; |
|
1254 |
|
1255 TInt groupId = 0; |
|
1256 TBool foundGroup = FindGroupIdByTextureId( entry.iLoading->iId, groupId ); |
|
1257 |
|
1258 if ( frameCount > 1 && NeedsAnimationState( *entry.iDecoder ) ) |
|
1259 { |
|
1260 // It's animated texture which needs to be produced sequentially. |
|
1261 if ( !foundGroup ) |
|
1262 { |
|
1263 HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - Animation: Group not found.")); |
|
1264 |
|
1265 if ( iAnimationWithoutGroup && |
|
1266 iAnimationWithoutGroup->CheckIfCanProduce( |
|
1267 imageFileName, |
|
1268 entry.iLoading->iFrameNumber, |
|
1269 frameCount ) ) |
|
1270 { |
|
1271 // use iAnimationWithoutGroup |
|
1272 } |
|
1273 else |
|
1274 { |
|
1275 delete iAnimationWithoutGroup; |
|
1276 iAnimationWithoutGroup = NULL; |
|
1277 |
|
1278 iAnimationWithoutGroup = |
|
1279 CHuiTextureAnimationState::NewL( |
|
1280 0, imageFileName, frameCount ); |
|
1281 } |
|
1282 textureAnimationState = iAnimationWithoutGroup; |
|
1283 } |
|
1284 else |
|
1285 { |
|
1286 HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - Animation: Group found.")); |
|
1287 textureAnimationState = CreateAnimationStateL( |
|
1288 groupId, imageFileName, |
|
1289 entry.iLoading->iFrameNumber, frameCount ); |
|
1290 } |
|
1291 } |
|
1292 else |
|
1293 { |
|
1294 // No need to produce sequentially. |
|
1295 if ( foundGroup ) |
|
1296 { |
|
1297 RemoveAnimationState( FindAnimationState( groupId ) ); |
|
1298 } |
|
1299 } |
|
1300 |
|
1301 if ( textureAnimationState != iAnimationWithoutGroup ) |
|
1302 { |
|
1303 delete iAnimationWithoutGroup; |
|
1304 iAnimationWithoutGroup = NULL; |
|
1305 } |
|
1306 |
|
1307 const TInt frameToBeLoaded = |
|
1308 !textureAnimationState ? |
|
1309 entry.iLoading->iFrameNumber : |
|
1310 textureAnimationState->GetNextFrameNumber(); |
|
1311 |
|
1312 TFrameInfo frameInfo(entry.iDecoder->FrameInfo(frameToBeLoaded)); |
|
1313 entry.iLoading->iFrameInterval = frameInfo.iDelay.Int64(); |
|
1314 |
|
1315 if ( textureAnimationState ) |
|
1316 { |
|
1317 textureAnimationState->OfferNextFrameInfo( frameInfo ); |
|
1318 } |
|
1319 |
|
1320 // check for alpha channel |
|
1321 // Gifs don't have alpha but support tranparency so the alpha flag is ignored currently |
|
1322 if(frameInfo.iFlags & TFrameInfo::ETransparencyPossible/* && |
|
1323 frameInfo.iFlags & TFrameInfo::EAlphaChannel*/) |
|
1324 { |
|
1325 entry.iHasAlpha = ETrue; |
|
1326 } |
|
1327 else |
|
1328 { |
|
1329 entry.iHasAlpha = EFalse; |
|
1330 } |
|
1331 |
|
1332 // Get the image original size |
|
1333 TRect bitmapSize = frameInfo.iFrameCoordsInPixels; |
|
1334 TSize overallSize = |
|
1335 !textureAnimationState ? |
|
1336 bitmapSize.Size() : |
|
1337 textureAnimationState->OverallSize(); |
|
1338 |
|
1339 entry.iOriginalSize = overallSize; |
|
1340 |
|
1341 HUI_DEBUG6(_L("CHuiTextureManager::DoLoadNext() - (sub)Image %S (id %i): w=%i, h=%i, bpp=%i, dm=%i"), |
|
1342 &texture->ImageFileName(), |
|
1343 entry.iLoading->iId, |
|
1344 bitmapSize.Size().iWidth, |
|
1345 bitmapSize.Size().iHeight, |
|
1346 frameInfo.iBitsPerPixel, |
|
1347 frameInfo.iFrameDisplayMode); |
|
1348 |
|
1349 HUI_DEBUG(_L("CHuiTextureManager::DoLoadNext() - Setting logical size of the bitmap.")); |
|
1350 |
|
1351 // Try to assign the original size to the image |
|
1352 texture->SetSize(overallSize); |
|
1353 |
|
1354 // target resolution for texture, initially equal to bitmap size |
|
1355 TInt widthResolutionTarget = overallSize.iWidth; |
|
1356 TInt heightResolutionTarget = overallSize.iHeight; |
|
1357 |
|
1358 TSize maxTexSize = entry.iLoading->iMaxTextureSize; |
|
1359 |
|
1360 // Assign new texture resolution target dimensions |
|
1361 // if we have explicitly requested them |
|
1362 if( (entry.iLoading->iFlags & EHuiTextureUploadFlagDoNotRetainResolution) |
|
1363 && maxTexSize.iWidth > 0 |
|
1364 && maxTexSize.iHeight > 0) |
|
1365 { |
|
1366 HUI_DEBUG3(_L("CHuiTextureManager::DoLoadNext() - Custom texture size for image %S: w=%i, h=%i"), |
|
1367 &texture->ImageFileName(), |
|
1368 maxTexSize.iWidth, |
|
1369 maxTexSize.iHeight); |
|
1370 |
|
1371 // assign new target resolution for decoder-based scaling |
|
1372 if(maxTexSize.iWidth < widthResolutionTarget) |
|
1373 { |
|
1374 widthResolutionTarget = maxTexSize.iWidth; |
|
1375 } |
|
1376 if(maxTexSize.iHeight < heightResolutionTarget) |
|
1377 { |
|
1378 heightResolutionTarget = maxTexSize.iHeight; |
|
1379 } |
|
1380 } |
|
1381 |
|
1382 // Set up segmentation so we know what kind of texture (and texture |
|
1383 // size) we are dealing with |
|
1384 texture->SetupSegmentsL(overallSize, |
|
1385 TSize(widthResolutionTarget, heightResolutionTarget), |
|
1386 entry.iLoading->iFlags); |
|
1387 |
|
1388 // we can do direct decoder-based scaling, |
|
1389 // if only a single segment texture is used |
|
1390 if( !textureAnimationState && |
|
1391 texture->SegmentCount() == 1 && |
|
1392 (texture->SegmentTextureSize(0).iWidth < bitmapSize.Size().iWidth || |
|
1393 texture->SegmentTextureSize(0).iHeight < bitmapSize.Size().iHeight)) |
|
1394 { |
|
1395 |
|
1396 // assign new texture size target dimensions from the calculated segment 0 |
|
1397 widthResolutionTarget = texture->SegmentTextureSize(0).iWidth; |
|
1398 heightResolutionTarget = texture->SegmentTextureSize(0).iHeight; |
|
1399 |
|
1400 // we need to do some downscaling, but can we do arbitrary |
|
1401 // scaling as well? |
|
1402 if(frameInfo.iFlags & TFrameInfo::EFullyScaleable) |
|
1403 { |
|
1404 // .. yes, arbitrary scaling is possible |
|
1405 // just assign the new size to the bitmap |
|
1406 // so that it will be scaled accordingly during |
|
1407 // conversion |
|
1408 HUI_DEBUG3(_L("CHuiTextureManager::DoLoadNext() - Downscaling image %S to size %ix%i."), |
|
1409 &texture->ImageFileName(), |
|
1410 widthResolutionTarget, |
|
1411 heightResolutionTarget); |
|
1412 } |
|
1413 else |
|
1414 { |
|
1415 // all decoders should be able to do 1/2, 1/4, 1/8 DCT Scaling |
|
1416 // calculate nearest half size for the decoder-downscaled bitmap |
|
1417 // halve image width&height to size which is closest larger match |
|
1418 // of the bitmap size |
|
1419 TInt halvedWidth = bitmapSize.Size().iWidth; |
|
1420 TInt halvedHeight = bitmapSize.Size().iHeight; |
|
1421 TInt halveFactor = 1; // this limits the halving to 1/8 max |
|
1422 while ( ((halvedWidth >> 1) > widthResolutionTarget) && |
|
1423 ((halvedHeight >> 1) > heightResolutionTarget) |
|
1424 && (halveFactor << 1) <= 8) |
|
1425 { |
|
1426 halveFactor <<= 1; |
|
1427 } |
|
1428 halvedWidth = halvedWidth / halveFactor; |
|
1429 halvedHeight = halvedHeight / halveFactor; |
|
1430 // .. the bitmap will be downscaled further to the correct |
|
1431 // dimensions by ImageLoadingCompleteL after the bitmap has been decoded |
|
1432 HUI_DEBUG4(_L("CHuiTextureManager::DoLoadNext() - Halving image %S size to %ix%i (factor %i)."), |
|
1433 &texture->ImageFileName(), |
|
1434 halvedWidth, |
|
1435 halvedHeight, halveFactor); |
|
1436 widthResolutionTarget = halvedWidth; |
|
1437 heightResolutionTarget = halvedHeight; |
|
1438 } |
|
1439 } |
|
1440 else |
|
1441 { |
|
1442 // either multi-segmented or no need for scaling.. |
|
1443 HUI_DEBUG(_L("CHuiTextureManager::DoLoadNext() - Decoder-based downscaling not required/possible.")); |
|
1444 } |
|
1445 |
|
1446 if ( textureAnimationState ) |
|
1447 { |
|
1448 // we convert subframe completely |
|
1449 widthResolutionTarget = bitmapSize.Size().iWidth; |
|
1450 heightResolutionTarget = bitmapSize.Size().iHeight; |
|
1451 } |
|
1452 |
|
1453 if (!(entry.iLoading->iFlags & EHuiTextureUploadFlagRetainColorDepth) && iBitmap->DisplayMode()!=EColor64K) |
|
1454 { |
|
1455 // (Re)Create the bitmap in EColor64K (16bit) mode to save memory |
|
1456 iBitmap->Create(TSize(widthResolutionTarget, heightResolutionTarget), EColor64K); |
|
1457 } |
|
1458 else if ((entry.iLoading->iFlags & EHuiTextureUploadFlagRetainColorDepth) && iBitmap->DisplayMode()==EColor64K) |
|
1459 { |
|
1460 // (Re)Create the bitmap in EColor16MU (24bit) mode retain the color information |
|
1461 iBitmap->Create(TSize(widthResolutionTarget, heightResolutionTarget), EColor16MU); |
|
1462 } |
|
1463 else |
|
1464 { |
|
1465 // no need to recreate the bitmap, but assign the new size! |
|
1466 iBitmap->Resize(TSize(widthResolutionTarget, heightResolutionTarget)); |
|
1467 } |
|
1468 |
|
1469 if (iBitmap->DisplayMode()==EColor64K) |
|
1470 { |
|
1471 HUI_DEBUG(_L("CHuiTextureManager::DoLoadNext() - Decoding to 16bit image to conserve memory.")); |
|
1472 } |
|
1473 // Decode ( and rescale ) to bitmap. |
|
1474 if(entry.iHasAlpha) |
|
1475 { |
|
1476 // set the alpha channel bitmap to the same size than the color bitmap |
|
1477 iMaskBitmap->Resize(TSize(widthResolutionTarget, heightResolutionTarget)); |
|
1478 entry.iDecoder->Convert(&iStatus, *iBitmap, *iMaskBitmap, frameToBeLoaded); |
|
1479 } |
|
1480 else |
|
1481 { |
|
1482 // Save some memory by making the unused alpha channel bitmap |
|
1483 // very small. |
|
1484 iMaskBitmap->Resize(TSize(4, 4)); |
|
1485 entry.iDecoder->Convert(&iStatus, *iBitmap, frameToBeLoaded); |
|
1486 } |
|
1487 |
|
1488 // Wait for completion. |
|
1489 SetActive(); |
|
1490 |
|
1491 HUI_DEBUG1(_L("CHuiTextureManager::DoLoadNext() - Exiting, toc %.2f sec"), CHuiStatic::Toc(2)); |
|
1492 } |
|
1493 |
|
1494 CHuiTextureAnimationState* CHuiTextureManager::CreateAnimationStateL( |
|
1495 TInt aGroupId, const TDesC& aImageFile, |
|
1496 TInt aFrameNumber, TInt aFrameCount ) |
|
1497 { |
|
1498 CHuiTextureAnimationState* result = FindAnimationState( aGroupId ); |
|
1499 |
|
1500 TBool recreate = !result || !aFrameNumber; |
|
1501 if ( !recreate ) |
|
1502 { |
|
1503 // result != NULL => check if result is animation state of some |
|
1504 // previous frame |
|
1505 recreate = |
|
1506 !result->CheckIfCanProduce( aImageFile, aFrameNumber, aFrameCount ); |
|
1507 } |
|
1508 |
|
1509 if ( recreate ) |
|
1510 { |
|
1511 // First frame, let's just recreate animation state. |
|
1512 RemoveAnimationState( result ); |
|
1513 result = NULL; |
|
1514 |
|
1515 result = CHuiTextureAnimationState::NewL( |
|
1516 aGroupId, aImageFile, aFrameCount ); |
|
1517 CleanupStack::PushL( result ); |
|
1518 iAnimations.AppendL( result ); |
|
1519 CleanupStack::Pop( result ); |
|
1520 } |
|
1521 |
|
1522 return result; |
|
1523 } |
|
1524 |
|
1525 CHuiTextureAnimationState* CHuiTextureManager::FindAnimationState( |
|
1526 TInt aGroupId ) |
|
1527 { |
|
1528 CHuiTextureAnimationState* result = NULL; |
|
1529 const TInt count = iAnimations.Count(); |
|
1530 for ( TInt i = 0; i < count; i++ ) |
|
1531 { |
|
1532 CHuiTextureAnimationState* state = iAnimations[ i ]; |
|
1533 if ( state->OwnerTextureGroupId() == aGroupId ) |
|
1534 { |
|
1535 result = state; |
|
1536 break; |
|
1537 } |
|
1538 } |
|
1539 return result; |
|
1540 } |
|
1541 |
|
1542 void CHuiTextureManager::RemoveAnimationState( |
|
1543 CHuiTextureAnimationState* aState ) |
|
1544 { |
|
1545 if ( aState ) |
|
1546 { |
|
1547 TInt pos = iAnimations.Find( aState ); |
|
1548 if ( pos != KErrNotFound ) |
|
1549 { |
|
1550 iAnimations.Remove( pos ); |
|
1551 } |
|
1552 delete aState; |
|
1553 } |
|
1554 } |
|
1555 |
|
1556 TBool CHuiTextureManager::FindGroupIdByTextureId( |
|
1557 TInt aTextureId, TInt& aGroupId ) const |
|
1558 { |
|
1559 TBool found = EFalse; |
|
1560 const TInt count = iAnimatedTextureGroupItems.Count(); |
|
1561 TInt i = 0; |
|
1562 while ( !found && ( i < count ) ) |
|
1563 { |
|
1564 const TAnimatedTextureGroupItem& item = iAnimatedTextureGroupItems[ i ]; |
|
1565 if ( item.iTextureId == aTextureId ) |
|
1566 { |
|
1567 found = ETrue; |
|
1568 aGroupId = item.iGroupId; |
|
1569 } |
|
1570 i++; |
|
1571 } |
|
1572 return found; |
|
1573 } |
|
1574 |
|
1575 TBool CHuiTextureManager::NeedsAnimationState( const CImageDecoder& aDecoder ) |
|
1576 { |
|
1577 // If this image contains any special image disposal methods, then |
|
1578 // use animation state. |
|
1579 |
|
1580 const TInt frames = aDecoder.FrameCount(); |
|
1581 TBool result = EFalse; |
|
1582 |
|
1583 for ( TInt i = 0; !result && i < frames; ++i ) |
|
1584 { |
|
1585 const TFrameInfo& info = aDecoder.FrameInfo( i ); |
|
1586 const TUint32 disposalFlags = |
|
1587 info.iFlags & |
|
1588 ( TFrameInfo::ELeaveInPlace | |
|
1589 TFrameInfo::ERestoreToBackground | |
|
1590 TFrameInfo::ERestoreToPrevious ); |
|
1591 |
|
1592 result = result || disposalFlags; |
|
1593 } |
|
1594 |
|
1595 return result; |
|
1596 } |
|
1597 |
|
1598 void CHuiTextureManager::DoUnload(TInt index) |
|
1599 { |
|
1600 HUI_ASSERT(index>=0 && index < iTextures.Count()); |
|
1601 CHuiTexture * t = iTextures[index]->iTexture; |
|
1602 if (t == NULL) |
|
1603 { |
|
1604 HUI_DEBUG1(_L("CHuiTextureManager::UnloadTexture() - Not unloading a NULL texture at index %i."), index); |
|
1605 return; |
|
1606 } |
|
1607 |
|
1608 HUI_DEBUG3(_L("CHuiTextureManager::UnloadTexture() - Unloading texture \"%S\" id %i at index %i."), &t->ImageFileName(), iTextures[index]->iId, index); |
|
1609 // Is this in the queue? |
|
1610 if(IsInLoadQueue(t)) |
|
1611 { |
|
1612 // Not loaded yet, can't unload. Mark it as unloaded, though, |
|
1613 // so it will be discarded when the loading completes. |
|
1614 for(TInt i = 0; i < iLoadQueue.Count(); ++i) |
|
1615 { |
|
1616 if(iLoadQueue[i].iLoading->iTexture == t) |
|
1617 { |
|
1618 HUI_DEBUG1(_L("CHuiTextureManager::UnloadTexture() - Marking \"%S\" as unloaded (still in the load queue). "), &t->ImageFileName()); |
|
1619 iLoadQueue[i].iUnloaded = ETrue; |
|
1620 return; |
|
1621 } |
|
1622 } |
|
1623 } |
|
1624 |
|
1625 // Just delete the contents of the texture |
|
1626 t->Reset(); |
|
1627 HUI_ASSERT(!t->HasContent()); |
|
1628 } |
|
1629 |
|
1630 |
|
1631 EXPORT_C TInt CHuiTextureManager::RunError( TInt /*aError*/ ) |
|
1632 { |
|
1633 // Should never be called, RunL is responsible for handling all error cases |
|
1634 HUI_ASSERT(EFalse); |
|
1635 return KErrNone; |
|
1636 } |
|
1637 |
|
1638 |
|
1639 EXPORT_C void CHuiTextureManager::RunL() |
|
1640 { |
|
1641 if( iReleaseState == EReleased || |
|
1642 iReleaseState == EPartiallyReleased || |
|
1643 iReleaseState == EReleasing ) |
|
1644 { |
|
1645 // Set the loading state to idle, but do not notify observers of this, |
|
1646 // since we are released. |
|
1647 // This has to be done so that unfinished loading can be restarted in |
|
1648 // the RestoreL(). |
|
1649 iState = EIdle; |
|
1650 // Leave the texture to the load queue and load it again after restore. |
|
1651 return; |
|
1652 } |
|
1653 |
|
1654 TInt status = iStatus.Int(); |
|
1655 |
|
1656 if ( status == KErrNone ) |
|
1657 { |
|
1658 status = ImageLoadingContinue(); |
|
1659 if ( status > KErrNone ) |
|
1660 { |
|
1661 HUI_DEBUG(_L("CHuiTextureManager::RunL() - Animation: Continue loading.")); |
|
1662 return; |
|
1663 } |
|
1664 } |
|
1665 |
|
1666 // remove the loaded entry from the queue |
|
1667 SLoadQueueEntry entry = PopLoadedQueueEntry(); |
|
1668 |
|
1669 // Image loading has been completed. |
|
1670 iState = EIdle; |
|
1671 |
|
1672 // check status |
|
1673 if( status == KErrNone ) |
|
1674 { |
|
1675 // ok, we have a loaded image, but |
|
1676 // we still need to do texture uploads |
|
1677 // and possibly some image conversions |
|
1678 TRAPD( err, ImageLoadingCompleteL(entry) ); |
|
1679 |
|
1680 if(err != KErrNone) |
|
1681 { |
|
1682 delete iAnimationWithoutGroup; |
|
1683 iAnimationWithoutGroup = NULL; |
|
1684 |
|
1685 switch (err) |
|
1686 { |
|
1687 case KErrNoMemory: |
|
1688 { |
|
1689 HUI_DEBUG3( _L("CHuiTextureManager::RunL() - ERROR! Failed to convert image to texture. Out of memory in ImageLoadingCompleteL(). Source image was \"%S\" (id %i). Trying to continue with %i items in the queue.."), |
|
1690 &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId, iLoadQueue.Count() ); |
|
1691 break; |
|
1692 } |
|
1693 default: |
|
1694 { |
|
1695 HUI_DEBUG4( _L("CHuiTextureManager::RunL() - Error %i occurred during image upload/conversion to texture. Image filename was: \"%S\" (id %i). Trying to continue with %i items in the queue.."), |
|
1696 err, &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId, iLoadQueue.Count() ); |
|
1697 break; |
|
1698 } |
|
1699 } |
|
1700 // Notify observers about the image upload error |
|
1701 NotifyTextureLoaded(*entry.iLoading->iTexture, entry.iLoading->iId, err); |
|
1702 } |
|
1703 } |
|
1704 else |
|
1705 { |
|
1706 HUI_DEBUG2( _L("CHuiTextureManager::RunL() - Image decoding error while decoding \"%S\" (id %i). Bypassing image.."), &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId); |
|
1707 |
|
1708 delete iAnimationWithoutGroup; |
|
1709 iAnimationWithoutGroup = NULL; |
|
1710 |
|
1711 // notify sb of failed image load! |
|
1712 NotifyTextureLoaded(*entry.iLoading->iTexture, entry.iLoading->iId, status); |
|
1713 } |
|
1714 |
|
1715 // Continue loading entries. |
|
1716 StartLoading(); |
|
1717 |
|
1718 if(iLoadQueue.Count() == 0) |
|
1719 { |
|
1720 HUI_DEBUG(_L("CHuiTextureManager::RunL() - No more images to load, exiting..")); |
|
1721 } |
|
1722 } |
|
1723 |
|
1724 |
|
1725 EXPORT_C void CHuiTextureManager::DoCancel() |
|
1726 { |
|
1727 if(iLoadQueue.Count() > 0) |
|
1728 { |
|
1729 iLoadQueue[0].iDecoder->Cancel(); |
|
1730 } |
|
1731 |
|
1732 iState = EIdle; |
|
1733 } |
|
1734 |
|
1735 TInt CHuiTextureManager::ImageLoadingContinue() |
|
1736 { |
|
1737 TInt status = KErrNone; |
|
1738 |
|
1739 const SLoadQueueEntry& entry = iLoadQueue[0]; |
|
1740 |
|
1741 TInt groupId = 0; |
|
1742 CHuiTextureAnimationState* state = NULL; |
|
1743 if ( iAnimationWithoutGroup ) |
|
1744 { |
|
1745 state = iAnimationWithoutGroup; |
|
1746 } |
|
1747 else if ( FindGroupIdByTextureId( entry.iLoading->iId, groupId ) ) |
|
1748 { |
|
1749 state = FindAnimationState( groupId ); |
|
1750 } |
|
1751 else |
|
1752 { |
|
1753 // state = NULL; |
|
1754 } |
|
1755 |
|
1756 if ( state && |
|
1757 ( state->GetNextFrameNumber() != entry.iLoading->iFrameNumber ) ) |
|
1758 { |
|
1759 // Someone has asked animated frames not in sequence - |
|
1760 // very inefficient! |
|
1761 HUI_DEBUG(_L("CHuiTextureManager::ImageLoadingContinue: Frames not requested in sequence.")); |
|
1762 TRAP( status, |
|
1763 state->ProceedWithoutNextFrameL( |
|
1764 iBitmap, |
|
1765 entry.iHasAlpha ? iMaskBitmap : NULL ) ); |
|
1766 |
|
1767 if ( status == KErrNone ) |
|
1768 { |
|
1769 // Image loading has been completed. |
|
1770 iState = EIdle; |
|
1771 StartLoading(); |
|
1772 status = 1; // indicate that started loading. |
|
1773 } |
|
1774 } |
|
1775 |
|
1776 return status; |
|
1777 } |
|
1778 |
|
1779 void CHuiTextureManager::ImageLoadingCompleteL(SLoadQueueEntry& aEntry) |
|
1780 { |
|
1781 CHuiTexture* tex = aEntry.iLoading->iTexture; |
|
1782 HUI_ASSERT(tex); |
|
1783 tex->iFrameNumber = aEntry.iLoading->iFrameNumber; |
|
1784 tex->iFrameCount = aEntry.iLoading->iFrameCount; |
|
1785 tex->iFrameInterval = aEntry.iLoading->iFrameInterval; |
|
1786 |
|
1787 if(iReleaseState != ENormal) |
|
1788 { |
|
1789 HUI_DEBUG1(_L("CHuiTextureManager::ImageLoadingCompleteL() - Unable to upload bitmap data for \"%S\". Texture manager has been released."), &tex->ImageFileName()); |
|
1790 return; |
|
1791 } |
|
1792 |
|
1793 if ( tex->iFrameCount > 1 ) |
|
1794 { |
|
1795 ProcessAnimatedFrameL( aEntry ); |
|
1796 } |
|
1797 TBool hasAlpha = aEntry.iHasAlpha; |
|
1798 |
|
1799 delete iAnimationWithoutGroup; |
|
1800 iAnimationWithoutGroup = NULL; |
|
1801 |
|
1802 TSize* maxTexSize = &aEntry.iLoading->iMaxTextureSize; |
|
1803 if(((maxTexSize->iWidth != 0) && (maxTexSize->iHeight != 0)) && iBitmap->SizeInPixels() != aEntry.iLoading->iMaxTextureSize ) |
|
1804 { |
|
1805 // The decoder failed to constrain the texture dimensions properly, due to its internal limitations. |
|
1806 // So we need to scale the texture(s) down further to the correct size. |
|
1807 |
|
1808 CFbsBitmap* dest = new (ELeave) CFbsBitmap(); |
|
1809 CleanupStack::PushL( dest ); |
|
1810 User::LeaveIfError( dest->Create(*maxTexSize, iBitmap->DisplayMode()) ); |
|
1811 HuiUtil::ScaleFbsBitmapL(*iBitmap, *dest); |
|
1812 CleanupStack::Pop( dest ); |
|
1813 delete iBitmap; |
|
1814 iBitmap = dest; |
|
1815 |
|
1816 if( hasAlpha ) |
|
1817 { |
|
1818 // Scale the alpha as well. |
|
1819 dest = new (ELeave) CFbsBitmap(); |
|
1820 CleanupStack::PushL( dest ); |
|
1821 User::LeaveIfError( |
|
1822 dest->Create(*maxTexSize, iMaskBitmap->DisplayMode()) ); |
|
1823 HuiUtil::ScaleFbsBitmapL(*iMaskBitmap, *dest); |
|
1824 CleanupStack::Pop( dest ); |
|
1825 delete iMaskBitmap; |
|
1826 iMaskBitmap = dest; |
|
1827 } |
|
1828 } |
|
1829 |
|
1830 HUI_DEBUG3(_L("CHuiTextureManager::ImageLoadingCompleteL() - Loading complete for \"%S\". Uploading %ix%i FBS bitmap to texture.."), |
|
1831 &tex->ImageFileName(), |
|
1832 iBitmap->SizeInPixels().iWidth, |
|
1833 iBitmap->SizeInPixels().iHeight); |
|
1834 |
|
1835 // Upload without compression. |
|
1836 tex->UploadL(*iBitmap, |
|
1837 (hasAlpha? iMaskBitmap: NULL), |
|
1838 aEntry.iLoading->iFlags); |
|
1839 |
|
1840 // Store bits per pixel info to calculate texture memory usage |
|
1841 aEntry.iLoading->iBitDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel( iBitmap->DisplayMode() ); |
|
1842 if( iMaskBitmap ) |
|
1843 { |
|
1844 aEntry.iLoading->iBitDepth = aEntry.iLoading->iBitDepth + |
|
1845 TDisplayModeUtils::NumDisplayModeBitsPerPixel( iMaskBitmap->DisplayMode() ); |
|
1846 } |
|
1847 |
|
1848 // Now we're setting up the real texture, no more placeholder needed |
|
1849 tex->SetPlaceholder(NULL); |
|
1850 |
|
1851 HUI_DEBUG2(_L("CHuiTextureManager::ImageLoadingCompleteL() - ... Upload done. Setting original size of %ix%i pixels."), |
|
1852 aEntry.iOriginalSize.iWidth, |
|
1853 aEntry.iOriginalSize.iHeight); |
|
1854 |
|
1855 // (Re)set the original size of the image as the logical size |
|
1856 tex->SetSize(aEntry.iOriginalSize); |
|
1857 |
|
1858 // Notify the observers of loaded texture |
|
1859 NotifyTextureLoaded(*tex, aEntry.iLoading->iId, KErrNone); |
|
1860 |
|
1861 // Unload, if the unloading was already requested while loading! |
|
1862 if(aEntry.iUnloaded) |
|
1863 { |
|
1864 UnloadTexture(tex->ImageFileName(),tex->iFrameNumber); |
|
1865 } |
|
1866 |
|
1867 HUI_DEBUG(_L("CHuiTextureManager::ImageLoadingCompleteL() - Done. ")); |
|
1868 } |
|
1869 |
|
1870 void CHuiTextureManager::ProcessAnimatedFrameL(SLoadQueueEntry& aEntry) |
|
1871 { |
|
1872 // Animated file - produce next frame. |
|
1873 CFbsBitmap* frameBitmap = NULL; |
|
1874 CFbsBitmap* frameMask = NULL; |
|
1875 |
|
1876 // ImageFileName() does not include image path |
|
1877 CHuiTextureAnimationState* state = NULL; |
|
1878 TInt groupId = 0; |
|
1879 if ( iAnimationWithoutGroup ) |
|
1880 { |
|
1881 state = iAnimationWithoutGroup; |
|
1882 } |
|
1883 else if ( FindGroupIdByTextureId( aEntry.iLoading->iId, groupId ) ) |
|
1884 { |
|
1885 state = FindAnimationState( groupId ); |
|
1886 } |
|
1887 |
|
1888 if ( !state ) |
|
1889 { |
|
1890 return; |
|
1891 } |
|
1892 |
|
1893 HUI_DEBUG1(_L("CHuiTextureManager::ProcessAnimatedFrameL: Producing next frame (%d)."), |
|
1894 state->GetNextFrameNumber() ); |
|
1895 |
|
1896 state->ProduceNextFrameL( |
|
1897 frameBitmap, frameMask, |
|
1898 iBitmap, aEntry.iHasAlpha ? iMaskBitmap : NULL ); |
|
1899 |
|
1900 HUI_DEBUG2(_L("CHuiTextureManager::ProcessAnimatedFrameL: Next frame produced (%x, %x)."), |
|
1901 frameBitmap, frameMask ); |
|
1902 |
|
1903 aEntry.iHasAlpha = ( frameMask != NULL ); |
|
1904 if ( frameBitmap != iBitmap ) |
|
1905 { |
|
1906 delete iBitmap; |
|
1907 iBitmap = frameBitmap; |
|
1908 } |
|
1909 |
|
1910 if ( frameMask && (frameMask != iMaskBitmap) ) |
|
1911 { |
|
1912 delete iMaskBitmap; |
|
1913 iMaskBitmap = frameMask; |
|
1914 } |
|
1915 } |
|
1916 |
|
1917 EXPORT_C TInt CHuiTextureManager::LoadQueueCount() const |
|
1918 { |
|
1919 return iLoadQueue.Count(); |
|
1920 } |
|
1921 |
|
1922 |
|
1923 EXPORT_C void CHuiTextureManager::AdvanceTime(TReal32 aElapsedTime) const |
|
1924 { |
|
1925 for(TInt i = 0; i < iAnimatedTextures.Count(); ++i) |
|
1926 { |
|
1927 iAnimatedTextures[i].AdvanceTime(aElapsedTime); |
|
1928 } |
|
1929 NotifyTextureAutoSizeObservers(); |
|
1930 // Write total memory consumed on rendering textures as an info message, |
|
1931 // if feature is enabled from central repository Rnd flag |
|
1932 if ( iEnableTexMemCalculation ) |
|
1933 { |
|
1934 TextureMemUsage(); |
|
1935 } |
|
1936 } |
|
1937 |
|
1938 |
|
1939 EXPORT_C void CHuiTextureManager::SetProcessor(CHuiTextureProcessor* aProcessor) |
|
1940 { |
|
1941 // Since we have ownership of the processor, delete the previous one if |
|
1942 // there is one. |
|
1943 if(iProcessor) |
|
1944 { |
|
1945 delete iProcessor; |
|
1946 iProcessor = NULL; |
|
1947 } |
|
1948 |
|
1949 iProcessor = aProcessor; |
|
1950 } |
|
1951 |
|
1952 |
|
1953 EXPORT_C CHuiTextureProcessor& CHuiTextureManager::Processor() |
|
1954 { |
|
1955 if(!iProcessor) |
|
1956 { |
|
1957 THuiPanic::Panic(THuiPanic::ETextureManagerNoProcessor); |
|
1958 } |
|
1959 return *iProcessor; |
|
1960 } |
|
1961 |
|
1962 |
|
1963 void CHuiTextureManager::CancelLoadingOfTexture(CHuiTexture& aTexture) |
|
1964 { |
|
1965 for(TInt i = 0; i < iLoadQueue.Count(); ++i) |
|
1966 { |
|
1967 if(iLoadQueue[i].iLoading->iTexture == &aTexture) |
|
1968 { |
|
1969 // Texture found from the load queue. |
|
1970 if(i == 0 && iState == ELoading) |
|
1971 { |
|
1972 // Texture is currently loading |
|
1973 Cancel(); |
|
1974 PopLoadedQueueEntry(); |
|
1975 StartLoading(); |
|
1976 } |
|
1977 else |
|
1978 { |
|
1979 // Delete the decoder and remove entry. |
|
1980 delete iLoadQueue[i].iDecoder; |
|
1981 iLoadQueue.Remove(i); |
|
1982 } |
|
1983 break; |
|
1984 } |
|
1985 } |
|
1986 } |
|
1987 |
|
1988 |
|
1989 void CHuiTextureManager::NotifyStateChange() const |
|
1990 { |
|
1991 for(TInt index = 0; index < iStateObservers.Count(); ++index) |
|
1992 { |
|
1993 iStateObservers[index].TextureManagerStateChanged(*this); |
|
1994 } |
|
1995 } |
|
1996 |
|
1997 |
|
1998 EXPORT_C void CHuiTextureManager::NotifyTextureLoaded(CHuiTexture& aTexture, |
|
1999 TInt aTextureId, |
|
2000 TInt aErrorCode) const |
|
2001 { |
|
2002 aTexture.SetTextureChanged(ETrue); |
|
2003 for(TInt index = 0; index < iLoadObservers.Count(); ++index) |
|
2004 { |
|
2005 iLoadObservers[index].TextureLoadingCompleted(aTexture, aTextureId, aErrorCode); |
|
2006 } |
|
2007 } |
|
2008 |
|
2009 EXPORT_C CHuiTextureManager::CTextureEntry * CHuiTextureManager::TextureEntry(TInt aIndex) |
|
2010 { |
|
2011 // check limits |
|
2012 if ( aIndex < iTextures.Count() ) |
|
2013 { |
|
2014 return iTextures[aIndex]; |
|
2015 } |
|
2016 else |
|
2017 { |
|
2018 return NULL; |
|
2019 } |
|
2020 } |
|
2021 |
|
2022 EXPORT_C TInt CHuiTextureManager::TextureEntryCount() const |
|
2023 { |
|
2024 return iTextures.Count(); |
|
2025 } |
|
2026 |
|
2027 EXPORT_C TBool CHuiTextureManager::Release() |
|
2028 { |
|
2029 HUI_DEBUG(_L("CHuiTextureManager::Release() - Called.")); |
|
2030 |
|
2031 HUI_ASSERT(iReleaseState == ENormal); |
|
2032 iReleaseState = EReleasing; |
|
2033 |
|
2034 TBool allReleased = ETrue; // by default, all texures are released. |
|
2035 |
|
2036 // Release all textures. Use an order inverse to creation order. |
|
2037 for(TInt i = iTextures.Count() - 1; i >= 0; --i) |
|
2038 { |
|
2039 CHuiTexture * tex = iTextures[i]->iTexture; |
|
2040 if (tex) |
|
2041 { |
|
2042 // This is called when application goes into the backgrounf |
|
2043 // If release priority is set to 0, the texture should not be released. |
|
2044 if ( tex->Priority() == 0 ) |
|
2045 { |
|
2046 HUI_DEBUG5(_L("CHuiTextureManager::Release() - Not releasing priority texture 0x%x (\"%S\", id: %i) [%i/%i]"), |
|
2047 tex, &(tex->ImageFileName()), iTextures[i]->iId, i+1, iTextures.Count()); |
|
2048 allReleased = EFalse; |
|
2049 } |
|
2050 else |
|
2051 { |
|
2052 HUI_DEBUG5(_L("CHuiTextureManager::Release() - Releasing texture 0x%x (\"%S\", id: %i) [%i/%i]"), |
|
2053 tex, &(tex->ImageFileName()), iTextures[i]->iId, i+1, iTextures.Count()); |
|
2054 tex->Release(); |
|
2055 } |
|
2056 } |
|
2057 else |
|
2058 { |
|
2059 HUI_DEBUG4(_L("CHuiTextureManager::Release() - Not releasing unloaded texture 0x%x, id: %i) [%i/%i]"), |
|
2060 tex, iTextures[i]->iId, i+1, iTextures.Count()); |
|
2061 } |
|
2062 } |
|
2063 |
|
2064 HUI_DEBUG(_L("CHuiTextureManager::Release() - Release processor.")); |
|
2065 |
|
2066 // Release texture processor. |
|
2067 if(iProcessor) |
|
2068 { |
|
2069 iProcessor->Release(); |
|
2070 } |
|
2071 |
|
2072 HUI_ASSERT(iReleaseState == EReleasing); |
|
2073 if ( allReleased ) |
|
2074 { |
|
2075 HUI_DEBUG(_L("CHuiTextureManager::Release() - Exiting (EReleased).")); |
|
2076 iReleaseState = EReleased; |
|
2077 } |
|
2078 else |
|
2079 { |
|
2080 HUI_DEBUG(_L("CHuiTextureManager::Release() - Exiting (EPartiallyReleased).")); |
|
2081 iReleaseState = EPartiallyReleased; |
|
2082 } |
|
2083 return allReleased; |
|
2084 } |
|
2085 |
|
2086 |
|
2087 EXPORT_C void CHuiTextureManager::RestoreL() |
|
2088 { |
|
2089 HUI_DEBUG(_L("CHuiTextureManager::RestoreL() - Called.")); |
|
2090 |
|
2091 HUI_ASSERT(iReleaseState == EReleased || iReleaseState == EPartiallyReleased ); |
|
2092 iReleaseState = ERestoring; |
|
2093 |
|
2094 // Restore texture processor. |
|
2095 if(iProcessor) |
|
2096 { |
|
2097 iProcessor->RestoreL(); |
|
2098 } |
|
2099 |
|
2100 // Restore all textures. Use same order as in which the textures were created. |
|
2101 for(TInt i = 0; i < iTextures.Count(); ++i) |
|
2102 { |
|
2103 CHuiTexture * tex = iTextures[i]->iTexture; |
|
2104 if (tex) |
|
2105 { |
|
2106 if ( tex->HasContent() ) |
|
2107 { |
|
2108 HUI_DEBUG5(_L("CHuiTextureManager::RestoreL() - Alredy has content texture 0x%x (\"%S\", id: %i) [%i/%i]"), |
|
2109 tex, &(tex->ImageFileName()), iTextures[i]->iId, i+1, iTextures.Count()); |
|
2110 } |
|
2111 else |
|
2112 { |
|
2113 HUI_DEBUG5(_L("CHuiTextureManager::RestoreL() - Restoring texture 0x%x (\"%S\", id: %i) [%i/%i]"), |
|
2114 tex, &(tex->ImageFileName()), iTextures[i]->iId, i+1, iTextures.Count()); |
|
2115 // Restore the texture. |
|
2116 tex->RestoreL(); |
|
2117 } |
|
2118 } |
|
2119 else |
|
2120 { |
|
2121 HUI_DEBUG4(_L("CHuiTextureManager::RestoreL() - Not restoring unloaded texture 0x%x, id: %i) [%i/%i]"), |
|
2122 tex, iTextures[i]->iId, i+1, iTextures.Count()); |
|
2123 } |
|
2124 } |
|
2125 |
|
2126 // Restart loading of textures that still might be in the load queue. |
|
2127 StartLoading(); |
|
2128 |
|
2129 HUI_ASSERT(iReleaseState == ERestoring); |
|
2130 iReleaseState = ENormal; |
|
2131 } |
|
2132 |
|
2133 EXPORT_C void CHuiTextureManager::NotifySkinChangedL() |
|
2134 { |
|
2135 for(TInt i = iTextures.Count()-1; i >= 0; i--) |
|
2136 { |
|
2137 CHuiTexture * tex = iTextures[i]->iTexture; |
|
2138 if (tex && |
|
2139 tex->HasContent() && |
|
2140 tex->IsSkinContent()) |
|
2141 { |
|
2142 tex->Release(); |
|
2143 tex->RestoreL(); |
|
2144 } |
|
2145 } |
|
2146 } |
|
2147 |
|
2148 EXPORT_C TInt CHuiTextureManager::AddAnimatedTextureGroupL( |
|
2149 const RArray<TInt>& aTextureIds ) |
|
2150 { |
|
2151 const TInt count = aTextureIds.Count(); |
|
2152 |
|
2153 // Zero ids are not allowed here |
|
2154 for ( TInt j = 0; j < count; j++ ) |
|
2155 { |
|
2156 if ( !aTextureIds[ j ] ) |
|
2157 { |
|
2158 User::Leave( KErrNotSupported ); |
|
2159 } |
|
2160 } |
|
2161 |
|
2162 TInt result = 0; |
|
2163 if ( count ) |
|
2164 { |
|
2165 result = aTextureIds[ 0 ]; |
|
2166 |
|
2167 // Reserve space so next loop cannot fail. |
|
2168 iAnimatedTextureGroupItems.ReserveL( |
|
2169 iAnimatedTextureGroupItems.Count() + aTextureIds.Count() ); |
|
2170 |
|
2171 TAnimatedTextureGroupItem item; |
|
2172 item.iGroupId = result; |
|
2173 |
|
2174 for ( TInt i = 0; i < count; i++ ) |
|
2175 { |
|
2176 item.iTextureId = aTextureIds[ i ]; |
|
2177 |
|
2178 (void)iAnimatedTextureGroupItems. |
|
2179 Append( item ); // ought not to fail due to Reserve. |
|
2180 } |
|
2181 } |
|
2182 |
|
2183 return result; |
|
2184 } |
|
2185 |
|
2186 EXPORT_C void CHuiTextureManager::RemoveAnimatedTextureGroup( TInt aGroupId ) |
|
2187 { |
|
2188 // Remove animated texture group items. |
|
2189 const TInt count = iAnimatedTextureGroupItems.Count(); |
|
2190 for ( TInt i = count - 1; i >= 0; --i ) |
|
2191 { |
|
2192 if ( iAnimatedTextureGroupItems[ i ].iGroupId == aGroupId ) |
|
2193 { |
|
2194 iAnimatedTextureGroupItems.Remove( i ); |
|
2195 } |
|
2196 } |
|
2197 |
|
2198 RemoveAnimationState( FindAnimationState( aGroupId ) ); |
|
2199 } |
|
2200 |
|
2201 // CHuiTextureManager::CTextureEntry |
|
2202 |
|
2203 CHuiTextureManager::CTextureEntry::CTextureEntry( |
|
2204 TInt aId, |
|
2205 const TFileName & aFileName, |
|
2206 const TSize& aMaxTextureSize, |
|
2207 THuiTextureUploadFlags aFlags, |
|
2208 TInt aFrameNumber ) |
|
2209 : iId(aId), iFileName(NULL), |
|
2210 iTexture(NULL), |
|
2211 iMaxTextureSize(aMaxTextureSize), iFlags(aFlags), |
|
2212 iBitmapProvider(NULL), |
|
2213 iFrameNumber(aFrameNumber), |
|
2214 iFrameCount(0), |
|
2215 iFrameInterval(0) |
|
2216 { |
|
2217 SetFileName(aFileName); |
|
2218 } |
|
2219 |
|
2220 CHuiTextureManager::CTextureEntry::CTextureEntry(TInt aId, CHuiTexture * aTexture) |
|
2221 : iId(aId), |
|
2222 iFileName(NULL), |
|
2223 iTexture(aTexture), |
|
2224 iMaxTextureSize(TSize(0,0)), |
|
2225 iFlags(EHuiTextureUploadFlagDefault), |
|
2226 iBitmapProvider(NULL), |
|
2227 iFrameNumber(0), |
|
2228 iFrameCount(0), |
|
2229 iFrameInterval(0) |
|
2230 { |
|
2231 } |
|
2232 |
|
2233 CHuiTextureManager::CTextureEntry::CTextureEntry(const CTextureEntry &aSrc) |
|
2234 : iId(aSrc.iId), |
|
2235 iFileName(NULL), |
|
2236 iTexture(aSrc.iTexture), |
|
2237 iMaxTextureSize(aSrc.iMaxTextureSize), |
|
2238 iFlags(aSrc.iFlags), |
|
2239 iBitmapProvider(NULL), |
|
2240 iFrameNumber(aSrc.iFrameNumber), |
|
2241 iFrameCount(0), |
|
2242 iFrameInterval(0) |
|
2243 { |
|
2244 SetFileName(*aSrc.iFileName); |
|
2245 } |
|
2246 |
|
2247 CHuiTextureManager::CTextureEntry & CHuiTextureManager::CTextureEntry::operator=(const CTextureEntry &aSrc) |
|
2248 { |
|
2249 if ( this == &aSrc ) |
|
2250 { |
|
2251 return *this; |
|
2252 } |
|
2253 |
|
2254 iId = aSrc.iId; |
|
2255 if (aSrc.iFileName != NULL) |
|
2256 { |
|
2257 SetFileName(*aSrc.iFileName); |
|
2258 } |
|
2259 iMaxTextureSize = aSrc.iMaxTextureSize; |
|
2260 iFlags = aSrc.iFlags; |
|
2261 iBitmapProvider = aSrc.iBitmapProvider; |
|
2262 iFrameNumber = aSrc.iFrameNumber; |
|
2263 iFrameCount = aSrc.iFrameCount; |
|
2264 iFrameInterval = aSrc.iFrameInterval; |
|
2265 return *this; |
|
2266 } |
|
2267 |
|
2268 EXPORT_C CHuiTextureManager::CTextureEntry::~CTextureEntry() |
|
2269 { |
|
2270 delete iFileName; |
|
2271 iFileName = NULL; |
|
2272 // CHuiTextureManager deletes the iTexture |
|
2273 } |
|
2274 |
|
2275 void CHuiTextureManager::CTextureEntry::SetFileName(const TFileName & aFileName) |
|
2276 { |
|
2277 delete iFileName; |
|
2278 iFileName = NULL; |
|
2279 if (aFileName.Length()>0) |
|
2280 { |
|
2281 // this might fail and therefore the iFileName is left as NULL. |
|
2282 iFileName = aFileName.Alloc(); |
|
2283 } |
|
2284 } |
|
2285 |
|
2286 void CHuiTextureManager::CTextureEntry::TextureContentUploaded(CHuiTexture& /*aTexture*/) |
|
2287 { |
|
2288 } |
|
2289 void CHuiTextureManager::CTextureEntry::TextureContentReleased(CHuiTexture& /*aTexture*/) |
|
2290 { |
|
2291 } |
|
2292 void CHuiTextureManager::CTextureEntry::RestoreTextureContentL(CHuiTexture& aTexture) |
|
2293 { |
|
2294 HUI_DEBUG(_L("CHuiTextureManager::CTextureEntry::RestoreTextureContentL() - Called for entry 0x%x (id: %i).")); |
|
2295 if (iBitmapProvider != NULL) |
|
2296 { |
|
2297 HUI_DEBUG3(_L("CHuiTextureManager::CTextureEntry::RestoreTextureContentL() - Using bitmap provider 0x%x to recreate content for texture 0x%x (id: %i).."), iBitmapProvider, &aTexture, iId); |
|
2298 CFbsBitmap* bitmap = NULL; |
|
2299 CFbsBitmap* maskBitmap = NULL; |
|
2300 |
|
2301 // call the bitmapProvider method to load the bitmaps |
|
2302 iBitmapProvider->ProvideBitmapL(iId, bitmap, maskBitmap); |
|
2303 |
|
2304 if (maskBitmap) |
|
2305 { |
|
2306 CleanupStack::PushL(maskBitmap); |
|
2307 } |
|
2308 |
|
2309 if (!bitmap) |
|
2310 { |
|
2311 User::Leave(KErrArgument); |
|
2312 } |
|
2313 else |
|
2314 { |
|
2315 CleanupStack::PushL(bitmap); |
|
2316 } |
|
2317 |
|
2318 // recreate texture content.. |
|
2319 |
|
2320 // Let the texture know its size as soon as possible. |
|
2321 aTexture.SetSize(bitmap->SizeInPixels()); |
|
2322 |
|
2323 // Enable texture shadow. |
|
2324 aTexture.EnableShadow((iFlags & EHuiTextureUploadFlagGenerateShadow) != 0); |
|
2325 |
|
2326 // Upload! |
|
2327 TSize bitmapSize = bitmap->SizeInPixels(); |
|
2328 if (bitmapSize.iWidth != 0 && bitmapSize.iHeight != 0) |
|
2329 { |
|
2330 if (iFlags & EHuiTextureFlagAllowDirectBitmapUsage) |
|
2331 { |
|
2332 aTexture.UploadDirectL(*bitmap, maskBitmap, iFlags); |
|
2333 } |
|
2334 else |
|
2335 { |
|
2336 aTexture.UploadL(*bitmap, maskBitmap, iFlags); |
|
2337 } |
|
2338 } |
|
2339 // Clean up owned bitmaps |
|
2340 CleanupStack::PopAndDestroy(bitmap); |
|
2341 if (maskBitmap) |
|
2342 { |
|
2343 CleanupStack::PopAndDestroy(maskBitmap); |
|
2344 } |
|
2345 } |
|
2346 // check for file-based restore |
|
2347 else if (iFileName != NULL) |
|
2348 { |
|
2349 HUI_DEBUG2(_L("CHuiTextureManager::CTextureEntry::RestoreTextureContentL() - Reloading texture 0x%x from \"%S\".."), &aTexture, iFileName); |
|
2350 CHuiStatic::Env().TextureManager().LoadTextureL(*iFileName, iMaxTextureSize, iFlags, iId); |
|
2351 return; |
|
2352 } |
|
2353 else |
|
2354 { |
|
2355 // for PC lint |
|
2356 } |
|
2357 } |
|
2358 |
|
2359 void CHuiTextureManager::NotifyTextureAutoSizeObservers() const |
|
2360 { |
|
2361 if (!iTextureAutoSizingEnabled) |
|
2362 { |
|
2363 return; |
|
2364 } |
|
2365 |
|
2366 TBool somethingWasReported = EFalse; |
|
2367 TBool anyAutoSizedTexturesExist = EFalse; |
|
2368 |
|
2369 for(TInt index = iTextures.Count() - 1; index >= 0; --index) |
|
2370 { |
|
2371 CTextureEntry * entry = iTextures[index]; |
|
2372 if (entry->iTexture) |
|
2373 { |
|
2374 if (entry->iTexture->IsAutoSizeCalculationEnabled()) |
|
2375 { |
|
2376 anyAutoSizedTexturesExist = ETrue; |
|
2377 |
|
2378 // Calculate preferred size from the previous frame data |
|
2379 THuiRealSize preferredSize = entry->iTexture->CalculateAutoSize(); |
|
2380 |
|
2381 // Notify observers if preferred size has changed |
|
2382 if (entry->iTexture->CalculatedAutoSizeChanged()) |
|
2383 { |
|
2384 HUI_DEBUG3(_L("CHuiTextureManager::NotifyTexturePreferredSizeObservers - To be notified id: %i, width: %f , height %f"), entry->iId, preferredSize.iWidth, preferredSize.iHeight); |
|
2385 |
|
2386 // Notify observers. For now ignore return values. |
|
2387 for(TInt index = 0; index < iTextureAutoSizeObservers.Count(); ++index) |
|
2388 { |
|
2389 iTextureAutoSizeObservers[index].PreferredSizeChanged(*entry->iTexture, entry->iId, preferredSize); |
|
2390 somethingWasReported = ETrue; |
|
2391 } |
|
2392 } |
|
2393 |
|
2394 // Restart preferred size calculations for next frame |
|
2395 entry->iTexture->ResetAutoSizeCalculation(); |
|
2396 } |
|
2397 } |
|
2398 } |
|
2399 |
|
2400 if (somethingWasReported) |
|
2401 { |
|
2402 for(TInt index = 0; index < iTextureAutoSizeObservers.Count(); ++index) |
|
2403 { |
|
2404 iTextureAutoSizeObservers[index].PreferredSizeReportCompleted(); |
|
2405 } |
|
2406 } |
|
2407 |
|
2408 // Keep checking autosized textures only if those exist. |
|
2409 // New textures will enable flag when needed. |
|
2410 iTextureAutoSizingEnabled = anyAutoSizedTexturesExist; |
|
2411 } |
|
2412 |
|
2413 EXPORT_C void CHuiTextureManager::ClearChangedTextures() |
|
2414 { |
|
2415 if (iHasChangedTextures) |
|
2416 { |
|
2417 for(TInt index = iTextures.Count() - 1; index >= 0; --index) |
|
2418 { |
|
2419 CTextureEntry * entry = iTextures[index]; |
|
2420 if (entry->iTexture) |
|
2421 { |
|
2422 entry->iTexture->TextureClearChanged(); |
|
2423 } |
|
2424 } |
|
2425 iHasChangedTextures = EFalse; |
|
2426 } |
|
2427 } |
|
2428 |
|
2429 EXPORT_C void CHuiTextureManager::SetHasChangedTextures() |
|
2430 { |
|
2431 iHasChangedTextures = ETrue; |
|
2432 } |
|
2433 |
|
2434 /* |
|
2435 * Enables/Disables memory usage calculation. |
|
2436 */ |
|
2437 EXPORT_C void CHuiTextureManager::EnableTexMemoryCalculation( TBool aEnableTeMemCal ) |
|
2438 { |
|
2439 iEnableTexMemCalculation = aEnableTeMemCal; |
|
2440 } |
|
2441 |
|
2442 /* |
|
2443 * Calculates memory used by texturemanager to store all the textures. |
|
2444 * Texture memory is calculated as ( Texture area ) * ( bits per pixel ) |
|
2445 * |
|
2446 * This routine prints info message stating toal no of textures and memory consuption by them. |
|
2447 */ |
|
2448 void CHuiTextureManager::TextureMemUsage() const |
|
2449 { |
|
2450 TReal32 totalMemUsage = 0; |
|
2451 TReal32 avgBitDepth = 0; |
|
2452 for(TInt i = 0; i < iTextures.Count(); ++i) |
|
2453 { |
|
2454 if( iTextures[i]->iTexture ) |
|
2455 { |
|
2456 TSize size = iTextures[i]->iTexture->Size(); |
|
2457 totalMemUsage = totalMemUsage + size.iWidth * size.iHeight * iTextures[i]->iBitDepth; |
|
2458 avgBitDepth = avgBitDepth + iTextures[i]->iBitDepth; |
|
2459 } |
|
2460 } |
|
2461 |
|
2462 avgBitDepth = avgBitDepth/iTextures.Count(); |
|
2463 totalMemUsage = totalMemUsage/8000000; |
|
2464 TBuf<300> buf; |
|
2465 buf.FillZ(); |
|
2466 buf.AppendNum( totalMemUsage, TRealFormat( 8, 4 ) ); |
|
2467 buf.Append(_L( "MB;By:" ) ); |
|
2468 buf.AppendNum( iTextures.Count() ); |
|
2469 buf.Append(_L( ";BD:" ) ); |
|
2470 buf.AppendNum( avgBitDepth ); |
|
2471 User::InfoPrint( buf ); |
|
2472 } |
|
2473 TInt CHuiTextureManager::EstimatedTextureMemUsage(TInt aAverageBitsPerPixel) const |
|
2474 { |
|
2475 TReal32 averageBytesPerPixel = TReal32(aAverageBitsPerPixel)/8.f; |
|
2476 TReal32 totalMemUsage = 0; |
|
2477 TInt pixels = 0; |
|
2478 for(TInt i = 0; i < iTextures.Count(); ++i) |
|
2479 { |
|
2480 // TODO: Exclude NVG textures ! |
|
2481 if( iTextures[i]->iTexture /*&& |
|
2482 iTextures[i]->iTexture->HasContent()*/) |
|
2483 { |
|
2484 TSize size = iTextures[i]->iTexture->Size(); |
|
2485 pixels += size.iWidth * size.iHeight; |
|
2486 } |
|
2487 } |
|
2488 |
|
2489 totalMemUsage = TReal32(pixels) * averageBytesPerPixel; |
|
2490 return totalMemUsage; |
|
2491 } |
|
2492 |
|
2493 |
|
2494 |
|
2495 EXPORT_C void CHuiTextureManager::TextureManagerExtension(const TUid& /*aExtensionUid*/, TAny** aExtensionParams) |
|
2496 { |
|
2497 // If no extension with given UID was found, indicate it by returning null |
|
2498 *aExtensionParams = NULL; |
|
2499 } |
|
2500 |
|
2501 void CHuiTextureManager::EnableAutoSizeCalculation(TBool aEnable) |
|
2502 { |
|
2503 iTextureAutoSizingEnabled = aEnable; |
|
2504 } |
|
2505 |