|
1 /* |
|
2 * Copyright (c) 2006-2008 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: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include "huicanvastexturecache.h" |
|
21 #include "uiacceltk/HuiImage.h" |
|
22 #include "uiacceltk/HuiTexture.h" |
|
23 #include "uiacceltk/HuiEnv.h" |
|
24 #include "uiacceltk/HuiUtil.h" |
|
25 #include "uiacceltk/HuiStatic.h" |
|
26 #include "huicanvasgc.h" |
|
27 #include "HuiRenderPlugin.h" |
|
28 #include "huicanvasrenderbuffer.h" |
|
29 |
|
30 #include <e32cmn.h> |
|
31 #include <bitdev.h> |
|
32 #include <AknLayoutFont.h> |
|
33 #include <e32property.h> |
|
34 |
|
35 // Enable this for debugging cache usage |
|
36 //#define HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE |
|
37 //#define HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE_EGL |
|
38 //#define HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE_EXTENDED |
|
39 |
|
40 // Enable this for debugging performance |
|
41 //#define HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
42 |
|
43 /** Magic S60 font constant */ |
|
44 const TInt KHuiFontVerticalShiftInPixels = 1; |
|
45 |
|
46 /** Initial touch count value */ |
|
47 const TInt KHuiInitialBitmapTouchCount = -1; |
|
48 |
|
49 /** Estimated bits per pixel for all textures */ |
|
50 const TReal32 KHuiTextureEstimatedBpp = 32; |
|
51 |
|
52 /** Estimated bits per pixel for rasterized canvas texts */ |
|
53 const TReal32 KHuiCanvasTextEstimatedBpp = 8; |
|
54 |
|
55 /** Estimated bits per pixel for canvas images */ |
|
56 const TReal32 KHuiCanvasImageEstimatedBpp = 32; |
|
57 |
|
58 /** Estimated bits per pixel for canvas render buffers */ |
|
59 const TReal32 KHuiCanvasRenderBufferEstimatedBpp = 32; |
|
60 |
|
61 /** Constant to define target how much memory UI textures should use, |
|
62 this is not a hard limit but effects how long unused textures are cached */ |
|
63 const TInt KHuiMaxRecommendedTextureAmountInKBytes = 4096; |
|
64 |
|
65 /** Constant to define target how much memory UI render buffers should use, |
|
66 this is not a hard limit but effects how long unused render buffers are cached */ |
|
67 const TInt KHuiMaxRecommendedRenderBufferAmountInKBytes = 0; |
|
68 |
|
69 /** Ratio how cache is divided between canvas texts and images */ |
|
70 const TReal32 KHuiCanvasUnusedTextImageCacheRatio = 0.1f; |
|
71 |
|
72 /** Max amount of recycled texture objects */ |
|
73 const TInt KHuiMaxRecycledTextureCount = 100; |
|
74 |
|
75 /** Use color modulation or not for setting text color */ |
|
76 const TBool KHuiCanvasTextUseColorModulation = ETrue; |
|
77 |
|
78 /** Store bitmap pointers to avoid handle duplication */ |
|
79 const TBool KHuiCanvasKeepBitmapPointer = ETrue; |
|
80 |
|
81 CHuiCanvasImage::CHuiCanvasImage() : |
|
82 iTexture(NULL), |
|
83 iCache(NULL) |
|
84 { |
|
85 } |
|
86 |
|
87 CHuiCanvasImage::~CHuiCanvasImage() |
|
88 { |
|
89 if (iCache && iTexture) |
|
90 { |
|
91 iCache->DeleteRecycledTexture(iTexture); |
|
92 } |
|
93 else |
|
94 { |
|
95 delete iTexture; |
|
96 } |
|
97 |
|
98 iActiveUsers.Close(); |
|
99 } |
|
100 |
|
101 void CHuiCanvasImage::RefreshUser(const CHuiCanvasVisual& aUser) |
|
102 { |
|
103 if (iActiveUsers.FindInAddressOrder(&aUser) == KErrNotFound) |
|
104 { |
|
105 iActiveUsers.InsertInAddressOrder(&aUser); |
|
106 } |
|
107 |
|
108 // Update last usage time |
|
109 iLastUsed.UniversalTime(); |
|
110 } |
|
111 |
|
112 void CHuiCanvasImage::RemoveUser(const CHuiCanvasVisual& aUser) |
|
113 { |
|
114 TInt index = iActiveUsers.FindInAddressOrder(&aUser); |
|
115 |
|
116 if (index != KErrNotFound) |
|
117 { |
|
118 iActiveUsers.Remove(index); |
|
119 } |
|
120 } |
|
121 |
|
122 TBool CHuiCanvasImage::IsUser(const CHuiCanvasVisual& aUser) const |
|
123 { |
|
124 TInt index = iActiveUsers.FindInAddressOrder(&aUser); |
|
125 |
|
126 if (index != KErrNotFound) |
|
127 { |
|
128 return ETrue; |
|
129 } |
|
130 return EFalse; |
|
131 } |
|
132 |
|
133 TBool CHuiCanvasImage::IsAnyUser() const |
|
134 { |
|
135 return iActiveUsers.Count() != 0; |
|
136 } |
|
137 |
|
138 CHuiTexture* CHuiCanvasImage::Texture() const |
|
139 { |
|
140 return iTexture; |
|
141 } |
|
142 |
|
143 void CHuiCanvasImage::CopyAttributes(CHuiCanvasImage& aSrc) |
|
144 { |
|
145 iTexture = aSrc.iTexture; |
|
146 iGcParams = aSrc.iGcParams; |
|
147 iLastUsed = aSrc.iLastUsed; |
|
148 iCache = aSrc.iCache; |
|
149 |
|
150 iActiveUsers.Reset(); |
|
151 for (TInt i=0; i < aSrc.iActiveUsers.Count(); i++) |
|
152 { |
|
153 iActiveUsers.Append(aSrc.iActiveUsers[i]); |
|
154 } |
|
155 } |
|
156 |
|
157 void CHuiCanvasImage::Reset() |
|
158 { |
|
159 // Reset does not delete owned items ! |
|
160 iTexture = NULL; |
|
161 iGcParams = THuiCachedGcParams(); |
|
162 iActiveUsers.Reset(); |
|
163 } |
|
164 |
|
165 |
|
166 CHuiCanvasGraphicImage::CHuiCanvasGraphicImage() : |
|
167 iBitmapHandle(0), |
|
168 iMaskHandle(0), |
|
169 iBitmap(NULL), |
|
170 iMask(NULL), |
|
171 iInvertedMask(EFalse), |
|
172 iMaskOriginPoint(TPoint(0,0)), |
|
173 iBitmapTouchCount(-1), |
|
174 iMaskTouchCount(-1), |
|
175 iImageSize(TSize(0,0)) |
|
176 { |
|
177 } |
|
178 |
|
179 void CHuiCanvasGraphicImage::CopyAttributes(CHuiCanvasGraphicImage& aSrc) |
|
180 { |
|
181 CHuiCanvasImage::CopyAttributes(aSrc); |
|
182 iBitmap = aSrc.iBitmap; |
|
183 iMask = aSrc.iMask; |
|
184 iBitmapHandle = aSrc.iBitmapHandle; |
|
185 iMaskHandle = aSrc.iMaskHandle; |
|
186 iInvertedMask = aSrc.iInvertedMask; |
|
187 iMaskOriginPoint = aSrc.iMaskOriginPoint; |
|
188 iTexture = aSrc.iTexture; |
|
189 iBitmapTouchCount = aSrc.iBitmapTouchCount; |
|
190 iMaskTouchCount = aSrc.iMaskTouchCount; |
|
191 iImageSize = aSrc.iImageSize; |
|
192 |
|
193 iSubImages.Reset(); |
|
194 for (TInt i=0; i<aSrc.iSubImages.Count();i++) |
|
195 { |
|
196 iSubImages.Append(aSrc.iSubImages[i]); |
|
197 } |
|
198 } |
|
199 |
|
200 void CHuiCanvasGraphicImage::Reset() |
|
201 { |
|
202 // Reset does not delete owned items ! |
|
203 CHuiCanvasImage::Reset(); |
|
204 iBitmap = NULL; |
|
205 iMask = NULL; |
|
206 iSubImages.Reset(); |
|
207 iBitmapHandle = 0; |
|
208 iMaskHandle = 0; |
|
209 iInvertedMask = EFalse; |
|
210 iMaskOriginPoint = TPoint(0,0); |
|
211 iTexture = NULL; |
|
212 iBitmapTouchCount = -1; |
|
213 iMaskTouchCount = -1; |
|
214 iImageSize = TSize(0,0); |
|
215 }; |
|
216 |
|
217 |
|
218 |
|
219 CHuiCanvasGraphicImage::~CHuiCanvasGraphicImage() |
|
220 { |
|
221 delete iBitmap; |
|
222 delete iMask; |
|
223 for (TInt i=0;i<iSubImages.Count();i++) |
|
224 { |
|
225 delete iSubImages[i].iBitmap; |
|
226 delete iSubImages[i].iMask; |
|
227 } |
|
228 iSubImages.Close(); |
|
229 } |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 CHuiCanvasTextImage::CHuiCanvasTextImage() : |
|
235 iText(NULL), |
|
236 iFindTextPtr(NULL), |
|
237 iFontHandle(0), |
|
238 iRasterizationOffset(TPoint(0,0)), |
|
239 iTextBoxMaxSize(TSize(KMinTInt,KMinTInt)), |
|
240 iTextWidth(KMinTInt), |
|
241 iBaseLineOffset(KMinTInt), |
|
242 iTextAlign(CGraphicsContext::ELeft), |
|
243 iMargin(0), |
|
244 iAngle(0), |
|
245 iUseColorModulation(EFalse), |
|
246 iFont(NULL) |
|
247 { |
|
248 } |
|
249 |
|
250 void CHuiCanvasTextImage::CopyAttributes(CHuiCanvasTextImage& aSrc) |
|
251 { |
|
252 CHuiCanvasImage::CopyAttributes(aSrc); |
|
253 iText = aSrc.iText; |
|
254 iFindTextPtr = aSrc.iFindTextPtr; |
|
255 iFontHandle = aSrc.iFontHandle; |
|
256 iRasterizationOffset = aSrc.iRasterizationOffset; |
|
257 iTextBoxMaxSize = aSrc.iTextBoxMaxSize; |
|
258 iTextWidth = aSrc.iTextWidth; |
|
259 iBaseLineOffset = aSrc.iBaseLineOffset; |
|
260 iTextAlign = aSrc.iTextAlign; |
|
261 iMargin = aSrc.iMargin; |
|
262 iAngle = aSrc.iAngle; |
|
263 iUseColorModulation = aSrc.iUseColorModulation; |
|
264 iTextParams = aSrc.iTextParams; |
|
265 iFont = aSrc.iFont; |
|
266 } |
|
267 |
|
268 void CHuiCanvasTextImage::Reset() |
|
269 { |
|
270 // Reset does not delete owned items ! |
|
271 CHuiCanvasImage::Reset(); |
|
272 iText = NULL; |
|
273 iFindTextPtr = NULL; |
|
274 iFontHandle = 0, |
|
275 iRasterizationOffset = TPoint(0,0); |
|
276 iTextBoxMaxSize = TSize(KMinTInt,KMinTInt); |
|
277 iTextWidth = KMinTInt; |
|
278 iBaseLineOffset = KMinTInt; |
|
279 iTextAlign = CGraphicsContext::ELeft; |
|
280 iMargin = 0; |
|
281 iAngle = 0; |
|
282 iUseColorModulation = EFalse; |
|
283 iFont = NULL; |
|
284 } |
|
285 |
|
286 CHuiCanvasTextImage::~CHuiCanvasTextImage() |
|
287 { |
|
288 } |
|
289 |
|
290 TBool CHuiCanvasTextImage::UseColorModulation() const |
|
291 { |
|
292 return iUseColorModulation; |
|
293 } |
|
294 |
|
295 NONSHARABLE_CLASS( CHuiCanvasRenderBufferImage ) : public CHuiCanvasImage |
|
296 { |
|
297 public: |
|
298 |
|
299 CHuiCanvasRenderBufferImage(); |
|
300 |
|
301 ~CHuiCanvasRenderBufferImage(); |
|
302 |
|
303 virtual void CopyAttributes(CHuiCanvasRenderBufferImage& aSrc); |
|
304 |
|
305 virtual void Reset(); |
|
306 |
|
307 public: |
|
308 |
|
309 CHuiCanvasRenderBuffer* iCanvasRenderBuffer; |
|
310 TAny* iOwner; |
|
311 }; |
|
312 |
|
313 |
|
314 CHuiCanvasRenderBufferImage::CHuiCanvasRenderBufferImage() : |
|
315 iCanvasRenderBuffer(NULL), |
|
316 iOwner(NULL) |
|
317 { |
|
318 } |
|
319 |
|
320 void CHuiCanvasRenderBufferImage::CopyAttributes(CHuiCanvasRenderBufferImage& aSrc) |
|
321 { |
|
322 CHuiCanvasImage::CopyAttributes(aSrc); |
|
323 iCanvasRenderBuffer= aSrc.iCanvasRenderBuffer; |
|
324 iOwner = aSrc.iOwner; |
|
325 } |
|
326 |
|
327 void CHuiCanvasRenderBufferImage::Reset() |
|
328 { |
|
329 // Reset does not delete owned items ! |
|
330 CHuiCanvasImage::Reset(); |
|
331 iCanvasRenderBuffer = NULL; |
|
332 iOwner = NULL; |
|
333 } |
|
334 |
|
335 CHuiCanvasRenderBufferImage::~CHuiCanvasRenderBufferImage() |
|
336 { |
|
337 delete iCanvasRenderBuffer; |
|
338 } |
|
339 |
|
340 |
|
341 NONSHARABLE_CLASS( CHuiCanvasImageRasterizer ) : public CBase |
|
342 { |
|
343 public: |
|
344 |
|
345 CHuiCanvasImageRasterizer(); |
|
346 |
|
347 ~CHuiCanvasImageRasterizer(); |
|
348 |
|
349 void ConstructL(TDisplayMode aPreferredMode = ENone); |
|
350 |
|
351 TBool IsSeparateTextMaskUsed(); |
|
352 |
|
353 static CFbsBitmap* CreateMovedMaskL(CFbsBitmap& aOriginalMask, TPoint aNewTopLeftCorner); |
|
354 |
|
355 static CFbsBitmap* CreateInvertedMaskL(CFbsBitmap& aOriginalMask); |
|
356 |
|
357 protected: |
|
358 |
|
359 CFbsBitmap* iTempMask; |
|
360 CFbsBitmapDevice* iTempMaskDevice; |
|
361 CFbsBitGc* iTempMaskGc; |
|
362 |
|
363 CFbsBitmap* iTempBitmap; |
|
364 CFbsBitmapDevice* iTempBitmapDevice; |
|
365 CFbsBitGc* iTempBitmapGc; |
|
366 }; |
|
367 |
|
368 CHuiCanvasImageRasterizer::CHuiCanvasImageRasterizer() |
|
369 { |
|
370 } |
|
371 |
|
372 CHuiCanvasImageRasterizer::~CHuiCanvasImageRasterizer() |
|
373 { |
|
374 delete iTempMaskGc; |
|
375 delete iTempMaskDevice; |
|
376 delete iTempMask; |
|
377 |
|
378 delete iTempBitmapGc; |
|
379 delete iTempBitmapDevice; |
|
380 delete iTempBitmap; |
|
381 } |
|
382 |
|
383 void CHuiCanvasImageRasterizer::ConstructL(TDisplayMode aPreferredMode) |
|
384 { |
|
385 iTempMask = NULL; |
|
386 iTempMaskDevice = NULL; |
|
387 iTempMaskGc = NULL; |
|
388 |
|
389 iTempBitmap = NULL; |
|
390 iTempBitmapDevice = NULL; |
|
391 iTempBitmapGc = NULL; |
|
392 |
|
393 // Select fastest color mode for uploading rasterized texts, we assume that EColor16MA |
|
394 // should be best for HW accelrated rendereres (requiring least amount of conversions |
|
395 // needed before uploading to texture memory) and EColor64K is good for |
|
396 // bitgdi because its backbuffer is in that format. |
|
397 // |
|
398 // NOTE: EHuiRendererGles10 and EHuiRendererGles11 temporarely use EColor64K |
|
399 // beacuse it looks as there are some problems with uploading 16MA |
|
400 // mode bitmaps into multisegmented textures. |
|
401 // |
|
402 TDisplayMode colorMode = EColor16MA; |
|
403 if (aPreferredMode == EGray256 && |
|
404 CHuiStatic::Env().Renderer() == EHuiRendererVg10) |
|
405 { |
|
406 colorMode = EGray256; |
|
407 } |
|
408 else if (aPreferredMode == EColor64K) |
|
409 { |
|
410 colorMode = EColor64K; |
|
411 } |
|
412 else if (CHuiStatic::Env().Renderer() == EHuiRendererBitgdi || |
|
413 CHuiStatic::Env().Renderer() == EHuiRendererGles10 || |
|
414 CHuiStatic::Env().Renderer() == EHuiRendererGles11) |
|
415 { |
|
416 colorMode = EColor64K; |
|
417 } |
|
418 |
|
419 iTempBitmap = new (ELeave) CFbsBitmap; |
|
420 iTempBitmap->Create(TSize(4,4), colorMode); |
|
421 iTempBitmapDevice = CFbsBitmapDevice::NewL(iTempBitmap); |
|
422 User::LeaveIfError(iTempBitmapDevice->CreateContext(iTempBitmapGc)); |
|
423 |
|
424 if (colorMode != EGray256) |
|
425 { |
|
426 iTempMask = new (ELeave) CFbsBitmap; |
|
427 iTempMask->Create(TSize(4,4), EGray256); |
|
428 iTempMaskDevice = CFbsBitmapDevice::NewL(iTempMask); |
|
429 User::LeaveIfError(iTempMaskDevice->CreateContext(iTempMaskGc)); |
|
430 } |
|
431 } |
|
432 |
|
433 TBool CHuiCanvasImageRasterizer::IsSeparateTextMaskUsed() |
|
434 { |
|
435 if (iTempBitmap && |
|
436 iTempBitmap->DisplayMode() != EColor16MA && |
|
437 iTempBitmap->DisplayMode() != EColor16MAP && |
|
438 iTempBitmap->DisplayMode() != EGray256) |
|
439 { |
|
440 return ETrue; |
|
441 } |
|
442 else |
|
443 { |
|
444 return EFalse; |
|
445 } |
|
446 } |
|
447 |
|
448 CFbsBitmap* CHuiCanvasImageRasterizer::CreateInvertedMaskL(CFbsBitmap& aOriginalMask) |
|
449 { |
|
450 TSize size = aOriginalMask.SizeInPixels(); |
|
451 |
|
452 CFbsBitmap* newMask = new(ELeave)CFbsBitmap; |
|
453 CleanupStack::PushL(newMask); |
|
454 |
|
455 CFbsBitmap* bitmap = new(ELeave)CFbsBitmap; |
|
456 CleanupStack::PushL(bitmap); |
|
457 |
|
458 newMask->Create(size, aOriginalMask.DisplayMode()); |
|
459 bitmap->Create(size, aOriginalMask.DisplayMode()); |
|
460 |
|
461 CFbsDevice* newMaskdevice = NULL; |
|
462 CFbsBitGc* newMaskGc = NULL; |
|
463 |
|
464 CFbsDevice* bitmapDevice = NULL; |
|
465 CFbsBitGc* bitmapGc = NULL; |
|
466 |
|
467 newMaskdevice = CFbsBitmapDevice::NewL(newMask); |
|
468 CleanupStack::PushL(newMaskdevice); |
|
469 User::LeaveIfError(newMaskdevice->CreateContext(newMaskGc)); |
|
470 |
|
471 bitmapDevice = CFbsBitmapDevice::NewL(bitmap); |
|
472 CleanupStack::PushL(bitmapDevice); |
|
473 User::LeaveIfError(bitmapDevice->CreateContext(bitmapGc)); |
|
474 |
|
475 bitmapGc->SetBrushStyle(CGraphicsContext::ESolidBrush); |
|
476 bitmapGc->SetPenStyle(CGraphicsContext::ESolidPen); |
|
477 bitmapGc->SetPenColor(KRgbBlack); |
|
478 bitmapGc->SetBrushColor(KRgbBlack); |
|
479 bitmapGc->DrawRect(TRect(TPoint(0,0), size)); |
|
480 |
|
481 newMaskGc->SetBrushStyle(CGraphicsContext::ESolidBrush); |
|
482 newMaskGc->SetPenStyle(CGraphicsContext::ESolidPen); |
|
483 newMaskGc->SetPenColor(KRgbWhite); |
|
484 newMaskGc->SetBrushColor(KRgbWhite); |
|
485 newMaskGc->DrawRect(TRect(TPoint(0,0), size)); |
|
486 newMaskGc->BitBltMasked(TPoint(0,0), bitmap, TRect(TPoint(0,0), size), &aOriginalMask, EFalse); |
|
487 |
|
488 delete bitmapGc; |
|
489 delete newMaskGc; |
|
490 |
|
491 CleanupStack::PopAndDestroy(bitmapDevice); |
|
492 CleanupStack::PopAndDestroy(newMaskdevice); |
|
493 CleanupStack::PopAndDestroy(bitmap); |
|
494 CleanupStack::Pop(newMask); |
|
495 |
|
496 return newMask; |
|
497 } |
|
498 |
|
499 CFbsBitmap* CHuiCanvasImageRasterizer::CreateMovedMaskL(CFbsBitmap& aOriginalMask, TPoint aNewTopLeftCorner) |
|
500 { |
|
501 TSize size = aOriginalMask.SizeInPixels(); |
|
502 |
|
503 CFbsBitmap* newMask = new(ELeave)CFbsBitmap; |
|
504 CleanupStack::PushL(newMask); |
|
505 |
|
506 newMask->Create(size, aOriginalMask.DisplayMode()); |
|
507 |
|
508 CFbsDevice* newMaskdevice = NULL; |
|
509 CFbsBitGc* newMaskGc = NULL; |
|
510 |
|
511 newMaskdevice = CFbsBitmapDevice::NewL(newMask); |
|
512 CleanupStack::PushL(newMaskdevice); |
|
513 User::LeaveIfError(newMaskdevice->CreateContext(newMaskGc)); |
|
514 |
|
515 newMaskGc->SetBrushStyle(CGraphicsContext::ESolidBrush); |
|
516 newMaskGc->SetPenStyle(CGraphicsContext::ESolidPen); |
|
517 newMaskGc->SetPenColor(KRgbWhite); |
|
518 newMaskGc->SetBrushColor(KRgbWhite); |
|
519 newMaskGc->DrawRect(TRect(TPoint(0,0), size)); |
|
520 newMaskGc->BitBlt(TPoint(0,0), &aOriginalMask, TRect(aNewTopLeftCorner, size)); |
|
521 newMaskGc->BitBlt(aNewTopLeftCorner, &aOriginalMask, TRect(TPoint(0,0), size)); |
|
522 |
|
523 delete newMaskGc; |
|
524 CleanupStack::PopAndDestroy(newMaskdevice); |
|
525 CleanupStack::Pop(newMask); |
|
526 |
|
527 return newMask; |
|
528 } |
|
529 |
|
530 |
|
531 NONSHARABLE_CLASS( CHuiCanvasTextImageRasterizer ) : public CHuiCanvasImageRasterizer |
|
532 { |
|
533 public: |
|
534 |
|
535 CHuiCanvasTextImageRasterizer(); |
|
536 |
|
537 ~CHuiCanvasTextImageRasterizer(); |
|
538 |
|
539 void RasterizeL(CHuiCanvasTextImage& aTextImage); |
|
540 |
|
541 private: |
|
542 |
|
543 TSize CalculateRasterizedTextSize(const TDesC& aText, CFont* aFont) const; |
|
544 |
|
545 void InitL(CHuiCanvasTextImage& aTextImage, TSize& aTextsize); |
|
546 |
|
547 void DrawL(CHuiCanvasTextImage& aTextImage, TSize& aTextsize, TPoint& aRasterizedOffset); |
|
548 |
|
549 void UploadL(CHuiCanvasTextImage& aTextImage, TPoint& aRasterrizedOffset); |
|
550 |
|
551 private: |
|
552 |
|
553 TInt iFontHandle; |
|
554 CFbsBitGcFont* iFont; |
|
555 }; |
|
556 |
|
557 CHuiCanvasTextImageRasterizer::CHuiCanvasTextImageRasterizer() |
|
558 { |
|
559 } |
|
560 |
|
561 CHuiCanvasTextImageRasterizer::~CHuiCanvasTextImageRasterizer() |
|
562 { |
|
563 delete iFont; |
|
564 } |
|
565 |
|
566 TSize CHuiCanvasTextImageRasterizer::CalculateRasterizedTextSize(const TDesC& aText, CFont* aFont) const |
|
567 { |
|
568 CFont::TMeasureTextInput input; |
|
569 input.iFlags = CFont::TMeasureTextInput::EFVisualOrder; |
|
570 CFont::TMeasureTextOutput output; |
|
571 |
|
572 TInt textAdvance = aFont->MeasureText( aText, &input, &output ); |
|
573 |
|
574 TRect bounds = output.iBounds; |
|
575 bounds.iTl.iX = Min(bounds.iTl.iX, 0); |
|
576 bounds.iBr.iX = Max(bounds.iBr.iX, textAdvance); |
|
577 |
|
578 TSize textSize = TSize(bounds.Width(), aFont->FontMaxHeight()); |
|
579 |
|
580 const CAknLayoutFont* layoutFont = 0; |
|
581 |
|
582 if (CCoeEnv::Static()) |
|
583 { |
|
584 layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( aFont ); |
|
585 } |
|
586 |
|
587 if ( layoutFont ) |
|
588 { |
|
589 textSize.iHeight = aFont->HeightInPixels(); |
|
590 TInt textPaneHeight = layoutFont->TextPaneHeight(); |
|
591 TInt textPaneTopToBaseline = layoutFont->TextPaneTopToBaseline(); |
|
592 |
|
593 textSize.iHeight += textPaneHeight - textPaneTopToBaseline; |
|
594 textSize.iHeight += KHuiFontVerticalShiftInPixels; |
|
595 } |
|
596 else |
|
597 { |
|
598 textSize.iHeight = Max(textSize.iHeight, aFont->HeightInPixels()); |
|
599 textSize.iHeight += 3; // the best approximation - fails on big (>=72) fonts |
|
600 } |
|
601 |
|
602 return textSize; |
|
603 } |
|
604 |
|
605 |
|
606 void CHuiCanvasTextImageRasterizer::RasterizeL(CHuiCanvasTextImage& aTextImage) |
|
607 { |
|
608 TPoint rasterizedOffset(0, 0); |
|
609 |
|
610 if (aTextImage.iFontHandle && (iFontHandle != aTextImage.iFontHandle)) |
|
611 { |
|
612 delete iFont; |
|
613 iFont = NULL; |
|
614 |
|
615 // the font might have been duplicated earlier in order to |
|
616 // find out whether it is an outline font or not. As the CHuiCanvasTextImage |
|
617 // does not own the font pointer by it's member iFont, just copy the pointer |
|
618 // to the instance of this class.. |
|
619 if (aTextImage.iFont) |
|
620 { |
|
621 iFont = aTextImage.iFont; |
|
622 } |
|
623 else |
|
624 { |
|
625 // Font is cached as pointer because next text may same font and in that case |
|
626 // we are much faster as there is no need to do font duplication again. |
|
627 iFont = new (ELeave) CFbsBitGcFont(); |
|
628 iFontHandle = aTextImage.iFontHandle; |
|
629 TInt fontDuplicateErrorCode = iFont->Duplicate(iFontHandle); |
|
630 |
|
631 if (fontDuplicateErrorCode) |
|
632 { |
|
633 // Invalid handle which would panic inside fbsbitgc |
|
634 iFontHandle = 0; |
|
635 delete iFont; |
|
636 iFont = NULL; |
|
637 aTextImage.iFont = NULL; |
|
638 } |
|
639 else |
|
640 { |
|
641 // we need a reference to the font in CHuiCanvasTextImage aswell.. |
|
642 aTextImage.iFont = iFont; |
|
643 } |
|
644 } |
|
645 } |
|
646 |
|
647 if (iFont) |
|
648 { |
|
649 TSize textSize = TSize(0,0); |
|
650 TInt textAscent = 0; |
|
651 |
|
652 // If no max size is provided, we need to approximate the needed texture size. |
|
653 if (aTextImage.iTextBoxMaxSize == TSize(KMinTInt,KMinTInt)) |
|
654 { |
|
655 textSize = CalculateRasterizedTextSize(*aTextImage.iText, iFont); |
|
656 |
|
657 // To get most closest values for the font metrics we could try to cast |
|
658 // font into aknlayoutfont, but that does not seem to work when font is |
|
659 // duplicated trough handle. This solution is not accurate and results slightly |
|
660 // too large textures but avoids text clipping. |
|
661 TReal32 height = textSize.iHeight; |
|
662 textSize.iHeight = height * 1.2; |
|
663 textAscent = height * 0.9; |
|
664 |
|
665 // If rotated 90 degress, then flip width and heigths |
|
666 if (aTextImage.iAngle == 90 || aTextImage.iAngle == -90) |
|
667 { |
|
668 TSize horizontalTextSize = textSize; |
|
669 textSize.iWidth = horizontalTextSize.iHeight; |
|
670 textSize.iHeight = horizontalTextSize.iWidth; |
|
671 } |
|
672 |
|
673 // Since we modify the actual point where drawing is to happen |
|
674 // (so that image size gets minimized), we use rasterizedOffset to specify |
|
675 // offset we have used. That offset needs to be used when image of the text |
|
676 // is to be drawn because with these coordinates text goes exactly where it ´ |
|
677 // is supposed to go. |
|
678 if (aTextImage.iAngle == 90) |
|
679 { |
|
680 // Rotated clockwise |
|
681 rasterizedOffset.iX = textSize.iWidth-textAscent; |
|
682 } |
|
683 else if (aTextImage.iAngle == -90) |
|
684 { |
|
685 // Rotated anti clockwise |
|
686 rasterizedOffset.iX = textAscent; |
|
687 // Drawing happens upwards |
|
688 rasterizedOffset.iY = textSize.iHeight; |
|
689 } |
|
690 else |
|
691 { |
|
692 // No rotation, just drawn lower |
|
693 rasterizedOffset.iY = textAscent; |
|
694 } |
|
695 } |
|
696 else |
|
697 { |
|
698 // Clipping text box is provided, much easier this way. |
|
699 textSize = aTextImage.iTextBoxMaxSize; |
|
700 } |
|
701 |
|
702 // Setup gc parameters |
|
703 InitL(aTextImage, textSize); |
|
704 |
|
705 // Draw the text |
|
706 DrawL(aTextImage, textSize, rasterizedOffset); |
|
707 } |
|
708 |
|
709 // Upload content |
|
710 UploadL(aTextImage, rasterizedOffset); |
|
711 |
|
712 } |
|
713 |
|
714 void CHuiCanvasTextImageRasterizer::InitL(CHuiCanvasTextImage& aTextImage, TSize& aTextsize) |
|
715 { |
|
716 TFontUnderline underline = (TFontUnderline)aTextImage.iGcParams.iUnderline; |
|
717 TFontStrikethrough strikethrough = (TFontStrikethrough)aTextImage.iGcParams.iStrikethrough; |
|
718 CGraphicsContext::TBrushStyle brushstyle = (CGraphicsContext::TBrushStyle)aTextImage.iGcParams.iBrushStyle; |
|
719 CGraphicsContext::TPenStyle penstyle = (CGraphicsContext::TPenStyle)aTextImage.iGcParams.iPenStyle; |
|
720 TInt shadowmode = aTextImage.iGcParams.iShadowMode; // TODO: Is this even needed for texts ? |
|
721 TBool outlinefont = iFont->FontSpecInTwips().iFontStyle.IsEffectOn(FontEffect::EOutline); |
|
722 if (IsSeparateTextMaskUsed()) |
|
723 { |
|
724 iTempMask->Resize(aTextsize); |
|
725 iTempMaskDevice->Resize(aTextsize); |
|
726 |
|
727 delete iTempMaskGc; |
|
728 iTempMaskGc = NULL; |
|
729 User::LeaveIfError(iTempMaskDevice->CreateContext(iTempMaskGc)); |
|
730 |
|
731 // Mask bitmap, this defines the shape of the text. |
|
732 iTempMaskGc->SetBrushColor(KRgbBlack); |
|
733 iTempMaskGc->Clear(); |
|
734 iTempMaskGc->SetPenColor(KRgbWhite); |
|
735 |
|
736 // We dont call the UseFont() variant with handle param because it is slower |
|
737 iTempMaskGc->UseFont(iFont); |
|
738 |
|
739 // Set correct gc settings |
|
740 iTempMaskGc->SetPenStyle(penstyle); |
|
741 iTempMaskGc->SetBrushStyle(brushstyle); |
|
742 iTempMaskGc->SetUnderlineStyle(underline); |
|
743 iTempMaskGc->SetStrikethroughStyle(strikethrough); |
|
744 iTempMaskGc->SetShadowMode(shadowmode); |
|
745 } |
|
746 |
|
747 iTempBitmap->Resize(aTextsize); |
|
748 iTempBitmapDevice->Resize(aTextsize); |
|
749 |
|
750 delete iTempBitmapGc; |
|
751 iTempBitmapGc = NULL; |
|
752 User::LeaveIfError(iTempBitmapDevice->CreateContext(iTempBitmapGc)); |
|
753 |
|
754 if (IsSeparateTextMaskUsed()) |
|
755 { |
|
756 // Just fill with correct color, text shape comes from mask |
|
757 if (KHuiCanvasTextUseColorModulation) |
|
758 { |
|
759 iTempBitmapGc->SetPenColor(KRgbWhite); |
|
760 } |
|
761 else |
|
762 { |
|
763 iTempBitmapGc->SetPenColor(aTextImage.iGcParams.iPenColor); |
|
764 } |
|
765 |
|
766 iTempBitmapGc->SetBrushColor(aTextImage.iGcParams.iBrushColor); |
|
767 iTempBitmapGc->Clear(); |
|
768 } |
|
769 else |
|
770 { |
|
771 // First clear |
|
772 TRgb clearColor(KRgbBlack); |
|
773 clearColor.SetAlpha(0); |
|
774 iTempBitmapGc->SetPenColor(clearColor); |
|
775 iTempBitmapGc->SetBrushColor(clearColor); |
|
776 if (iTempBitmap->DisplayMode() == EColor16MA) |
|
777 { |
|
778 iTempBitmapGc->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); |
|
779 } |
|
780 else |
|
781 { |
|
782 iTempBitmapGc->SetDrawMode(CGraphicsContext::EDrawModePEN); |
|
783 } |
|
784 |
|
785 iTempBitmapGc->Clear(); |
|
786 |
|
787 // Set correct gc settings |
|
788 if (!outlinefont && KHuiCanvasTextUseColorModulation) |
|
789 { |
|
790 iTempBitmapGc->SetPenColor(KRgbWhite); |
|
791 } |
|
792 else |
|
793 { |
|
794 iTempBitmapGc->SetPenColor(aTextImage.iGcParams.iPenColor); |
|
795 iTempBitmapGc->SetBrushColor(aTextImage.iGcParams.iBrushColor); |
|
796 } |
|
797 |
|
798 iTempBitmapGc->SetPenStyle(penstyle); |
|
799 if (!outlinefont) |
|
800 { |
|
801 iTempBitmapGc->SetBrushStyle( CGraphicsContext::ENullBrush ); |
|
802 } |
|
803 else |
|
804 { |
|
805 iTempBitmapGc->SetBrushStyle( brushstyle ); |
|
806 } |
|
807 |
|
808 iTempBitmapGc->SetUnderlineStyle(underline); |
|
809 iTempBitmapGc->SetStrikethroughStyle(strikethrough); |
|
810 iTempBitmapGc->SetShadowMode(shadowmode); |
|
811 } |
|
812 |
|
813 // We dont call the UseFont() variant with handle param because it is slower |
|
814 iTempBitmapGc->UseFont(iFont); |
|
815 |
|
816 // Are we using color modulation, store info to entry |
|
817 aTextImage.iUseColorModulation = outlinefont ? EFalse : KHuiCanvasTextUseColorModulation; |
|
818 |
|
819 // Debug, enable this to see texture outlines. |
|
820 //iTempMaskGc->DrawRect(TRect(TPoint(0,0), textSize)); |
|
821 } |
|
822 |
|
823 void CHuiCanvasTextImageRasterizer::DrawL(CHuiCanvasTextImage& aTextImage, TSize& aTextsize, TPoint& aRasterizedOffset) |
|
824 { |
|
825 #ifdef SYMBIAN_BUILD_GCE |
|
826 CGraphicsContext::TTextParameters gcTextParams = *(CGraphicsContext::TTextParameters*)& aTextImage.iTextParams; |
|
827 #endif |
|
828 // Based on supplied params, select the approprite DrawText variant. |
|
829 TBool up = (aTextImage.iAngle == -90); |
|
830 if (aTextImage.iTextBoxMaxSize != TSize(KMinTInt,KMinTInt)) |
|
831 { |
|
832 if (aTextImage.iBaseLineOffset != KMinTInt) |
|
833 { |
|
834 CGraphicsContext::TTextAlign align = (CGraphicsContext::TTextAlign) aTextImage.iTextAlign; |
|
835 |
|
836 if (aTextImage.iTextWidth != KMinTInt) |
|
837 |
|
838 { |
|
839 if (aTextImage.iAngle == 0) |
|
840 { |
|
841 if (IsSeparateTextMaskUsed()) |
|
842 { |
|
843 iTempMaskGc->DrawText(*aTextImage.iText, |
|
844 #ifdef SYMBIAN_BUILD_GCE |
|
845 &gcTextParams, |
|
846 #endif |
|
847 TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, aTextImage.iTextWidth, align, aTextImage.iMargin); |
|
848 } |
|
849 else |
|
850 { |
|
851 // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode |
|
852 } |
|
853 |
|
854 iTempBitmapGc->DrawText(*aTextImage.iText, |
|
855 #ifdef SYMBIAN_BUILD_GCE |
|
856 &gcTextParams, |
|
857 #endif |
|
858 TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, aTextImage.iTextWidth, align, aTextImage.iMargin); |
|
859 } |
|
860 else |
|
861 { |
|
862 if (IsSeparateTextMaskUsed()) |
|
863 { |
|
864 iTempMaskGc->DrawTextVertical(*aTextImage.iText, |
|
865 #ifdef SYMBIAN_BUILD_GCE |
|
866 &gcTextParams, |
|
867 #endif |
|
868 TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, aTextImage.iTextWidth, up, align, aTextImage.iMargin); |
|
869 } |
|
870 else |
|
871 { |
|
872 // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode |
|
873 } |
|
874 iTempBitmapGc->DrawTextVertical(*aTextImage.iText, |
|
875 #ifdef SYMBIAN_BUILD_GCE |
|
876 &gcTextParams, |
|
877 #endif |
|
878 TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, aTextImage.iTextWidth, up, align, aTextImage.iMargin); |
|
879 } |
|
880 } |
|
881 else |
|
882 { |
|
883 if (aTextImage.iAngle == 0) |
|
884 { |
|
885 if (IsSeparateTextMaskUsed()) |
|
886 { |
|
887 iTempMaskGc->DrawText(*aTextImage.iText, |
|
888 #ifdef SYMBIAN_BUILD_GCE |
|
889 &gcTextParams, |
|
890 #endif |
|
891 TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, align, aTextImage.iMargin); |
|
892 } |
|
893 else |
|
894 { |
|
895 // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode |
|
896 } |
|
897 iTempBitmapGc->DrawText(*aTextImage.iText, |
|
898 #ifdef SYMBIAN_BUILD_GCE |
|
899 &gcTextParams, |
|
900 #endif |
|
901 TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, align, aTextImage.iMargin); |
|
902 } |
|
903 else |
|
904 { |
|
905 if (IsSeparateTextMaskUsed()) |
|
906 { |
|
907 iTempMaskGc->DrawTextVertical(*aTextImage.iText, |
|
908 #ifdef SYMBIAN_BUILD_GCE |
|
909 &gcTextParams, |
|
910 #endif |
|
911 TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, up, align, aTextImage.iMargin); |
|
912 } |
|
913 else |
|
914 { |
|
915 // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode |
|
916 } |
|
917 iTempBitmapGc->DrawTextVertical(*aTextImage.iText, |
|
918 #ifdef SYMBIAN_BUILD_GCE |
|
919 &gcTextParams, |
|
920 #endif |
|
921 TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, up, align, aTextImage.iMargin); |
|
922 } |
|
923 } |
|
924 } |
|
925 else |
|
926 { |
|
927 if (aTextImage.iAngle == 0) |
|
928 { |
|
929 if (IsSeparateTextMaskUsed()) |
|
930 { |
|
931 iTempMaskGc->DrawText(*aTextImage.iText, |
|
932 #ifdef SYMBIAN_BUILD_GCE |
|
933 &gcTextParams, |
|
934 #endif |
|
935 TRect(TPoint(0,0), aTextsize) ); |
|
936 } |
|
937 else |
|
938 { |
|
939 // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode |
|
940 } |
|
941 |
|
942 iTempBitmapGc->DrawText(*aTextImage.iText, |
|
943 #ifdef SYMBIAN_BUILD_GCE |
|
944 &gcTextParams, |
|
945 #endif |
|
946 TRect(TPoint(0,0), aTextsize)); |
|
947 } |
|
948 else |
|
949 { |
|
950 if (IsSeparateTextMaskUsed()) |
|
951 { |
|
952 iTempMaskGc->DrawTextVertical(*aTextImage.iText, |
|
953 #ifdef SYMBIAN_BUILD_GCE |
|
954 &gcTextParams, |
|
955 #endif |
|
956 TRect(TPoint(0,0), aTextsize), up ); |
|
957 } |
|
958 else |
|
959 { |
|
960 // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode |
|
961 } |
|
962 |
|
963 iTempBitmapGc->DrawTextVertical(*aTextImage.iText, |
|
964 #ifdef SYMBIAN_BUILD_GCE |
|
965 &gcTextParams, |
|
966 #endif |
|
967 TRect(TPoint(0,0), aTextsize), up); |
|
968 } |
|
969 } |
|
970 } |
|
971 else |
|
972 { |
|
973 if (aTextImage.iAngle == 0) |
|
974 { |
|
975 if (IsSeparateTextMaskUsed()) |
|
976 { |
|
977 iTempMaskGc->DrawText(*aTextImage.iText, |
|
978 #ifdef SYMBIAN_BUILD_GCE |
|
979 &gcTextParams, |
|
980 #endif |
|
981 aRasterizedOffset); |
|
982 } |
|
983 else |
|
984 { |
|
985 // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode |
|
986 } |
|
987 |
|
988 iTempBitmapGc->DrawText(*aTextImage.iText, |
|
989 #ifdef SYMBIAN_BUILD_GCE |
|
990 &gcTextParams, |
|
991 #endif |
|
992 aRasterizedOffset); |
|
993 } |
|
994 else |
|
995 { |
|
996 if (IsSeparateTextMaskUsed()) |
|
997 { |
|
998 iTempMaskGc->DrawTextVertical(*aTextImage.iText, |
|
999 #ifdef SYMBIAN_BUILD_GCE |
|
1000 &gcTextParams, |
|
1001 #endif |
|
1002 aRasterizedOffset, up); |
|
1003 } |
|
1004 else |
|
1005 { |
|
1006 // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode |
|
1007 } |
|
1008 |
|
1009 iTempBitmapGc->DrawTextVertical(*aTextImage.iText, |
|
1010 #ifdef SYMBIAN_BUILD_GCE |
|
1011 &gcTextParams, |
|
1012 #endif |
|
1013 aRasterizedOffset, up); |
|
1014 } |
|
1015 } |
|
1016 } |
|
1017 |
|
1018 void CHuiCanvasTextImageRasterizer::UploadL(CHuiCanvasTextImage& aTextImage, TPoint& aRasterizedOffset) |
|
1019 { |
|
1020 // Upload bitmap content...this may be slow depending on used HW acceleration ! |
|
1021 |
|
1022 TSize colorBitmapSize = iTempBitmap->SizeInPixels(); |
|
1023 TSize maskBitmapSize = IsSeparateTextMaskUsed() ? iTempMask->SizeInPixels() : colorBitmapSize; |
|
1024 CFbsBitmap* textColorBitmap = iTempBitmap; |
|
1025 CFbsBitmap* textMaskBitmap = IsSeparateTextMaskUsed() ? iTempMask : NULL; |
|
1026 |
|
1027 |
|
1028 if (maskBitmapSize.iWidth > 0 && |
|
1029 maskBitmapSize.iHeight > 0 && |
|
1030 colorBitmapSize.iWidth > 0 && |
|
1031 colorBitmapSize.iHeight > 0) |
|
1032 { |
|
1033 // TODO: For BitGdi it might be good to use direct upload, but it would require changes such as |
|
1034 // making new textColorBitmap, textMaskBitmap everytime. |
|
1035 THuiTextureUploadFlags uploadFlags = THuiTextureUploadFlags(EHuiTextureUploadFlagDoNotRetainResolution | EHuiTextureUploadFlagRetainColorDepth); |
|
1036 |
|
1037 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
1038 TTime startTime; |
|
1039 startTime.UniversalTime(); |
|
1040 #endif |
|
1041 |
|
1042 aTextImage.iRasterizationOffset = aRasterizedOffset; |
|
1043 |
|
1044 CHuiTexture* texture = aTextImage.iTexture; |
|
1045 texture->UploadL(*textColorBitmap, textMaskBitmap, uploadFlags); |
|
1046 |
|
1047 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
1048 TTime endTime; |
|
1049 endTime.UniversalTime(); |
|
1050 TInt uploadTimeInMilliSeconds = endTime.MicroSecondsFrom( startTime ).Int64()/1000; |
|
1051 RDebug::Print(_L(">>> CHuiCanvasTextImageRasterizer::UpdateCachedTextL: Upload of %ix%i %S took %i ms"), |
|
1052 texture->Size().iWidth, |
|
1053 texture->Size().iHeight, |
|
1054 aTextImage.iText, |
|
1055 uploadTimeInMilliSeconds); |
|
1056 #endif |
|
1057 } |
|
1058 } |
|
1059 |
|
1060 |
|
1061 NONSHARABLE_CLASS( CHuiCanvasGraphicImageRasterizer ) : public CHuiCanvasImageRasterizer |
|
1062 { |
|
1063 public: |
|
1064 |
|
1065 CHuiCanvasGraphicImageRasterizer(); |
|
1066 |
|
1067 ~CHuiCanvasGraphicImageRasterizer(); |
|
1068 |
|
1069 void ConstructL(TBool aUseGray256 = EFalse); |
|
1070 |
|
1071 void RasterizeL(CHuiCanvasGraphicImage& aImage); |
|
1072 |
|
1073 private: |
|
1074 }; |
|
1075 |
|
1076 CHuiCanvasGraphicImageRasterizer::CHuiCanvasGraphicImageRasterizer() |
|
1077 { |
|
1078 } |
|
1079 |
|
1080 CHuiCanvasGraphicImageRasterizer::~CHuiCanvasGraphicImageRasterizer() |
|
1081 { |
|
1082 } |
|
1083 |
|
1084 void CHuiCanvasGraphicImageRasterizer::ConstructL(TBool /*aUseGray256*/) |
|
1085 { |
|
1086 } |
|
1087 |
|
1088 void CHuiCanvasGraphicImageRasterizer::RasterizeL(CHuiCanvasGraphicImage& aImage) |
|
1089 { |
|
1090 CFbsBitmap* bitmap = NULL; |
|
1091 CFbsBitmap* mask = NULL; |
|
1092 |
|
1093 TInt bitmapTouchCount = KHuiInitialBitmapTouchCount; |
|
1094 TInt maskTouchCount = KHuiInitialBitmapTouchCount; |
|
1095 |
|
1096 #ifdef SYMBIAN_BUILD_GCE |
|
1097 TBool volatileBitmapOrMask = EFalse; |
|
1098 #else |
|
1099 TBool volatileBitmapOrMask = ETrue; |
|
1100 #endif |
|
1101 |
|
1102 TBool originalMaskUsed = ETrue; |
|
1103 |
|
1104 |
|
1105 TInt bitmapHandle = aImage.iBitmapHandle; |
|
1106 TInt maskHandle = aImage.iMaskHandle; |
|
1107 TBool invertMask = aImage.iInvertedMask; |
|
1108 TPoint maskOriginPoint = aImage.iMaskOriginPoint; |
|
1109 |
|
1110 if (!bitmapHandle) |
|
1111 { |
|
1112 return; |
|
1113 } |
|
1114 |
|
1115 // Lets see if we have already cached the pointer... |
|
1116 if (aImage.iBitmap) |
|
1117 { |
|
1118 // ...yes lets use it |
|
1119 bitmap = aImage.iBitmap; |
|
1120 } |
|
1121 else |
|
1122 { |
|
1123 // ...no, so we need to duplicate the handle |
|
1124 bitmap = new(ELeave)CFbsBitmap; |
|
1125 bitmap->Duplicate(bitmapHandle); |
|
1126 if (bitmap) |
|
1127 { |
|
1128 if (KHuiCanvasKeepBitmapPointer) |
|
1129 { |
|
1130 aImage.iBitmap = bitmap; |
|
1131 } |
|
1132 else |
|
1133 { |
|
1134 CleanupStack::PushL(bitmap); |
|
1135 } |
|
1136 } |
|
1137 |
|
1138 } |
|
1139 |
|
1140 #ifdef SYMBIAN_BUILD_GCE |
|
1141 if (bitmap) |
|
1142 { |
|
1143 bitmapTouchCount = bitmap->TouchCount(); |
|
1144 volatileBitmapOrMask |= bitmap->IsVolatile(); |
|
1145 } |
|
1146 #endif |
|
1147 |
|
1148 // Mask is optional |
|
1149 if (maskHandle) |
|
1150 { |
|
1151 // Lets see if we have already cached the pointer... |
|
1152 if (aImage.iMask) |
|
1153 { |
|
1154 // ...yes lets use it |
|
1155 mask = aImage.iMask; |
|
1156 } |
|
1157 else |
|
1158 { |
|
1159 // ...no, so we need to duplicate the handle |
|
1160 mask = new(ELeave)CFbsBitmap; |
|
1161 mask->Duplicate(maskHandle); |
|
1162 if (mask) |
|
1163 { |
|
1164 if (KHuiCanvasKeepBitmapPointer) |
|
1165 { |
|
1166 aImage.iMask = mask; |
|
1167 } |
|
1168 else |
|
1169 { |
|
1170 CleanupStack::PushL(mask); |
|
1171 } |
|
1172 } |
|
1173 } |
|
1174 |
|
1175 #ifdef SYMBIAN_BUILD_GCE |
|
1176 if (mask) |
|
1177 { |
|
1178 maskTouchCount = mask->TouchCount(); |
|
1179 volatileBitmapOrMask |= mask->IsVolatile(); |
|
1180 } |
|
1181 #endif |
|
1182 |
|
1183 // If mask is defined not to be inverted, |
|
1184 // we must invert it because toolkit assumes they are always inverted. Huh. |
|
1185 #ifdef __NVG |
|
1186 // Inverting masks is done ONLY for non-extended bitmaps! |
|
1187 if (bitmap->ExtendedBitmapType() == KNullUid) // => Bitmap isn't extended |
|
1188 { |
|
1189 #endif |
|
1190 if (invertMask && mask->DisplayMode() == EGray2) |
|
1191 { |
|
1192 CFbsBitmap* invertedMask = CreateInvertedMaskL(*mask); |
|
1193 |
|
1194 // If we are not using stored pointer, delete it |
|
1195 if (mask != aImage.iMask) |
|
1196 { |
|
1197 CleanupStack::PopAndDestroy(mask); |
|
1198 } |
|
1199 |
|
1200 mask = invertedMask; |
|
1201 CleanupStack::PushL(mask); |
|
1202 originalMaskUsed = EFalse; |
|
1203 } |
|
1204 |
|
1205 // Upload expects mask to begin always at TPoint(0,0), so if mask |
|
1206 // offset is defined we re-create mask with the given new |
|
1207 // offset. Note that it might be a good idea to combine this op |
|
1208 // with mask inversion op, but we assume that these are not really used |
|
1209 // very often, even more rarely together. |
|
1210 if (maskOriginPoint != TPoint(0,0)) |
|
1211 { |
|
1212 CFbsBitmap* movedMask = CreateMovedMaskL(*mask, maskOriginPoint); |
|
1213 |
|
1214 // If we are not using stored pointer, delete it |
|
1215 if (mask != aImage.iMask) |
|
1216 { |
|
1217 CleanupStack::PopAndDestroy(mask); |
|
1218 } |
|
1219 mask = movedMask; |
|
1220 CleanupStack::PushL(mask); |
|
1221 originalMaskUsed = EFalse; |
|
1222 } |
|
1223 #ifdef __NVG |
|
1224 } |
|
1225 #endif |
|
1226 } |
|
1227 |
|
1228 // Bitmap has changed, must be updated ? |
|
1229 TBool touchCountChanged = EFalse; |
|
1230 touchCountChanged |= volatileBitmapOrMask; |
|
1231 touchCountChanged |= (aImage.iBitmapTouchCount != bitmapTouchCount); |
|
1232 touchCountChanged |= (aImage.iMaskTouchCount != maskTouchCount); |
|
1233 |
|
1234 // Is touch count check enabled ? |
|
1235 TBool touchCountCheckEnabled = CHuiStatic::Env().CanvasTextureCache().IsTouchCountCheckEnabled(); |
|
1236 |
|
1237 // Has it old content at all ? |
|
1238 TBool hasContent = aImage.iTexture->HasContent(); |
|
1239 |
|
1240 if (!hasContent || (touchCountCheckEnabled && touchCountChanged)) |
|
1241 { |
|
1242 // Upload bitmap content...this may be slow depending on used HW acceleration ! |
|
1243 if (bitmap->SizeInPixels().iWidth > 0 && |
|
1244 bitmap->SizeInPixels().iHeight > 0 && |
|
1245 (!mask || (mask->SizeInPixels().iWidth > 0 && mask->SizeInPixels().iHeight))) |
|
1246 { |
|
1247 // EHuiTextureUploadFlagDoNotRetainResolution should be removed when |
|
1248 // texturecoordinates with segmented textures work. |
|
1249 // This flag causes ugly scaling to happen with small textures. |
|
1250 THuiTextureUploadFlags uploadFlags = THuiTextureUploadFlags(EHuiTextureUploadFlagDoNotRetainResolution | EHuiTextureUploadFlagRetainColorDepth); |
|
1251 |
|
1252 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
1253 TTime startTime; |
|
1254 startTime.UniversalTime(); |
|
1255 #endif |
|
1256 |
|
1257 CHuiTexture* texture = aImage.iTexture; |
|
1258 texture->UploadL(*bitmap, mask, uploadFlags); |
|
1259 |
|
1260 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
1261 TTime endTime; |
|
1262 endTime.UniversalTime(); |
|
1263 TInt uploadTimeInMilliSeconds = endTime.MicroSecondsFrom( startTime ).Int64()/1000; |
|
1264 |
|
1265 if (volatileBitmapOrMask) |
|
1266 { |
|
1267 RDebug::Print(_L(">>> CHuiCanvasGraphicImageRasterizer::UpdateCachedImageL: Reason for uploading is volatileBitmapOrMask")); |
|
1268 } |
|
1269 |
|
1270 if (aImage.iBitmapTouchCount != bitmapTouchCount) |
|
1271 { |
|
1272 RDebug::Print(_L(">>> CHuiCanvasGraphicImageRasterizer::UpdateCachedImageL: Reason for uploading is iBitmapTouchCount %i, old was %i "), bitmapTouchCount, aImage.iBitmapTouchCount); |
|
1273 } |
|
1274 |
|
1275 if (aImage.iMaskTouchCount != maskTouchCount) |
|
1276 { |
|
1277 RDebug::Print(_L(">>> CHuiCanvasGraphicImageRasterizer::UpdateCachedImageL: Reason for uploading is iMaskTouchCount %i, old was %i "), maskTouchCount, aImage.iMaskTouchCount); |
|
1278 } |
|
1279 |
|
1280 RDebug::Print(_L(">>> CHuiCanvasGraphicImageRasterizer::UpdateCachedImageL: Upload of %ix%i %i+%i took %i ms"), |
|
1281 texture->Size().iWidth, |
|
1282 texture->Size().iHeight, |
|
1283 aImage.iBitmapHandle, |
|
1284 aImage.iMaskHandle, |
|
1285 uploadTimeInMilliSeconds); |
|
1286 #endif |
|
1287 } |
|
1288 |
|
1289 #ifdef SYMBIAN_BUILD_GCE |
|
1290 // Texture upload itself must not modify bitmap or mask touch count. |
|
1291 // Otherwise, it's impossible to detect client data access |
|
1292 // (since there is not necessarily any synchronisation between client & alf). |
|
1293 |
|
1294 aImage.iBitmapTouchCount = bitmapTouchCount; |
|
1295 aImage.iMaskTouchCount = maskTouchCount; |
|
1296 #endif |
|
1297 } |
|
1298 else |
|
1299 { |
|
1300 if (touchCountChanged && !touchCountCheckEnabled) |
|
1301 { |
|
1302 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
1303 RDebug::Print(_L(">>> CHuiCanvasGraphicImageRasterizer::UpdateCachedImageL: skipping uploading because touchcount check is disabled")); |
|
1304 #endif |
|
1305 } |
|
1306 } |
|
1307 |
|
1308 // If we are not using stored pointer, delete it |
|
1309 if (mask && (mask != aImage.iMask)) |
|
1310 { |
|
1311 CleanupStack::PopAndDestroy(mask); |
|
1312 mask = NULL; |
|
1313 } |
|
1314 |
|
1315 // If we are not using stored pointer, delete it |
|
1316 if (bitmap && (bitmap != aImage.iBitmap)) |
|
1317 { |
|
1318 CleanupStack::PopAndDestroy(bitmap); |
|
1319 bitmap = NULL; |
|
1320 } |
|
1321 } |
|
1322 |
|
1323 |
|
1324 |
|
1325 NONSHARABLE_CLASS( CHuiCanvasCombinedGraphicImageRasterizer ) : public CHuiCanvasImageRasterizer |
|
1326 { |
|
1327 public: |
|
1328 |
|
1329 CHuiCanvasCombinedGraphicImageRasterizer(); |
|
1330 |
|
1331 ~CHuiCanvasCombinedGraphicImageRasterizer(); |
|
1332 |
|
1333 void RasterizeL(CHuiCanvasGraphicImage& aImage); |
|
1334 |
|
1335 private: |
|
1336 |
|
1337 void InitL(CHuiCanvasGraphicImage& aImage); |
|
1338 |
|
1339 void DrawL(CHuiCanvasGraphicImage& aImage); |
|
1340 |
|
1341 void UploadL(CHuiCanvasGraphicImage& aImage); |
|
1342 |
|
1343 }; |
|
1344 |
|
1345 CHuiCanvasCombinedGraphicImageRasterizer::CHuiCanvasCombinedGraphicImageRasterizer() |
|
1346 { |
|
1347 } |
|
1348 |
|
1349 CHuiCanvasCombinedGraphicImageRasterizer::~CHuiCanvasCombinedGraphicImageRasterizer() |
|
1350 { |
|
1351 } |
|
1352 |
|
1353 void CHuiCanvasCombinedGraphicImageRasterizer::RasterizeL(CHuiCanvasGraphicImage& aImage) |
|
1354 { |
|
1355 // First check the bitmaps |
|
1356 TBool bitmapsChanged = EFalse; |
|
1357 for (TInt i=0; i<aImage.iSubImages.Count(); i++) |
|
1358 { |
|
1359 // Lets see if we have already cached the pointer... |
|
1360 if (!aImage.iSubImages[i].iBitmap) |
|
1361 { |
|
1362 // ...no we must duplicate handle |
|
1363 if (aImage.iSubImages[i].iBitmapHandle) |
|
1364 { |
|
1365 aImage.iSubImages[i].iBitmap = new (ELeave) CFbsBitmap; |
|
1366 aImage.iSubImages[i].iBitmap->Duplicate(aImage.iSubImages[i].iBitmapHandle); |
|
1367 } |
|
1368 } |
|
1369 |
|
1370 if (!aImage.iSubImages[i].iMask) |
|
1371 { |
|
1372 // Lets see if we have already cached the pointer... |
|
1373 if (aImage.iSubImages[i].iMaskHandle) |
|
1374 { |
|
1375 aImage.iSubImages[i].iMask = new (ELeave) CFbsBitmap; |
|
1376 aImage.iSubImages[i].iMask->Duplicate(aImage.iSubImages[i].iMaskHandle); |
|
1377 } |
|
1378 } |
|
1379 |
|
1380 if (aImage.iSubImages[i].iBitmap) |
|
1381 { |
|
1382 bitmapsChanged |= (aImage.iSubImages[i].iBitmapTouchCount != aImage.iSubImages[i].iBitmap->TouchCount()); |
|
1383 } |
|
1384 |
|
1385 if (aImage.iSubImages[i].iMask) |
|
1386 { |
|
1387 bitmapsChanged |= (aImage.iSubImages[i].iMaskTouchCount != aImage.iSubImages[i].iMask->TouchCount()); |
|
1388 } |
|
1389 } |
|
1390 |
|
1391 if (bitmapsChanged) |
|
1392 { |
|
1393 InitL(aImage); |
|
1394 |
|
1395 DrawL(aImage); |
|
1396 |
|
1397 UploadL(aImage); |
|
1398 |
|
1399 // Touch counts updated after upload in case upload changes the count ? |
|
1400 for (TInt i=0; i<aImage.iSubImages.Count(); i++) |
|
1401 { |
|
1402 if (aImage.iSubImages[i].iBitmap) |
|
1403 aImage.iSubImages[i].iBitmapTouchCount = aImage.iSubImages[i].iBitmap->TouchCount(); |
|
1404 |
|
1405 if (aImage.iSubImages[i].iMask) |
|
1406 aImage.iSubImages[i].iMaskTouchCount = aImage.iSubImages[i].iMask->TouchCount(); |
|
1407 } |
|
1408 } |
|
1409 |
|
1410 if (!KHuiCanvasKeepBitmapPointer) |
|
1411 { |
|
1412 for (TInt i=0; i<aImage.iSubImages.Count(); i++) |
|
1413 { |
|
1414 delete aImage.iSubImages[i].iBitmap; |
|
1415 aImage.iSubImages[i].iBitmap = NULL; |
|
1416 |
|
1417 delete aImage.iSubImages[i].iMask; |
|
1418 aImage.iSubImages[i].iMask = NULL; |
|
1419 } |
|
1420 } |
|
1421 } |
|
1422 |
|
1423 |
|
1424 void CHuiCanvasCombinedGraphicImageRasterizer::InitL(CHuiCanvasGraphicImage& aImage) |
|
1425 { |
|
1426 if (IsSeparateTextMaskUsed()) |
|
1427 { |
|
1428 iTempMask->Resize(aImage.iImageSize); |
|
1429 iTempMaskDevice->Resize(aImage.iImageSize); |
|
1430 |
|
1431 delete iTempMaskGc; |
|
1432 iTempMaskGc = NULL; |
|
1433 User::LeaveIfError(iTempMaskDevice->CreateContext(iTempMaskGc)); |
|
1434 |
|
1435 iTempMaskGc->Reset(); |
|
1436 iTempMaskGc->SetBrushColor(KRgbBlack); |
|
1437 iTempMaskGc->Clear(); |
|
1438 iTempMaskGc->SetPenColor(KRgbWhite); |
|
1439 } |
|
1440 |
|
1441 iTempBitmap->Resize(aImage.iImageSize); |
|
1442 iTempBitmapDevice->Resize(aImage.iImageSize); |
|
1443 |
|
1444 delete iTempBitmapGc; |
|
1445 iTempBitmapGc = NULL; |
|
1446 User::LeaveIfError(iTempBitmapDevice->CreateContext(iTempBitmapGc)); |
|
1447 |
|
1448 if (IsSeparateTextMaskUsed()) |
|
1449 { |
|
1450 TRgb clearColor(KRgbWhite); |
|
1451 clearColor.SetAlpha(0); |
|
1452 iTempBitmapGc->SetPenColor(clearColor); |
|
1453 iTempBitmapGc->SetBrushColor(clearColor); |
|
1454 iTempBitmapGc->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); |
|
1455 iTempBitmapGc->Clear(); |
|
1456 iTempBitmapGc->SetPenColor(KRgbWhite); |
|
1457 |
|
1458 iTempMaskGc->SetPenColor(clearColor); |
|
1459 iTempMaskGc->SetBrushColor(clearColor); |
|
1460 iTempMaskGc->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); |
|
1461 iTempMaskGc->Clear(); |
|
1462 iTempMaskGc->SetPenColor(KRgbWhite); |
|
1463 } |
|
1464 else |
|
1465 { |
|
1466 // First clear |
|
1467 TRgb clearColor(KRgbWhite); |
|
1468 clearColor.SetAlpha(0); |
|
1469 iTempBitmapGc->SetPenColor(clearColor); |
|
1470 iTempBitmapGc->SetBrushColor(clearColor); |
|
1471 iTempBitmapGc->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); |
|
1472 iTempBitmapGc->Clear(); |
|
1473 iTempBitmapGc->SetPenColor(KRgbWhite); |
|
1474 } |
|
1475 } |
|
1476 |
|
1477 void CHuiCanvasCombinedGraphicImageRasterizer::DrawL(CHuiCanvasGraphicImage& aImage) |
|
1478 { |
|
1479 for (TInt i=0; i<aImage.iSubImages.Count(); i++) |
|
1480 { |
|
1481 CFbsBitmap* bitmap = aImage.iSubImages[i].iBitmap; |
|
1482 CFbsBitmap* mask = aImage.iSubImages[i].iMask; |
|
1483 TPoint point = aImage.iSubImages[i].iCombinedBitmapPoint; |
|
1484 |
|
1485 if (bitmap) |
|
1486 { |
|
1487 if (IsSeparateTextMaskUsed()) |
|
1488 { |
|
1489 TRect sourceRect = TRect(TPoint(0,0), bitmap->SizeInPixels()); |
|
1490 if (bitmap) |
|
1491 { |
|
1492 iTempBitmapGc->BitBlt(point, bitmap); |
|
1493 } |
|
1494 if (mask) |
|
1495 { |
|
1496 iTempMaskGc->BitBlt(point, mask); |
|
1497 } |
|
1498 } |
|
1499 else |
|
1500 { |
|
1501 TRect sourceRect = TRect(TPoint(0,0), bitmap->SizeInPixels()); |
|
1502 if (mask) |
|
1503 { |
|
1504 TBool invertMask = (mask->DisplayMode() == EGray256); |
|
1505 iTempBitmapGc->BitBltMasked(point, bitmap, sourceRect, mask, invertMask); |
|
1506 } |
|
1507 else |
|
1508 { |
|
1509 iTempBitmapGc->BitBlt(point, bitmap); |
|
1510 } |
|
1511 } |
|
1512 } |
|
1513 } |
|
1514 } |
|
1515 |
|
1516 void CHuiCanvasCombinedGraphicImageRasterizer::UploadL(CHuiCanvasGraphicImage& aImage) |
|
1517 { |
|
1518 CFbsBitmap* mask = IsSeparateTextMaskUsed() ? iTempMask : NULL; |
|
1519 |
|
1520 // Upload bitmap content...this may be slow depending on used HW acceleration ! |
|
1521 if (iTempBitmap->SizeInPixels().iWidth > 0 && |
|
1522 iTempBitmap->SizeInPixels().iHeight > 0 && |
|
1523 (!mask || (mask->SizeInPixels().iWidth > 0 && mask->SizeInPixels().iHeight))) |
|
1524 { |
|
1525 // EHuiTextureUploadFlagDoNotRetainResolution should be removed when |
|
1526 // texturecoordinates with segmented textures work. |
|
1527 // This flag causes ugly scaling to happen with small textures. |
|
1528 THuiTextureUploadFlags uploadFlags = THuiTextureUploadFlags(EHuiTextureUploadFlagDoNotRetainResolution | EHuiTextureUploadFlagRetainColorDepth); |
|
1529 |
|
1530 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
1531 TTime startTime; |
|
1532 startTime.UniversalTime(); |
|
1533 #endif |
|
1534 |
|
1535 CHuiTexture* texture = aImage.iTexture; |
|
1536 texture->UploadL(*iTempBitmap, mask, uploadFlags); |
|
1537 |
|
1538 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
1539 TTime endTime; |
|
1540 endTime.UniversalTime(); |
|
1541 TInt uploadTimeInMilliSeconds = endTime.MicroSecondsFrom( startTime ).Int64()/1000; |
|
1542 |
|
1543 RDebug::Print(_L(">>> CHuiCanvasCombinedGraphicImageRasterizer::UploadCombinedImageL: Upload of %ix%i %i+%i took %i ms"), |
|
1544 texture->Size().iWidth, |
|
1545 texture->Size().iHeight, |
|
1546 aImage.iBitmapHandle, |
|
1547 aImage.iMaskHandle, |
|
1548 uploadTimeInMilliSeconds); |
|
1549 #endif |
|
1550 } |
|
1551 } |
|
1552 // --------------------------------------------------------------------------- |
|
1553 // |
|
1554 // --------------------------------------------------------------------------- |
|
1555 // |
|
1556 TInt ImageTimeOrderFunc(const CHuiCanvasGraphicImage& aFirst, const CHuiCanvasGraphicImage& aSecond) |
|
1557 { |
|
1558 if (aFirst.iLastUsed < aSecond.iLastUsed) |
|
1559 { |
|
1560 return -1; // less than |
|
1561 } |
|
1562 else if (aFirst.iLastUsed > aSecond.iLastUsed) |
|
1563 { |
|
1564 return 1; // more than |
|
1565 } |
|
1566 else |
|
1567 { |
|
1568 return 0; |
|
1569 } |
|
1570 } |
|
1571 |
|
1572 // --------------------------------------------------------------------------- |
|
1573 // |
|
1574 // --------------------------------------------------------------------------- |
|
1575 // |
|
1576 TInt TextTimeOrderFunc(const CHuiCanvasTextImage& aFirst, const CHuiCanvasTextImage& aSecond) |
|
1577 { |
|
1578 if (aFirst.iLastUsed < aSecond.iLastUsed) |
|
1579 { |
|
1580 return -1; // less than |
|
1581 } |
|
1582 else if (aFirst.iLastUsed > aSecond.iLastUsed) |
|
1583 { |
|
1584 return 1; // more than |
|
1585 } |
|
1586 else |
|
1587 { |
|
1588 return 0; |
|
1589 } |
|
1590 } |
|
1591 |
|
1592 // --------------------------------------------------------------------------- |
|
1593 // |
|
1594 // --------------------------------------------------------------------------- |
|
1595 // |
|
1596 TInt RenderBufferTimeOrderFunc(const CHuiCanvasRenderBufferImage& aFirst, const CHuiCanvasRenderBufferImage& aSecond) |
|
1597 { |
|
1598 if (aFirst.iLastUsed < aSecond.iLastUsed) |
|
1599 { |
|
1600 return -1; // less than |
|
1601 } |
|
1602 else if (aFirst.iLastUsed > aSecond.iLastUsed) |
|
1603 { |
|
1604 return 1; // more than |
|
1605 } |
|
1606 else |
|
1607 { |
|
1608 return 0; |
|
1609 } |
|
1610 } |
|
1611 |
|
1612 // --------------------------------------------------------------------------- |
|
1613 // |
|
1614 // --------------------------------------------------------------------------- |
|
1615 // |
|
1616 TInt GcImageOrderFunc(const THuiCachedGcParams& /*aFirst*/, const THuiCachedGcParams& /*aSecond*/) |
|
1617 { |
|
1618 return 0; // equal enough, note that we don't check every field |
|
1619 } |
|
1620 |
|
1621 |
|
1622 // --------------------------------------------------------------------------- |
|
1623 // |
|
1624 // --------------------------------------------------------------------------- |
|
1625 // |
|
1626 TInt GcTextOrderFunc(const THuiCachedGcParams& aFirst, const THuiCachedGcParams& aSecond) |
|
1627 { |
|
1628 if (!KHuiCanvasTextUseColorModulation) |
|
1629 { |
|
1630 if (aFirst.iPenColor.Value() < aSecond.iPenColor.Value()) |
|
1631 { |
|
1632 return -1; // less than |
|
1633 } |
|
1634 else if (aFirst.iPenColor.Value() > aSecond.iPenColor.Value()) |
|
1635 { |
|
1636 return 1; // more than |
|
1637 } |
|
1638 else |
|
1639 { |
|
1640 // For PC-lint |
|
1641 } |
|
1642 } |
|
1643 |
|
1644 if (aFirst.iPenStyle < aSecond.iPenStyle) |
|
1645 { |
|
1646 return -1; // less than |
|
1647 } |
|
1648 else if (aFirst.iPenStyle > aSecond.iPenStyle) |
|
1649 { |
|
1650 return 1; // more than |
|
1651 } |
|
1652 else |
|
1653 { |
|
1654 // For PC-lint |
|
1655 } |
|
1656 |
|
1657 if (aFirst.iDrawMode < aSecond.iDrawMode) |
|
1658 { |
|
1659 return -1; // less than |
|
1660 } |
|
1661 else if (aFirst.iDrawMode > aSecond.iDrawMode) |
|
1662 { |
|
1663 return 1; // more than |
|
1664 } |
|
1665 else |
|
1666 { |
|
1667 // For PC-lint |
|
1668 } |
|
1669 |
|
1670 if (aFirst.iStrikethrough < aSecond.iStrikethrough) |
|
1671 { |
|
1672 return -1; // less than |
|
1673 } |
|
1674 else if (aFirst.iStrikethrough > aSecond.iStrikethrough) |
|
1675 { |
|
1676 return 1; // more than |
|
1677 } |
|
1678 else |
|
1679 { |
|
1680 // For PC-lint |
|
1681 } |
|
1682 |
|
1683 if (aFirst.iUnderline < aSecond.iUnderline) |
|
1684 { |
|
1685 return -1; // less than |
|
1686 } |
|
1687 else if (aFirst.iUnderline > aSecond.iUnderline) |
|
1688 { |
|
1689 return 1; // more than |
|
1690 } |
|
1691 else |
|
1692 { |
|
1693 // For PC-lint |
|
1694 } |
|
1695 |
|
1696 return 0; // equal enough, note that we don't check every field |
|
1697 } |
|
1698 |
|
1699 // --------------------------------------------------------------------------- |
|
1700 // |
|
1701 // --------------------------------------------------------------------------- |
|
1702 // |
|
1703 TInt ImageOrderFunc(const CHuiCanvasGraphicImage& aFirst, const CHuiCanvasGraphicImage& aSecond) |
|
1704 { |
|
1705 // Bitmap handle |
|
1706 if (aFirst.iBitmapHandle < aSecond.iBitmapHandle) |
|
1707 { |
|
1708 return -1; // less than |
|
1709 } |
|
1710 else if (aFirst.iBitmapHandle > aSecond.iBitmapHandle) |
|
1711 { |
|
1712 return 1; // more than |
|
1713 } |
|
1714 else |
|
1715 { |
|
1716 // For PC-lint |
|
1717 } |
|
1718 |
|
1719 // Mask handle |
|
1720 if (aFirst.iMaskHandle < aSecond.iMaskHandle) |
|
1721 { |
|
1722 return -1; // less than |
|
1723 } |
|
1724 else if (aFirst.iMaskHandle > aSecond.iMaskHandle) |
|
1725 { |
|
1726 return 1; // more than |
|
1727 } |
|
1728 else |
|
1729 { |
|
1730 // For PC-lint |
|
1731 } |
|
1732 |
|
1733 // Inverted mask |
|
1734 if (aFirst.iInvertedMask < aSecond.iInvertedMask) |
|
1735 { |
|
1736 return -1; // less than |
|
1737 } |
|
1738 else if (aFirst.iInvertedMask > aSecond.iInvertedMask) |
|
1739 { |
|
1740 return 1; // more than |
|
1741 } |
|
1742 else |
|
1743 { |
|
1744 // For PC-lint |
|
1745 } |
|
1746 |
|
1747 // Mask origin point X |
|
1748 if (aFirst.iMaskOriginPoint.iX < aSecond.iMaskOriginPoint.iX) |
|
1749 { |
|
1750 return -1; // less than |
|
1751 } |
|
1752 else if (aFirst.iMaskOriginPoint.iX > aSecond.iMaskOriginPoint.iX) |
|
1753 { |
|
1754 return 1; // more than |
|
1755 } |
|
1756 else |
|
1757 { |
|
1758 // For PC-lint |
|
1759 } |
|
1760 |
|
1761 // Mask origin point Y |
|
1762 if (aFirst.iMaskOriginPoint.iY < aSecond.iMaskOriginPoint.iY) |
|
1763 { |
|
1764 return -1; // less than |
|
1765 } |
|
1766 else if (aFirst.iMaskOriginPoint.iY > aSecond.iMaskOriginPoint.iY) |
|
1767 { |
|
1768 return 1; // more than |
|
1769 } |
|
1770 else |
|
1771 { |
|
1772 // For PC-lint |
|
1773 } |
|
1774 |
|
1775 if (aFirst.iImageSize.iHeight < aSecond.iImageSize.iHeight) |
|
1776 { |
|
1777 return -1; // less than |
|
1778 } |
|
1779 else if (aFirst.iImageSize.iHeight > aSecond.iImageSize.iHeight) |
|
1780 { |
|
1781 return 1; // more than |
|
1782 } |
|
1783 else |
|
1784 { |
|
1785 // For PC-lint |
|
1786 } |
|
1787 |
|
1788 if (aFirst.iImageSize.iWidth < aSecond.iImageSize.iWidth) |
|
1789 { |
|
1790 return -1; // less than |
|
1791 } |
|
1792 else if (aFirst.iImageSize.iWidth > aSecond.iImageSize.iWidth) |
|
1793 { |
|
1794 return 1; // more than |
|
1795 } |
|
1796 else |
|
1797 { |
|
1798 // For PC-lint |
|
1799 } |
|
1800 |
|
1801 if (aFirst.iSubImages.Count() < aSecond.iSubImages.Count()) |
|
1802 { |
|
1803 return -1; |
|
1804 } |
|
1805 else if (aFirst.iSubImages.Count() > aSecond.iSubImages.Count()) |
|
1806 { |
|
1807 return 1; |
|
1808 } |
|
1809 else |
|
1810 { |
|
1811 // Same amount, must check array content |
|
1812 if (aFirst.iSubImages.Count() && aSecond.iSubImages.Count()) |
|
1813 { |
|
1814 for (TInt i=0; i<aFirst.iSubImages.Count();i++) |
|
1815 { |
|
1816 if (aFirst.iSubImages[i].iBitmapHandle < aSecond.iSubImages[i].iBitmapHandle) |
|
1817 { |
|
1818 return -1; |
|
1819 } |
|
1820 else if (aFirst.iSubImages[i].iBitmapHandle > aSecond.iSubImages[i].iBitmapHandle) |
|
1821 { |
|
1822 return 1; |
|
1823 } |
|
1824 else |
|
1825 { |
|
1826 // For PC-lint |
|
1827 } |
|
1828 |
|
1829 if (aFirst.iSubImages[i].iMaskHandle < aSecond.iSubImages[i].iMaskHandle) |
|
1830 { |
|
1831 return -1; |
|
1832 } |
|
1833 else if (aFirst.iSubImages[i].iMaskHandle > aSecond.iSubImages[i].iMaskHandle) |
|
1834 { |
|
1835 return 1; |
|
1836 } |
|
1837 else |
|
1838 { |
|
1839 // For PC-lint |
|
1840 } |
|
1841 |
|
1842 if (aFirst.iSubImages[i].iCombinedBitmapPoint.iX < aSecond.iSubImages[i].iCombinedBitmapPoint.iX) |
|
1843 { |
|
1844 return -1; |
|
1845 } |
|
1846 else if (aFirst.iSubImages[i].iCombinedBitmapPoint.iX > aSecond.iSubImages[i].iCombinedBitmapPoint.iX) |
|
1847 { |
|
1848 return 1; |
|
1849 } |
|
1850 else |
|
1851 { |
|
1852 // For PC-lint |
|
1853 } |
|
1854 |
|
1855 if (aFirst.iSubImages[i].iCombinedBitmapPoint.iY < aSecond.iSubImages[i].iCombinedBitmapPoint.iY) |
|
1856 { |
|
1857 return -1; |
|
1858 } |
|
1859 else if (aFirst.iSubImages[i].iCombinedBitmapPoint.iY > aSecond.iSubImages[i].iCombinedBitmapPoint.iY) |
|
1860 { |
|
1861 return 1; |
|
1862 } |
|
1863 else |
|
1864 { |
|
1865 // For PC-lint |
|
1866 } |
|
1867 |
|
1868 |
|
1869 } |
|
1870 } |
|
1871 else |
|
1872 { |
|
1873 // For PC-lint |
|
1874 } |
|
1875 } |
|
1876 return GcImageOrderFunc(aFirst.iGcParams, aSecond.iGcParams); |
|
1877 } |
|
1878 |
|
1879 // --------------------------------------------------------------------------- |
|
1880 // |
|
1881 // --------------------------------------------------------------------------- |
|
1882 // |
|
1883 TInt TextOrderFunc(const CHuiCanvasTextImage& aFirst, const CHuiCanvasTextImage& aSecond) |
|
1884 { |
|
1885 // Font handle |
|
1886 if (aFirst.iFontHandle < aSecond.iFontHandle) |
|
1887 { |
|
1888 return -1; // less than |
|
1889 } |
|
1890 else if (aFirst.iFontHandle > aSecond.iFontHandle) |
|
1891 { |
|
1892 return 1; // more than |
|
1893 } |
|
1894 else |
|
1895 { |
|
1896 // For PC-lint |
|
1897 } |
|
1898 |
|
1899 // Text width |
|
1900 if (aFirst.iTextWidth < aSecond.iTextWidth) |
|
1901 { |
|
1902 return -1; // less than |
|
1903 } |
|
1904 else if (aFirst.iTextWidth > aSecond.iTextWidth) |
|
1905 { |
|
1906 return 1; // more than |
|
1907 } |
|
1908 else |
|
1909 { |
|
1910 // For PC-lint |
|
1911 } |
|
1912 |
|
1913 // iTextBoxMaxSize.iWidth |
|
1914 if (aFirst.iTextBoxMaxSize.iWidth < aSecond.iTextBoxMaxSize.iWidth) |
|
1915 { |
|
1916 return -1; // less than |
|
1917 } |
|
1918 else if (aFirst.iTextBoxMaxSize.iWidth > aSecond.iTextBoxMaxSize.iWidth) |
|
1919 { |
|
1920 return 1; // more than |
|
1921 } |
|
1922 else |
|
1923 { |
|
1924 // For PC-lint |
|
1925 } |
|
1926 |
|
1927 // Text content |
|
1928 TInt textcompare = KErrNotFound; |
|
1929 if ( aFirst.iFindTextPtr ) |
|
1930 { |
|
1931 textcompare = aFirst.iFindTextPtr->Compare(*aSecond.iText); |
|
1932 } |
|
1933 else |
|
1934 { |
|
1935 textcompare = aFirst.iText->Compare(*aSecond.iText); |
|
1936 } |
|
1937 |
|
1938 if (textcompare < 0) |
|
1939 { |
|
1940 return -1; |
|
1941 } |
|
1942 else if (textcompare > 0) |
|
1943 { |
|
1944 return 1; |
|
1945 } |
|
1946 else |
|
1947 { |
|
1948 // For PC-lint |
|
1949 } |
|
1950 |
|
1951 // iBaseLineOffset |
|
1952 if (aFirst.iBaseLineOffset < aSecond.iBaseLineOffset) |
|
1953 { |
|
1954 return -1; // less than |
|
1955 } |
|
1956 else if (aFirst.iBaseLineOffset > aSecond.iBaseLineOffset) |
|
1957 { |
|
1958 return 1; // more than |
|
1959 } |
|
1960 else |
|
1961 { |
|
1962 // For PC-lint |
|
1963 } |
|
1964 |
|
1965 // iTextAlign |
|
1966 if (aFirst.iTextAlign < aSecond.iTextAlign) |
|
1967 { |
|
1968 return -1; // less than |
|
1969 } |
|
1970 else if (aFirst.iTextAlign > aSecond.iTextAlign) |
|
1971 { |
|
1972 return 1; // more than |
|
1973 } |
|
1974 else |
|
1975 { |
|
1976 // For PC-lint |
|
1977 } |
|
1978 |
|
1979 // iMargin |
|
1980 if (aFirst.iMargin < aSecond.iMargin) |
|
1981 { |
|
1982 return -1; // less than |
|
1983 } |
|
1984 else if (aFirst.iMargin > aSecond.iMargin) |
|
1985 { |
|
1986 return 1; // more than |
|
1987 } |
|
1988 else |
|
1989 { |
|
1990 // For PC-lint |
|
1991 } |
|
1992 |
|
1993 // iAngle |
|
1994 if (aFirst.iAngle < aSecond.iAngle) |
|
1995 { |
|
1996 return -1; // less than |
|
1997 } |
|
1998 else if (aFirst.iAngle > aSecond.iAngle) |
|
1999 { |
|
2000 return 1; // more than |
|
2001 } |
|
2002 else |
|
2003 { |
|
2004 // For PC-lint |
|
2005 } |
|
2006 |
|
2007 // Font handle |
|
2008 if (aFirst.iTextParams.iStart < aSecond.iTextParams.iStart) |
|
2009 { |
|
2010 return -1; // less than |
|
2011 } |
|
2012 else if (aFirst.iTextParams.iStart > aSecond.iTextParams.iStart) |
|
2013 { |
|
2014 return 1; // more than |
|
2015 } |
|
2016 else |
|
2017 { |
|
2018 // For PC-lint |
|
2019 } |
|
2020 |
|
2021 // Font handle |
|
2022 if (aFirst.iTextParams.iEnd < aSecond.iTextParams.iEnd) |
|
2023 { |
|
2024 return -1; // less than |
|
2025 } |
|
2026 else if (aFirst.iTextParams.iEnd > aSecond.iTextParams.iEnd) |
|
2027 { |
|
2028 return 1; // more than |
|
2029 } |
|
2030 else |
|
2031 { |
|
2032 // For PC-lint |
|
2033 } |
|
2034 |
|
2035 // Font handle |
|
2036 if (aFirst.iTextParams.iFlags < aSecond.iTextParams.iFlags) |
|
2037 { |
|
2038 return -1; // less than |
|
2039 } |
|
2040 else if (aFirst.iTextParams.iFlags > aSecond.iTextParams.iFlags) |
|
2041 { |
|
2042 return 1; // more than |
|
2043 } |
|
2044 else |
|
2045 { |
|
2046 // For PC-lint |
|
2047 } |
|
2048 |
|
2049 return GcTextOrderFunc(aFirst.iGcParams, aSecond.iGcParams); |
|
2050 } |
|
2051 |
|
2052 |
|
2053 // --------------------------------------------------------------------------- |
|
2054 // |
|
2055 // --------------------------------------------------------------------------- |
|
2056 // |
|
2057 TInt RenderBufferOrderFunc(const CHuiCanvasRenderBufferImage& aFirst, const CHuiCanvasRenderBufferImage& aSecond) |
|
2058 { |
|
2059 if (aFirst.iOwner < aSecond.iOwner) |
|
2060 { |
|
2061 return -1; // less than |
|
2062 } |
|
2063 else if (aFirst.iOwner > aSecond.iOwner) |
|
2064 { |
|
2065 return 1; // more than |
|
2066 } |
|
2067 else |
|
2068 { |
|
2069 // For PC-lint |
|
2070 } |
|
2071 |
|
2072 return 0; // Equal |
|
2073 } |
|
2074 |
|
2075 |
|
2076 // --------------------------------------------------------------------------- |
|
2077 // Constructor |
|
2078 // --------------------------------------------------------------------------- |
|
2079 // |
|
2080 CHuiCanvasTextureCache::CHuiCanvasTextureCache() |
|
2081 { |
|
2082 EnableLowMemoryState(EFalse); |
|
2083 CHuiStatic::Env().AddLowMemoryObserver(this); |
|
2084 } |
|
2085 |
|
2086 // --------------------------------------------------------------------------- |
|
2087 // Destructor |
|
2088 // --------------------------------------------------------------------------- |
|
2089 // |
|
2090 CHuiCanvasTextureCache::~CHuiCanvasTextureCache() |
|
2091 { |
|
2092 CHuiStatic::Env().RemoveLowMemoryObserver(this); |
|
2093 iCachedTexts.ResetAndDestroy(); |
|
2094 iCachedImages.ResetAndDestroy(); |
|
2095 iRecycledTextures.ResetAndDestroy(); |
|
2096 |
|
2097 if (iSearchedTextImageEntry) |
|
2098 { |
|
2099 iSearchedTextImageEntry->Reset(); |
|
2100 delete iSearchedTextImageEntry; |
|
2101 } |
|
2102 |
|
2103 if (iSearchedGraphicImageEntry) |
|
2104 { |
|
2105 iSearchedGraphicImageEntry->Reset(); |
|
2106 delete iSearchedGraphicImageEntry; |
|
2107 } |
|
2108 |
|
2109 if (iSearchedRenderBufferImageEntry) |
|
2110 { |
|
2111 iSearchedRenderBufferImageEntry->Reset(); |
|
2112 delete iSearchedRenderBufferImageEntry; |
|
2113 } |
|
2114 |
|
2115 delete iTextImageRasterizer; |
|
2116 delete iOutLineTextImageRasterizer; |
|
2117 delete iGraphicImageRasterizer; |
|
2118 delete iCombinedGraphicImageRasterizer; |
|
2119 delete iCanvasGc; |
|
2120 } |
|
2121 |
|
2122 // --------------------------------------------------------------------------- |
|
2123 // |
|
2124 // --------------------------------------------------------------------------- |
|
2125 // |
|
2126 CHuiCanvasTextureCache* CHuiCanvasTextureCache::NewL() |
|
2127 { |
|
2128 CHuiCanvasTextureCache* self = CHuiCanvasTextureCache::NewLC(); |
|
2129 CleanupStack::Pop(self); |
|
2130 return self; |
|
2131 } |
|
2132 |
|
2133 // --------------------------------------------------------------------------- |
|
2134 // |
|
2135 // --------------------------------------------------------------------------- |
|
2136 // |
|
2137 CHuiCanvasTextureCache* CHuiCanvasTextureCache::NewLC() |
|
2138 { |
|
2139 CHuiCanvasTextureCache* self = new (ELeave) CHuiCanvasTextureCache(); |
|
2140 CleanupStack::PushL(self); |
|
2141 self->ConstructL(); |
|
2142 return self; |
|
2143 } |
|
2144 |
|
2145 |
|
2146 // --------------------------------------------------------------------------- |
|
2147 // |
|
2148 // --------------------------------------------------------------------------- |
|
2149 // |
|
2150 void CHuiCanvasTextureCache::ConstructL() |
|
2151 { |
|
2152 iMemoryLevel = EHuiMemoryLevelNormal; |
|
2153 |
|
2154 iCanvasGc = CHuiStatic::Renderer().CreateCanvasGcL(); |
|
2155 |
|
2156 iTextImageRasterizer = new (ELeave) CHuiCanvasTextImageRasterizer; |
|
2157 iTextImageRasterizer->ConstructL(EGray256); |
|
2158 |
|
2159 iOutLineTextImageRasterizer = new (ELeave) CHuiCanvasTextImageRasterizer; |
|
2160 iOutLineTextImageRasterizer->ConstructL(EColor16MA); |
|
2161 |
|
2162 iGraphicImageRasterizer = new (ELeave) CHuiCanvasGraphicImageRasterizer; |
|
2163 iGraphicImageRasterizer->ConstructL(); |
|
2164 |
|
2165 iCombinedGraphicImageRasterizer = new (ELeave) CHuiCanvasCombinedGraphicImageRasterizer; |
|
2166 iCombinedGraphicImageRasterizer->ConstructL(EColor64K); |
|
2167 |
|
2168 iSearchedTextImageEntry = new (ELeave) CHuiCanvasTextImage; |
|
2169 iSearchedGraphicImageEntry = new (ELeave) CHuiCanvasGraphicImage; |
|
2170 iSearchedRenderBufferImageEntry = new (ELeave) CHuiCanvasRenderBufferImage; |
|
2171 } |
|
2172 |
|
2173 |
|
2174 // --------------------------------------------------------------------------- |
|
2175 // |
|
2176 // |
|
2177 // --------------------------------------------------------------------------- |
|
2178 // |
|
2179 const CHuiCanvasGraphicImage* CHuiCanvasTextureCache::FindCachedImageL( |
|
2180 const THuiCachedImageParams& aCachedImageParams, |
|
2181 const CHuiCanvasVisual& aUser) |
|
2182 { |
|
2183 TInt cachedEntry = KErrNotFound; |
|
2184 |
|
2185 iSearchedGraphicImageEntry->Reset(); |
|
2186 iSearchedGraphicImageEntry->iBitmapHandle = aCachedImageParams.iBitmapHandle; |
|
2187 iSearchedGraphicImageEntry->iMaskHandle = aCachedImageParams.iMaskHandle; |
|
2188 iSearchedGraphicImageEntry->iTexture = NULL; |
|
2189 iSearchedGraphicImageEntry->iInvertedMask = aCachedImageParams.iInvertedMask; |
|
2190 iSearchedGraphicImageEntry->iMaskOriginPoint = aCachedImageParams.iMaskOriginPoint; |
|
2191 iSearchedGraphicImageEntry->iBitmapTouchCount = KHuiInitialBitmapTouchCount; |
|
2192 iSearchedGraphicImageEntry->iMaskTouchCount = KHuiInitialBitmapTouchCount; |
|
2193 iSearchedGraphicImageEntry->iGcParams = aCachedImageParams.iGcParams; |
|
2194 |
|
2195 cachedEntry = iCachedImages.FindInOrder(iSearchedGraphicImageEntry, ImageOrderFunc); |
|
2196 if (cachedEntry == KErrNotFound) |
|
2197 { |
|
2198 User::Leave(KErrNotFound); |
|
2199 } |
|
2200 |
|
2201 iCachedImages[cachedEntry]->RefreshUser(aUser); |
|
2202 return iCachedImages[cachedEntry]; |
|
2203 } |
|
2204 |
|
2205 // --------------------------------------------------------------------------- |
|
2206 // |
|
2207 // |
|
2208 // --------------------------------------------------------------------------- |
|
2209 // |
|
2210 const CHuiCanvasGraphicImage* CHuiCanvasTextureCache::CreateCombinedCachedImageL( |
|
2211 const RArray<THuiCachedCombinedImageParams>& aCachedImageParams, |
|
2212 const THuiCachedGcParams& aGcParams, |
|
2213 const TSize& aImageSize, |
|
2214 const CHuiCanvasVisual& aUser) |
|
2215 { |
|
2216 TBool needUpdate = EFalse; |
|
2217 TInt cachedEntry = KErrNotFound; |
|
2218 |
|
2219 iSearchedGraphicImageEntry->Reset(); |
|
2220 iSearchedGraphicImageEntry->iGcParams = aGcParams; |
|
2221 iSearchedGraphicImageEntry->iImageSize = aImageSize; |
|
2222 |
|
2223 |
|
2224 for (TInt i=0; i<aCachedImageParams.Count();i++) |
|
2225 { |
|
2226 THuiCachedBitmap cachedBitmap; |
|
2227 cachedBitmap.iBitmapHandle = aCachedImageParams[i].iBitmapHandle; |
|
2228 cachedBitmap.iMaskHandle = aCachedImageParams[i].iMaskHandle; |
|
2229 cachedBitmap.iCombinedBitmapPoint = aCachedImageParams[i].iCombinedBitmapPoint; |
|
2230 iSearchedGraphicImageEntry->iSubImages.Append(cachedBitmap); |
|
2231 } |
|
2232 |
|
2233 cachedEntry = iCachedImages.FindInOrder(iSearchedGraphicImageEntry, ImageOrderFunc); |
|
2234 if (cachedEntry == KErrNotFound) |
|
2235 { |
|
2236 // Create new entry object |
|
2237 CHuiCanvasGraphicImage* newEntry = new (ELeave) CHuiCanvasGraphicImage; |
|
2238 CleanupStack::PushL(newEntry); |
|
2239 newEntry->CopyAttributes(*iSearchedGraphicImageEntry); |
|
2240 |
|
2241 // Create new accelerated image |
|
2242 CHuiTexture* newtexture = CreateRecycledTextureL(); |
|
2243 newEntry->iTexture = newtexture; |
|
2244 |
|
2245 User::LeaveIfError(iCachedImages.InsertInOrder(newEntry, ImageOrderFunc)); |
|
2246 cachedEntry = iCachedImages.FindInOrder(newEntry, ImageOrderFunc); |
|
2247 |
|
2248 CleanupStack::Pop(newEntry); |
|
2249 needUpdate = ETrue; |
|
2250 } |
|
2251 else |
|
2252 { |
|
2253 // Check if needs to be updated by checking active users list |
|
2254 if (!iCachedImages[cachedEntry]->IsUser(aUser)) |
|
2255 { |
|
2256 needUpdate = ETrue; |
|
2257 } |
|
2258 } |
|
2259 |
|
2260 if (needUpdate) |
|
2261 { |
|
2262 TRAPD(updateError, iCombinedGraphicImageRasterizer->RasterizeL(*iCachedImages[cachedEntry])); |
|
2263 if (updateError == KErrNoMemory) |
|
2264 { |
|
2265 // Call grim reaper to initiate system level texture memory actions ! |
|
2266 HandleOutOfTextureMemory(); |
|
2267 User::LeaveIfError(updateError); |
|
2268 } |
|
2269 } |
|
2270 |
|
2271 iCachedImages[cachedEntry]->RefreshUser(aUser); |
|
2272 return iCachedImages[cachedEntry]; |
|
2273 } |
|
2274 |
|
2275 |
|
2276 // --------------------------------------------------------------------------- |
|
2277 // Improvement idea for HW accelerated, upload all images of the buffer |
|
2278 // into single texture and use texture coordinates to draw each image. |
|
2279 // --------------------------------------------------------------------------- |
|
2280 // |
|
2281 const CHuiCanvasGraphicImage* CHuiCanvasTextureCache::CreateCachedImageL( |
|
2282 const THuiCachedImageParams& aCachedImageParams, |
|
2283 const CHuiCanvasVisual& aUser) |
|
2284 { |
|
2285 TBool needUpdate = EFalse; |
|
2286 TInt cachedEntry = KErrNotFound; |
|
2287 |
|
2288 iSearchedGraphicImageEntry->Reset(); |
|
2289 iSearchedGraphicImageEntry->iBitmapHandle = aCachedImageParams.iBitmapHandle; |
|
2290 iSearchedGraphicImageEntry->iMaskHandle = aCachedImageParams.iMaskHandle; |
|
2291 iSearchedGraphicImageEntry->iTexture = NULL; |
|
2292 iSearchedGraphicImageEntry->iInvertedMask = aCachedImageParams.iInvertedMask; |
|
2293 iSearchedGraphicImageEntry->iMaskOriginPoint = aCachedImageParams.iMaskOriginPoint; |
|
2294 iSearchedGraphicImageEntry->iBitmapTouchCount = KHuiInitialBitmapTouchCount; |
|
2295 iSearchedGraphicImageEntry->iMaskTouchCount = KHuiInitialBitmapTouchCount; |
|
2296 iSearchedGraphicImageEntry->iGcParams = aCachedImageParams.iGcParams; |
|
2297 |
|
2298 cachedEntry = iCachedImages.FindInOrder(iSearchedGraphicImageEntry, ImageOrderFunc); |
|
2299 if (cachedEntry == KErrNotFound) |
|
2300 { |
|
2301 // Create new entry object |
|
2302 CHuiCanvasGraphicImage* newEntry = new (ELeave) CHuiCanvasGraphicImage; |
|
2303 CleanupStack::PushL(newEntry); |
|
2304 |
|
2305 newEntry->CopyAttributes(*iSearchedGraphicImageEntry); |
|
2306 |
|
2307 // Create new accelerated image |
|
2308 CHuiTexture* newtexture = CreateRecycledTextureL(); |
|
2309 newEntry->iTexture = newtexture; |
|
2310 |
|
2311 User::LeaveIfError(iCachedImages.InsertInOrder(newEntry, ImageOrderFunc)); |
|
2312 cachedEntry = iCachedImages.FindInOrder(newEntry, ImageOrderFunc); |
|
2313 CleanupStack::Pop(newEntry); |
|
2314 needUpdate = ETrue; |
|
2315 } |
|
2316 else |
|
2317 { |
|
2318 // Check if needs to be updated by checking active users list |
|
2319 if (!iCachedImages[cachedEntry]->IsUser(aUser)) |
|
2320 { |
|
2321 needUpdate = ETrue; |
|
2322 } |
|
2323 } |
|
2324 |
|
2325 if (needUpdate) |
|
2326 { |
|
2327 TRAPD(updateError, iGraphicImageRasterizer->RasterizeL(*iCachedImages[cachedEntry])); |
|
2328 if (updateError == KErrNoMemory) |
|
2329 { |
|
2330 // Call grim reaper to initiate system level texture memory actions ! |
|
2331 HandleOutOfTextureMemory(); |
|
2332 User::LeaveIfError(updateError); |
|
2333 } |
|
2334 } |
|
2335 |
|
2336 iCachedImages[cachedEntry]->RefreshUser(aUser); |
|
2337 return iCachedImages[cachedEntry]; |
|
2338 } |
|
2339 |
|
2340 |
|
2341 |
|
2342 |
|
2343 // --------------------------------------------------------------------------- |
|
2344 // |
|
2345 // --------------------------------------------------------------------------- |
|
2346 // |
|
2347 const CHuiCanvasTextImage* CHuiCanvasTextureCache::CreateCachedTextL( |
|
2348 const THuiCachedTextParams& aCachedTextParams, |
|
2349 const CHuiCanvasVisual& aUser) |
|
2350 { |
|
2351 TBool needUpdate = EFalse; |
|
2352 TInt cachedEntry = KErrNotFound; |
|
2353 |
|
2354 iSearchedTextImageEntry->Reset(); |
|
2355 iSearchedTextImageEntry->iFindTextPtr= aCachedTextParams.iFindTextPtr; // Not owned, gets be updated if not found |
|
2356 iSearchedTextImageEntry->iTexture = NULL; // Gets updated if not found |
|
2357 iSearchedTextImageEntry->iFontHandle = aCachedTextParams.iFontHandle; |
|
2358 iSearchedTextImageEntry->iRasterizationOffset = TPoint(0,0); // Gets updated when text has been rasterized |
|
2359 Mem::Copy( &iSearchedTextImageEntry->iTextParams, &aCachedTextParams.iTextParams, sizeof(THuiCanvasTextParameters)); |
|
2360 iSearchedTextImageEntry->iTextBoxMaxSize = aCachedTextParams.iTextBoxMaxSize; |
|
2361 iSearchedTextImageEntry->iTextWidth = aCachedTextParams.iTextWidth; |
|
2362 iSearchedTextImageEntry->iBaseLineOffset = aCachedTextParams.iBaseLineOffset; |
|
2363 iSearchedTextImageEntry->iTextAlign = aCachedTextParams.iTextAlign; |
|
2364 iSearchedTextImageEntry->iMargin = aCachedTextParams.iMargin; |
|
2365 iSearchedTextImageEntry->iAngle = aCachedTextParams.iAngle; |
|
2366 iSearchedTextImageEntry->iGcParams = aCachedTextParams.iGcParams; |
|
2367 |
|
2368 |
|
2369 cachedEntry = iCachedTexts.FindInOrder(iSearchedTextImageEntry, TextOrderFunc); |
|
2370 if (cachedEntry == KErrNotFound) |
|
2371 { |
|
2372 // Create new entry object |
|
2373 CHuiCanvasTextImage* newTextEntry = new (ELeave) CHuiCanvasTextImage; |
|
2374 CleanupStack::PushL(newTextEntry); |
|
2375 |
|
2376 newTextEntry->CopyAttributes(*iSearchedTextImageEntry); |
|
2377 |
|
2378 // Create new accelerated image |
|
2379 CHuiTexture* newtexture = CreateRecycledTextureL(); |
|
2380 newTextEntry->iTexture = newtexture; |
|
2381 |
|
2382 // Create text which entry will own |
|
2383 HBufC* ownedText = aCachedTextParams.iFindTextPtr->AllocL(); |
|
2384 newTextEntry->iText = ownedText; |
|
2385 newTextEntry->iFindTextPtr = NULL; |
|
2386 TInt insertSuccess = iCachedTexts.InsertInOrder(newTextEntry, TextOrderFunc); |
|
2387 __ASSERT_DEBUG( !insertSuccess, USER_INVARIANT() ); |
|
2388 User::LeaveIfError( insertSuccess ); |
|
2389 cachedEntry = iCachedTexts.FindInOrder(newTextEntry, TextOrderFunc); |
|
2390 |
|
2391 CleanupStack::Pop(newTextEntry); |
|
2392 needUpdate = ETrue; |
|
2393 } |
|
2394 else |
|
2395 { |
|
2396 // If it was found, great. No need to update it. |
|
2397 } |
|
2398 |
|
2399 |
|
2400 if (needUpdate) |
|
2401 { |
|
2402 TBool outlinefont = EFalse; |
|
2403 |
|
2404 if (!(*iCachedTexts[cachedEntry]).iFont) |
|
2405 { |
|
2406 CFbsBitGcFont* font = new (ELeave) CFbsBitGcFont(); |
|
2407 CleanupStack::PushL(font); |
|
2408 User::LeaveIfError(font->Duplicate((*iCachedTexts[cachedEntry]).iFontHandle)); |
|
2409 (*iCachedTexts[cachedEntry]).iFont = font; |
|
2410 CleanupStack::Pop(); // font |
|
2411 } |
|
2412 |
|
2413 outlinefont = (*iCachedTexts[cachedEntry]).iFont->FontSpecInTwips().iFontStyle.IsEffectOn(FontEffect::EOutline); |
|
2414 TInt updateError(KErrNone); |
|
2415 if (!outlinefont) |
|
2416 { |
|
2417 TRAP(updateError, iTextImageRasterizer->RasterizeL(*iCachedTexts[cachedEntry])); |
|
2418 } |
|
2419 else |
|
2420 { |
|
2421 TRAP(updateError, iOutLineTextImageRasterizer->RasterizeL(*iCachedTexts[cachedEntry])); |
|
2422 } |
|
2423 |
|
2424 |
|
2425 |
|
2426 if (updateError == KErrNoMemory) |
|
2427 { |
|
2428 // Call grim reaper to initiate system level texture memory actions ! |
|
2429 HandleOutOfTextureMemory(); |
|
2430 User::LeaveIfError(updateError); |
|
2431 } |
|
2432 } |
|
2433 |
|
2434 iCachedTexts[cachedEntry]->RefreshUser(aUser); |
|
2435 return iCachedTexts[cachedEntry]; |
|
2436 } |
|
2437 |
|
2438 |
|
2439 |
|
2440 |
|
2441 // --------------------------------------------------------------------------- |
|
2442 // |
|
2443 // --------------------------------------------------------------------------- |
|
2444 // |
|
2445 void CHuiCanvasTextureCache::ReleaseAllCachedEntries(const CHuiCanvasVisual& aUser) |
|
2446 { |
|
2447 // Texts |
|
2448 for (TInt i=0; i < iCachedTexts.Count(); i++) |
|
2449 { |
|
2450 TInt index = iCachedTexts[i]->iActiveUsers.FindInAddressOrder(&aUser); |
|
2451 |
|
2452 if (index != KErrNotFound) |
|
2453 { |
|
2454 iCachedTexts[i]->iActiveUsers.Remove(index); |
|
2455 iHasReleasedTexts = ETrue; |
|
2456 } |
|
2457 } |
|
2458 |
|
2459 // Images |
|
2460 for (TInt i=0; i < iCachedImages.Count(); i++) |
|
2461 { |
|
2462 TInt index = iCachedImages[i]->iActiveUsers.FindInAddressOrder(&aUser); |
|
2463 |
|
2464 if (index != KErrNotFound) |
|
2465 { |
|
2466 iCachedImages[i]->iActiveUsers.Remove(index); |
|
2467 iHasReleasedImages = ETrue; |
|
2468 } |
|
2469 } |
|
2470 |
|
2471 // Render buffers are _not_ released together with images and text |
|
2472 } |
|
2473 |
|
2474 |
|
2475 // --------------------------------------------------------------------------- |
|
2476 // |
|
2477 // --------------------------------------------------------------------------- |
|
2478 // |
|
2479 void CHuiCanvasTextureCache::DeleteAllReleasedEntries(TBool aAllowKeepCached) |
|
2480 { |
|
2481 // Texts |
|
2482 if (iHasReleasedTexts) |
|
2483 { |
|
2484 RPointerArray<CHuiCanvasTextImage> unusedEntries; |
|
2485 |
|
2486 FindUnusedTextEntries(unusedEntries); |
|
2487 |
|
2488 // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows |
|
2489 if (aAllowKeepCached) |
|
2490 { |
|
2491 SelectPreservedUnusedTextEntries(unusedEntries); |
|
2492 } |
|
2493 |
|
2494 DeleteUnusedTextEntries(unusedEntries); |
|
2495 |
|
2496 unusedEntries.Close(); |
|
2497 iHasReleasedTexts = EFalse; |
|
2498 } |
|
2499 |
|
2500 // Images |
|
2501 if (iHasReleasedImages) |
|
2502 { |
|
2503 RPointerArray<CHuiCanvasGraphicImage> unusedEntries; |
|
2504 |
|
2505 FindUnusedImageEntries(unusedEntries); |
|
2506 |
|
2507 // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows |
|
2508 if (aAllowKeepCached) |
|
2509 { |
|
2510 SelectPreservedUnusedImageEntries(unusedEntries); |
|
2511 } |
|
2512 |
|
2513 DeleteUnusedImageEntries(unusedEntries); |
|
2514 |
|
2515 unusedEntries.Close(); |
|
2516 iHasReleasedImages = EFalse; |
|
2517 } |
|
2518 |
|
2519 // Render buffers |
|
2520 if (iHasReleasedRenderBuffers) |
|
2521 { |
|
2522 RPointerArray<CHuiCanvasRenderBufferImage> unusedEntries; |
|
2523 |
|
2524 FindUnusedRenderBufferEntries(unusedEntries); |
|
2525 |
|
2526 // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows |
|
2527 if (aAllowKeepCached) |
|
2528 { |
|
2529 SelectPreservedUnusedRenderBufferEntries(unusedEntries); |
|
2530 } |
|
2531 |
|
2532 DeleteUnusedRenderBufferEntries(unusedEntries); |
|
2533 |
|
2534 unusedEntries.Close(); |
|
2535 iHasReleasedRenderBuffers = EFalse; |
|
2536 } |
|
2537 } |
|
2538 |
|
2539 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE_EGL |
|
2540 #include "eglext.h" |
|
2541 typedef EGLBoolean (*NOK_resource_profiling)(EGLDisplay, EGLint, EGLint*, EGLint, EGLint*); |
|
2542 |
|
2543 void ReportGraphicsMemoryUsage() |
|
2544 { |
|
2545 RDebug::Print(_L("About to ask EGL profiling ext")); |
|
2546 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
|
2547 |
|
2548 /* |
|
2549 ** Search for extName in the extensions string. Use of strstr() |
|
2550 ** is not sufficient because extension names can be prefixes of |
|
2551 ** other extension names. Could use strtok() but the constant |
|
2552 ** string returned by glGetString can be in read-only memory. |
|
2553 */ |
|
2554 /* TBool extensionFound = EFalse; |
|
2555 char *p = (char *) eglQueryString(dpy,EGL_EXTENSIONS); |
|
2556 char *end; |
|
2557 int extNameLen = strlen("EGL_NOK_resource_profiling"); |
|
2558 end = p + strlen(p); |
|
2559 |
|
2560 while (p < end) |
|
2561 { |
|
2562 int n = strcspn(p, " "); |
|
2563 if ((extNameLen == n) && (strncmp("EGL_NOK_resource_profiling", p, n) == 0)) |
|
2564 { |
|
2565 extensionFound = ETrue; |
|
2566 break; |
|
2567 } |
|
2568 p += (n + 1); |
|
2569 } |
|
2570 |
|
2571 if (!extensionFound) |
|
2572 { |
|
2573 TRACES("EGL_NOK_resource_profiling not found from EGL_EXTENSIONS"); |
|
2574 }*/ |
|
2575 // okay, let's fetch the function ptr to our profiling functions |
|
2576 // resource profiling extension function ptr |
|
2577 NOK_resource_profiling eglQueryProfilingData = (NOK_resource_profiling)eglGetProcAddress("eglQueryProfilingDataNOK"); |
|
2578 if (!eglQueryProfilingData) |
|
2579 { |
|
2580 RDebug::Print(_L("EGL profiling ext not present")); |
|
2581 return; |
|
2582 } |
|
2583 |
|
2584 EGLint data_count; |
|
2585 EGLint* prof_data; |
|
2586 TInt i(0); |
|
2587 |
|
2588 /* Find out how much profiling data is available */ |
|
2589 eglQueryProfilingData(dpy, EGL_PROF_QUERY_GLOBAL_BIT_NOK | EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK, |
|
2590 NULL, 0, &data_count); |
|
2591 |
|
2592 /* Allocate room for the profiling data */ |
|
2593 prof_data = (EGLint*)User::Alloc(data_count * sizeof(EGLint)); |
|
2594 if (prof_data == NULL) |
|
2595 { |
|
2596 RDebug::Print(_L("Could not get mem for EGL profiling ext")); |
|
2597 return; |
|
2598 } |
|
2599 /* Retrieve the profiling data */ |
|
2600 eglQueryProfilingData(dpy, |
|
2601 EGL_PROF_QUERY_GLOBAL_BIT_NOK | |
|
2602 EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK, |
|
2603 prof_data, |
|
2604 data_count, |
|
2605 &data_count); |
|
2606 |
|
2607 /* Iterate over the returned data */ |
|
2608 while (i < data_count) |
|
2609 { |
|
2610 switch (prof_data[i++]) |
|
2611 { |
|
2612 case EGL_PROF_USED_MEMORY_NOK: |
|
2613 { |
|
2614 RDebug::Print(_L("EGL Profiling: used mem %d"), prof_data[i++]); |
|
2615 break; |
|
2616 } |
|
2617 case EGL_PROF_TOTAL_MEMORY_NOK: |
|
2618 { |
|
2619 RDebug::Print(_L("EGL Profiling: total mem available: %d"), prof_data[i++]); |
|
2620 break; |
|
2621 } |
|
2622 case EGL_PROF_THREAD_ID_NOK: |
|
2623 { |
|
2624 if (sizeof(EGLNativeThreadIdTypeNOK) == 8) |
|
2625 { |
|
2626 i+=2; |
|
2627 } |
|
2628 else |
|
2629 { |
|
2630 i++; |
|
2631 } |
|
2632 break; |
|
2633 } |
|
2634 case EGL_PROF_THREAD_USED_PRIVATE_MEMORY_NOK: |
|
2635 case EGL_PROF_THREAD_USED_SHARED_MEMORY_NOK: |
|
2636 default: |
|
2637 { |
|
2638 i++; |
|
2639 break; |
|
2640 } |
|
2641 } |
|
2642 } |
|
2643 |
|
2644 User::Free(prof_data); |
|
2645 } |
|
2646 |
|
2647 #endif |
|
2648 |
|
2649 |
|
2650 // --------------------------------------------------------------------------- |
|
2651 // |
|
2652 // --------------------------------------------------------------------------- |
|
2653 // |
|
2654 void CHuiCanvasTextureCache::AdvanceTime() |
|
2655 { |
|
2656 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE |
|
2657 RDebug::Print(_L("-- CHuiCanvasTextureCache::AdvanceTime: begin --")); |
|
2658 if (IsLowMemoryStateEnabled()) |
|
2659 { |
|
2660 RDebug::Print(_L("-- CHuiCanvasTextureCache::AdvanceTime: LOW MEMORY STATE ENABLED")); |
|
2661 } |
|
2662 if(iEglProfiling > 10) |
|
2663 { |
|
2664 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE_EGL |
|
2665 ReportGraphicsMemoryUsage(); |
|
2666 #endif |
|
2667 iEglProfiling = 0; |
|
2668 } |
|
2669 else |
|
2670 { |
|
2671 iEglProfiling++; |
|
2672 } |
|
2673 #endif |
|
2674 |
|
2675 // We do not delete all, by leaving something unused in the cache |
|
2676 // we can improve performance. |
|
2677 CalculateGraphicsMemoryUsage(); |
|
2678 DeleteAllReleasedEntries(ETrue); |
|
2679 |
|
2680 // Reset bitmap sizes to save memory. Commented out as resize appears to |
|
2681 // be relatively slow (0.2 - 0.5 ms). Not resizing here means that it uses |
|
2682 // more RAM between frames. |
|
2683 //iTempMask->Resize(KEmptyBitmapSize); |
|
2684 //iTempBitmap->Resize(KEmptyBitmapSize); |
|
2685 |
|
2686 //iFontHandle = 0; |
|
2687 //delete iFont; |
|
2688 //iFont = NULL; |
|
2689 |
|
2690 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE |
|
2691 RDebug::Print(_L("-- Cached texts: %i --"), iCachedTexts.Count()); |
|
2692 RDebug::Print(_L("-- Cached imgs : %i --"), iCachedImages.Count()); |
|
2693 |
|
2694 TInt totalPixels = 0; |
|
2695 |
|
2696 for(TInt i=iCachedTexts.Count() - 1; i >= 0; i--) |
|
2697 { |
|
2698 TSize size = iCachedTexts[i]->iTexture->Size(); |
|
2699 RDebug::Print(_L("-- Cached text: %ix%i, users=%i, string=%S --"), size.iWidth, size.iHeight, iCachedTexts[i]->iActiveUsers.Count(), iCachedTexts[i]->iText ); |
|
2700 totalPixels += size.iWidth * size.iHeight; |
|
2701 |
|
2702 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE_EXTENDED |
|
2703 |
|
2704 RDebug::Print(_L("-- iFontHandle: %i --"), iCachedTexts[i]->iFontHandle ); |
|
2705 RDebug::Print(_L("-- iTextWidth: %i --"), iCachedTexts[i]->iTextWidth ); |
|
2706 RDebug::Print(_L("-- iTextBoxMaxSize.iWidth: %i --"), iCachedTexts[i]->iTextBoxMaxSize.iWidth ); |
|
2707 RDebug::Print(_L("-- iBaseLineOffset: %i --"), iCachedTexts[i]->iBaseLineOffset ); |
|
2708 RDebug::Print(_L("-- iTextAlign: %i --"), iCachedTexts[i]->iTextAlign ); |
|
2709 RDebug::Print(_L("-- iMargin: %i --"), iCachedTexts[i]->iMargin ); |
|
2710 RDebug::Print(_L("-- iAngle: %i --"), iCachedTexts[i]->iAngle ); |
|
2711 RDebug::Print(_L("-- iTextParams.iStart: %i --"), iCachedTexts[i]->iTextParams.iStart ); |
|
2712 RDebug::Print(_L("-- iTextParams.iEnd: %i --"), iCachedTexts[i]->iTextParams.iEnd ); |
|
2713 RDebug::Print(_L("-- iTextParams.iFlagst: %i --"), iCachedTexts[i]->iTextParams.iFlags ); |
|
2714 |
|
2715 |
|
2716 THuiCachedGcParams p = iCachedTexts[i]->iGcParams; |
|
2717 RDebug::Print(_L("-- iPenColor: %i --"), p.iPenColor ); |
|
2718 RDebug::Print(_L("-- iPenStyle: %i --"), p.iPenStyle ); |
|
2719 RDebug::Print(_L("-- iDrawMode: %i --"), p.iDrawMode ); |
|
2720 RDebug::Print(_L("-- iBrushColor: %i --"), p.iBrushColor ); |
|
2721 RDebug::Print(_L("-- iBrushStyle: %i --"), p.iBrushStyle ); |
|
2722 RDebug::Print(_L("-- iShadowMode: %i --"), p.iShadowMode ); |
|
2723 RDebug::Print(_L("-- iStrikethrough: %i --"), p.iStrikethrough ); |
|
2724 RDebug::Print(_L("-- iUnderline: %i --"), p.iUnderline ); |
|
2725 RDebug::Print(_L("-- iUserDisplayMode: %i --"), p.iUserDisplayMode ); |
|
2726 RDebug::Print(_L("-- iShadowColor: %i --"), p.iShadowColor ); |
|
2727 #endif |
|
2728 } |
|
2729 |
|
2730 for(TInt i=iCachedImages.Count() - 1; i >= 0; i--) |
|
2731 { |
|
2732 TSize size = iCachedImages[i]->iTexture->Size(); |
|
2733 if (iCachedImages[i]->iSubImages.Count()) |
|
2734 { |
|
2735 RDebug::Print(_L("-- Cached combined image: %i+%i %ix%i, users=%i --"), iCachedImages[i]->iBitmapHandle, iCachedImages[i]->iMaskHandle, size.iWidth, size.iHeight, iCachedImages[i]->iActiveUsers.Count()); |
|
2736 RDebug::Print(_L("-- Blit size: %ix%i --"), iCachedImages[i]->iImageSize.iWidth, iCachedImages[i]->iImageSize.iHeight); |
|
2737 for (TInt j=0; j<iCachedImages[i]->iSubImages.Count();j++) |
|
2738 { |
|
2739 RDebug::Print(_L("-- subimage: %i+%i Point: %i,%i--"), |
|
2740 iCachedImages[i]->iSubImages[j].iBitmapHandle, |
|
2741 iCachedImages[i]->iSubImages[j].iMaskHandle, |
|
2742 iCachedImages[i]->iSubImages[j].iCombinedBitmapPoint.iX, |
|
2743 iCachedImages[i]->iSubImages[j].iCombinedBitmapPoint.iY); |
|
2744 } |
|
2745 } |
|
2746 else |
|
2747 { |
|
2748 RDebug::Print(_L("-- Cached image: %i+%i %ix%i, users=%i --"), iCachedImages[i]->iBitmapHandle,iCachedImages[i]->iMaskHandle, size.iWidth, size.iHeight, iCachedImages[i]->iActiveUsers.Count()); |
|
2749 } |
|
2750 |
|
2751 totalPixels += size.iWidth * size.iHeight; |
|
2752 } |
|
2753 |
|
2754 RDebug::Print(_L("-- Estimated canvas texture mem usage with 32bpp %i KBytes --"), totalPixels*4 / 1024); |
|
2755 |
|
2756 TInt unusedCanvasTextures = CalculateUnusedCanvasTextureUsageInKbytes(); |
|
2757 |
|
2758 RDebug::Print(_L("-- Estimated canvas unused texture mem usage with 32bpp %i KBytes --"), unusedCanvasTextures); |
|
2759 |
|
2760 TInt totalUsedTextureMemoryInKBytes = CHuiStatic::Env().TextureManager().EstimatedTextureMemUsage(KHuiTextureEstimatedBpp) / 1024; |
|
2761 |
|
2762 RDebug::Print(_L("-- Estimated total texture mem usage with 32bpp %i KBytes --"), totalUsedTextureMemoryInKBytes); |
|
2763 |
|
2764 TInt totalPixelsForRenderBuffers = 0; |
|
2765 for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--) |
|
2766 { |
|
2767 if (iCachedRenderBuffers[i]->iCanvasRenderBuffer) |
|
2768 { |
|
2769 TSize size = iCachedRenderBuffers[i]->iCanvasRenderBuffer->Size(); |
|
2770 RDebug::Print(_L("-- Cached render buffer: %ix%i, users=%i --"), size.iWidth, size.iHeight, iCachedRenderBuffers[i]->iActiveUsers.Count()); |
|
2771 totalPixelsForRenderBuffers += size.iWidth * size.iHeight; |
|
2772 } |
|
2773 else |
|
2774 { |
|
2775 RDebug::Print(_L("-- Cached render buffer: 0x0, users=%i --"), iCachedRenderBuffers[i]->iActiveUsers.Count()); |
|
2776 } |
|
2777 } |
|
2778 RDebug::Print(_L("-- Estimated canvas render buffer mem usage with 32bpp %i KBytes --"), totalPixelsForRenderBuffers*4 / 1024); |
|
2779 |
|
2780 TInt totalAllocSize = 0; |
|
2781 User::AllocSize(totalAllocSize); |
|
2782 RDebug::Print(_L("-- User::AllocSize = %i"), totalAllocSize); |
|
2783 |
|
2784 RDebug::Print(_L("-- CHuiCanvasTextureCache::AdvanceTime: end --")); |
|
2785 #endif |
|
2786 } |
|
2787 |
|
2788 // --------------------------------------------------------------------------- |
|
2789 // |
|
2790 // --------------------------------------------------------------------------- |
|
2791 // |
|
2792 void CHuiCanvasTextureCache::FindUnusedImageEntries(RPointerArray<CHuiCanvasGraphicImage>& aIndexEntries) |
|
2793 { |
|
2794 for(TInt i=iCachedImages.Count() - 1; i >= 0; i--) |
|
2795 { |
|
2796 CHuiCanvasGraphicImage* entry = iCachedImages[i]; |
|
2797 if (!entry->iActiveUsers.Count()) |
|
2798 { |
|
2799 aIndexEntries.InsertInOrderAllowRepeats(entry, ImageTimeOrderFunc); |
|
2800 } |
|
2801 } |
|
2802 } |
|
2803 |
|
2804 // --------------------------------------------------------------------------- |
|
2805 // |
|
2806 // --------------------------------------------------------------------------- |
|
2807 // |
|
2808 void CHuiCanvasTextureCache::FindUnusedTextEntries(RPointerArray<CHuiCanvasTextImage>& aIndexEntries) |
|
2809 { |
|
2810 for(TInt i=iCachedTexts.Count() - 1; i >= 0; i--) |
|
2811 { |
|
2812 CHuiCanvasTextImage* entry = iCachedTexts[i]; |
|
2813 |
|
2814 if (!entry->iActiveUsers.Count()) |
|
2815 { |
|
2816 aIndexEntries.InsertInOrderAllowRepeats(entry, TextTimeOrderFunc); |
|
2817 } |
|
2818 } |
|
2819 } |
|
2820 |
|
2821 // --------------------------------------------------------------------------- |
|
2822 // |
|
2823 // --------------------------------------------------------------------------- |
|
2824 // |
|
2825 void CHuiCanvasTextureCache::FindUnusedRenderBufferEntries(RPointerArray<CHuiCanvasRenderBufferImage>& aIndexEntries) |
|
2826 { |
|
2827 for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--) |
|
2828 { |
|
2829 CHuiCanvasRenderBufferImage* entry = iCachedRenderBuffers[i]; |
|
2830 |
|
2831 if (!entry->iActiveUsers.Count()) |
|
2832 { |
|
2833 aIndexEntries.InsertInOrderAllowRepeats(entry, RenderBufferTimeOrderFunc); |
|
2834 } |
|
2835 } |
|
2836 } |
|
2837 |
|
2838 |
|
2839 // --------------------------------------------------------------------------- |
|
2840 // |
|
2841 // --------------------------------------------------------------------------- |
|
2842 // |
|
2843 void CHuiCanvasTextureCache::DeleteUnusedImageEntries(RPointerArray<CHuiCanvasGraphicImage>& aIndexEntries) |
|
2844 { |
|
2845 // Remove given entries |
|
2846 for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--) |
|
2847 { |
|
2848 TInt indexEntry = iCachedImages.FindInOrder(aIndexEntries[i], ImageOrderFunc); |
|
2849 if (indexEntry != KErrNotFound) |
|
2850 { |
|
2851 CHuiCanvasGraphicImage* entry = iCachedImages[indexEntry]; |
|
2852 iCachedImages.Remove(indexEntry); |
|
2853 delete entry; |
|
2854 } |
|
2855 } |
|
2856 } |
|
2857 |
|
2858 // --------------------------------------------------------------------------- |
|
2859 // |
|
2860 // --------------------------------------------------------------------------- |
|
2861 // |
|
2862 void CHuiCanvasTextureCache::DeleteUnusedTextEntries(RPointerArray<CHuiCanvasTextImage>& aIndexEntries) |
|
2863 { |
|
2864 // Remove given entries |
|
2865 for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--) |
|
2866 { |
|
2867 TInt indexEntry = iCachedTexts.FindInOrder(aIndexEntries[i], TextOrderFunc); |
|
2868 if (indexEntry != KErrNotFound) |
|
2869 { |
|
2870 CHuiCanvasTextImage* entry = iCachedTexts[indexEntry]; |
|
2871 iCachedTexts.Remove(indexEntry); |
|
2872 delete entry; |
|
2873 } |
|
2874 } |
|
2875 } |
|
2876 |
|
2877 // --------------------------------------------------------------------------- |
|
2878 // |
|
2879 // --------------------------------------------------------------------------- |
|
2880 // |
|
2881 void CHuiCanvasTextureCache::DeleteUnusedRenderBufferEntries(RPointerArray<CHuiCanvasRenderBufferImage>& aIndexEntries) |
|
2882 { |
|
2883 // Remove given entries |
|
2884 for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--) |
|
2885 { |
|
2886 TInt indexEntry = iCachedRenderBuffers.FindInOrder(aIndexEntries[i], RenderBufferOrderFunc); |
|
2887 if (indexEntry != KErrNotFound) |
|
2888 { |
|
2889 CHuiCanvasRenderBufferImage* entry = iCachedRenderBuffers[indexEntry]; |
|
2890 iCachedRenderBuffers.Remove(indexEntry); |
|
2891 delete entry; |
|
2892 } |
|
2893 } |
|
2894 } |
|
2895 |
|
2896 |
|
2897 // --------------------------------------------------------------------------- |
|
2898 // |
|
2899 // --------------------------------------------------------------------------- |
|
2900 // |
|
2901 void CHuiCanvasTextureCache::SelectPreservedUnusedImageEntries(RPointerArray<CHuiCanvasGraphicImage>& aIndexEntries) |
|
2902 { |
|
2903 TInt totalUnusedTextureBytes = 0; |
|
2904 |
|
2905 // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows |
|
2906 for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--) |
|
2907 { |
|
2908 // Always delete bitmaps from unused entries, we can again duplicate pointers from handles when needed. |
|
2909 // Pointers are kept only for perfromance reasons. |
|
2910 CHuiCanvasGraphicImage* entry = aIndexEntries[i]; |
|
2911 |
|
2912 delete entry->iBitmap; |
|
2913 entry->iBitmap = NULL; |
|
2914 |
|
2915 delete entry->iMask; |
|
2916 entry->iMask = NULL; |
|
2917 |
|
2918 for (TInt j=0; j < entry->iSubImages.Count(); j++) |
|
2919 { |
|
2920 delete entry->iSubImages[j].iBitmap; |
|
2921 entry->iSubImages[j].iBitmap = NULL; |
|
2922 |
|
2923 delete entry->iSubImages[j].iMask; |
|
2924 entry->iSubImages[j].iMask = NULL; |
|
2925 } |
|
2926 |
|
2927 TSize textureSize = entry->iTexture->Size(); |
|
2928 TInt textureEstimatedSizeInBytes = textureSize.iWidth * textureSize.iHeight * KHuiCanvasImageEstimatedBpp/8.f; |
|
2929 |
|
2930 if (totalUnusedTextureBytes + textureEstimatedSizeInBytes < iUnusedCanvasImageTextureCacheSizeInKBytes*1024) |
|
2931 { |
|
2932 // Fits in the cache, remove from unused list, but keep zero size textures |
|
2933 if (textureEstimatedSizeInBytes != 0) |
|
2934 { |
|
2935 aIndexEntries.Remove(i); |
|
2936 } |
|
2937 } |
|
2938 |
|
2939 totalUnusedTextureBytes += textureEstimatedSizeInBytes; |
|
2940 } |
|
2941 } |
|
2942 |
|
2943 // --------------------------------------------------------------------------- |
|
2944 // |
|
2945 // --------------------------------------------------------------------------- |
|
2946 // |
|
2947 void CHuiCanvasTextureCache::SelectPreservedUnusedTextEntries(RPointerArray<CHuiCanvasTextImage>& aIndexEntries) |
|
2948 { |
|
2949 TInt totalUnusedTextureBytes = 0; |
|
2950 |
|
2951 // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows |
|
2952 for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--) |
|
2953 { |
|
2954 TSize textureSize = aIndexEntries[i]->iTexture->Size(); |
|
2955 TInt textureEstimatedSizeInBytes = textureSize.iWidth * textureSize.iHeight * KHuiCanvasTextEstimatedBpp/8.f; |
|
2956 |
|
2957 if (totalUnusedTextureBytes + textureEstimatedSizeInBytes < iUnusedCanvasTextTextureCacheSizeInKBytes*1024) |
|
2958 { |
|
2959 // Fits in the cache, remove from unused list, but keep zero size textures |
|
2960 if (textureEstimatedSizeInBytes != 0) |
|
2961 { |
|
2962 aIndexEntries.Remove(i); |
|
2963 } |
|
2964 } |
|
2965 |
|
2966 totalUnusedTextureBytes += textureEstimatedSizeInBytes; |
|
2967 } |
|
2968 } |
|
2969 |
|
2970 // --------------------------------------------------------------------------- |
|
2971 // |
|
2972 // --------------------------------------------------------------------------- |
|
2973 // |
|
2974 void CHuiCanvasTextureCache::SelectPreservedUnusedRenderBufferEntries(RPointerArray<CHuiCanvasRenderBufferImage>& aIndexEntries) |
|
2975 { |
|
2976 TInt totalUnusedRenderBufferBytes = 0; |
|
2977 |
|
2978 // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows |
|
2979 for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--) |
|
2980 { |
|
2981 CHuiCanvasRenderBufferImage* entry = aIndexEntries[i]; |
|
2982 if (entry->iCanvasRenderBuffer) |
|
2983 { |
|
2984 TSize renderBufferSize = entry->iCanvasRenderBuffer->Size(); |
|
2985 TInt renderBufferEstimatedSizeInBytes = renderBufferSize.iWidth * renderBufferSize.iHeight * KHuiCanvasRenderBufferEstimatedBpp/8.f; |
|
2986 |
|
2987 if (totalUnusedRenderBufferBytes + renderBufferEstimatedSizeInBytes < iUnusedCanvasRenderBufferCacheSizeInKBytes*1024) |
|
2988 { |
|
2989 aIndexEntries.Remove(i); |
|
2990 } |
|
2991 totalUnusedRenderBufferBytes += renderBufferEstimatedSizeInBytes; |
|
2992 } |
|
2993 else |
|
2994 { |
|
2995 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE |
|
2996 RDebug::Print(_L("CHuiCanvasTextureCache::PurgeUnusedRenderBufferEntries: Non existing render buffer, Render does not support canvas render buffers ?")); |
|
2997 #endif |
|
2998 } |
|
2999 } |
|
3000 } |
|
3001 |
|
3002 |
|
3003 |
|
3004 // --------------------------------------------------------------------------- |
|
3005 // |
|
3006 // --------------------------------------------------------------------------- |
|
3007 // |
|
3008 void CHuiCanvasTextureCache::HandleOutOfTextureMemory() |
|
3009 { |
|
3010 RDebug::Print(_L("CHuiCanvasTextureCache::HandleOutOfTextureMemory: Out of memory happened !")); |
|
3011 |
|
3012 DeleteAllReleasedEntries(EFalse); |
|
3013 |
|
3014 // TODO: Who you gonna call when texture memory is full and we cannot ourself |
|
3015 // delete anymore textures ? |
|
3016 // |
|
3017 // Grim reaper ?! |
|
3018 // |
|
3019 } |
|
3020 |
|
3021 // --------------------------------------------------------------------------- |
|
3022 // |
|
3023 // --------------------------------------------------------------------------- |
|
3024 // |
|
3025 void CHuiCanvasTextureCache::CalculateGraphicsMemoryUsage() |
|
3026 { |
|
3027 // TODO: This should handle NVG textures |
|
3028 |
|
3029 if (iMaxTextureMemoryInKBytes) |
|
3030 { |
|
3031 // How much all alfred textures use memory currently, this include alf apps and all canvas textures |
|
3032 TInt totalUsedTextureMemoryInKBytes = CHuiStatic::Env().TextureManager().EstimatedTextureMemUsage(KHuiTextureEstimatedBpp) / 1024; |
|
3033 |
|
3034 // How much there are unused textures cached currently |
|
3035 TInt totalUnusedCanvasTextureMemoryUsageInKBytes = CalculateUnusedCanvasTextureUsageInKbytes(); |
|
3036 |
|
3037 // Calculate how much there is space for unused textures |
|
3038 TInt availableCacheSizeInKBytes = iMaxTextureMemoryInKBytes - (totalUsedTextureMemoryInKBytes - totalUnusedCanvasTextureMemoryUsageInKBytes); |
|
3039 |
|
3040 // Divide available space for unused textures between texts and images using defined ratio |
|
3041 if (availableCacheSizeInKBytes > 0) |
|
3042 { |
|
3043 iUnusedCanvasTextTextureCacheSizeInKBytes = availableCacheSizeInKBytes * KHuiCanvasUnusedTextImageCacheRatio; |
|
3044 iUnusedCanvasImageTextureCacheSizeInKBytes = availableCacheSizeInKBytes * (1.f - KHuiCanvasUnusedTextImageCacheRatio); |
|
3045 } |
|
3046 else |
|
3047 { |
|
3048 iUnusedCanvasTextTextureCacheSizeInKBytes = 0; |
|
3049 iUnusedCanvasImageTextureCacheSizeInKBytes = 0; |
|
3050 } |
|
3051 } |
|
3052 else |
|
3053 { |
|
3054 iUnusedCanvasTextTextureCacheSizeInKBytes = 0; |
|
3055 iUnusedCanvasImageTextureCacheSizeInKBytes = 0; |
|
3056 } |
|
3057 |
|
3058 if (iMaxRenderBufferMemoryInKBytes) |
|
3059 { |
|
3060 // How much there are render buffers cached currently |
|
3061 TInt totalInKBytes = CalculateTotalCanvasRenderBufferUsageInKbytes(); |
|
3062 |
|
3063 // How much available for unused |
|
3064 TInt availableCacheSizeInKBytes = iMaxRenderBufferMemoryInKBytes - totalInKBytes; |
|
3065 |
|
3066 if (availableCacheSizeInKBytes > 0) |
|
3067 { |
|
3068 iUnusedCanvasRenderBufferCacheSizeInKBytes = iMaxRenderBufferMemoryInKBytes - totalInKBytes; |
|
3069 } |
|
3070 else |
|
3071 { |
|
3072 iUnusedCanvasRenderBufferCacheSizeInKBytes = 0; |
|
3073 } |
|
3074 } |
|
3075 else |
|
3076 { |
|
3077 iUnusedCanvasRenderBufferCacheSizeInKBytes = 0; |
|
3078 } |
|
3079 |
|
3080 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE |
|
3081 RDebug::Print(_L("-- CHuiCanvasTextureCache::CalculateTextureUsage: iUnusedCanvasTextTextureCacheSizeInKBytes = %i"), iUnusedCanvasTextTextureCacheSizeInKBytes); |
|
3082 RDebug::Print(_L("-- CHuiCanvasTextureCache::CalculateTextureUsage: iUnusedCanvasImageTextureCacheSizeInKBytes = %i"), iUnusedCanvasImageTextureCacheSizeInKBytes); |
|
3083 RDebug::Print(_L("-- CHuiCanvasTextureCache::CalculateTextureUsage: iUnusedCanvasRenderBufferCacheSizeInKBytes = %i"), iUnusedCanvasRenderBufferCacheSizeInKBytes); |
|
3084 #endif |
|
3085 } |
|
3086 |
|
3087 void CHuiCanvasTextureCache::EnableTouchCountCheck(TBool aEnable) |
|
3088 { |
|
3089 iTouchCountCheckEnabled = aEnable; |
|
3090 } |
|
3091 |
|
3092 TBool CHuiCanvasTextureCache::IsTouchCountCheckEnabled() |
|
3093 { |
|
3094 return iTouchCountCheckEnabled; |
|
3095 } |
|
3096 |
|
3097 // --------------------------------------------------------------------------- |
|
3098 // |
|
3099 // --------------------------------------------------------------------------- |
|
3100 // |
|
3101 TInt CHuiCanvasTextureCache::CalculateUnusedCanvasTextureUsageInKbytes() |
|
3102 { |
|
3103 // TODO: This should handle NVG textures |
|
3104 |
|
3105 TInt totalUnusedTextureBytes = 0; |
|
3106 |
|
3107 // Texts |
|
3108 RPointerArray<CHuiCanvasTextImage> textEntries; |
|
3109 |
|
3110 FindUnusedTextEntries(textEntries); |
|
3111 |
|
3112 for(TInt i=textEntries.Count() - 1; i >= 0; i--) |
|
3113 { |
|
3114 TSize textureSize = textEntries[i]->iTexture->Size(); |
|
3115 totalUnusedTextureBytes += textureSize.iWidth * textureSize.iHeight * KHuiCanvasTextEstimatedBpp/8.f; |
|
3116 } |
|
3117 |
|
3118 textEntries.Close(); |
|
3119 |
|
3120 // Images |
|
3121 RPointerArray<CHuiCanvasGraphicImage> imageEntries; |
|
3122 |
|
3123 FindUnusedImageEntries(imageEntries); |
|
3124 |
|
3125 for(TInt i=imageEntries.Count() - 1; i >= 0; i--) |
|
3126 { |
|
3127 TSize textureSize = imageEntries[i]->iTexture->Size(); |
|
3128 totalUnusedTextureBytes += textureSize.iWidth * textureSize.iHeight * KHuiCanvasImageEstimatedBpp/8.f; |
|
3129 } |
|
3130 |
|
3131 imageEntries.Close(); |
|
3132 |
|
3133 return totalUnusedTextureBytes/1024; |
|
3134 } |
|
3135 |
|
3136 // --------------------------------------------------------------------------- |
|
3137 // |
|
3138 // --------------------------------------------------------------------------- |
|
3139 // |
|
3140 TInt CHuiCanvasTextureCache::CalculateUnusedCanvasRenderBufferUsageInKbytes() |
|
3141 { |
|
3142 TInt totalUnusedRenderBufferBytes = 0; |
|
3143 |
|
3144 RPointerArray<CHuiCanvasRenderBufferImage> entries; |
|
3145 |
|
3146 FindUnusedRenderBufferEntries(entries); |
|
3147 |
|
3148 for(TInt i=entries.Count() - 1; i >= 0; i--) |
|
3149 { |
|
3150 if (iCachedRenderBuffers[i]->iCanvasRenderBuffer) |
|
3151 { |
|
3152 TSize renderBufferSize = entries[i]->iCanvasRenderBuffer->Size(); |
|
3153 totalUnusedRenderBufferBytes += renderBufferSize.iWidth * renderBufferSize.iHeight * KHuiCanvasRenderBufferEstimatedBpp/8.f; |
|
3154 } |
|
3155 } |
|
3156 |
|
3157 entries.Close(); |
|
3158 |
|
3159 return totalUnusedRenderBufferBytes/1024; |
|
3160 } |
|
3161 |
|
3162 // --------------------------------------------------------------------------- |
|
3163 // |
|
3164 // --------------------------------------------------------------------------- |
|
3165 // |
|
3166 TInt CHuiCanvasTextureCache::CalculateTotalCanvasRenderBufferUsageInKbytes() |
|
3167 { |
|
3168 TInt totalRenderBufferBytes = 0; |
|
3169 for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--) |
|
3170 { |
|
3171 if (iCachedRenderBuffers[i]->iCanvasRenderBuffer) |
|
3172 { |
|
3173 TSize renderBufferSize = iCachedRenderBuffers[i]->iCanvasRenderBuffer->Size(); |
|
3174 totalRenderBufferBytes += renderBufferSize.iWidth * renderBufferSize.iHeight * KHuiCanvasRenderBufferEstimatedBpp/8.f; |
|
3175 } |
|
3176 } |
|
3177 return totalRenderBufferBytes/1024; |
|
3178 } |
|
3179 |
|
3180 |
|
3181 // --------------------------------------------------------------------------- |
|
3182 // |
|
3183 // --------------------------------------------------------------------------- |
|
3184 // |
|
3185 CHuiTexture* CHuiCanvasTextureCache::CreateRecycledTextureL() |
|
3186 { |
|
3187 CHuiTexture* texture = NULL; |
|
3188 if (iRecycledTextures.Count()) |
|
3189 { |
|
3190 // If there are recycled textures, use one of those |
|
3191 TInt last = iRecycledTextures.Count() - 1; |
|
3192 texture = iRecycledTextures[last]; |
|
3193 iRecycledTextures.Remove(last); |
|
3194 } |
|
3195 else |
|
3196 { |
|
3197 // No recycled textures available, create new one |
|
3198 texture = CHuiTexture::NewL(); |
|
3199 } |
|
3200 return texture; |
|
3201 } |
|
3202 |
|
3203 // --------------------------------------------------------------------------- |
|
3204 // |
|
3205 // --------------------------------------------------------------------------- |
|
3206 // |
|
3207 void CHuiCanvasTextureCache::DeleteRecycledTexture(CHuiTexture* aTexture) |
|
3208 { |
|
3209 aTexture->Reset(); |
|
3210 |
|
3211 TInt error = KErrNone; |
|
3212 |
|
3213 if (iRecycledTextures.Count() < KHuiMaxRecycledTextureCount) |
|
3214 { |
|
3215 error = iRecycledTextures.Append(aTexture); |
|
3216 if (error) |
|
3217 { |
|
3218 delete aTexture; |
|
3219 } |
|
3220 } |
|
3221 else |
|
3222 { |
|
3223 delete aTexture; |
|
3224 } |
|
3225 } |
|
3226 |
|
3227 // --------------------------------------------------------------------------- |
|
3228 // |
|
3229 // --------------------------------------------------------------------------- |
|
3230 // |
|
3231 CHuiCanvasRenderBuffer* CHuiCanvasTextureCache::CreateCachedRenderBufferL(const CHuiCanvasVisual& aUser, TSize aSizeHint) |
|
3232 { |
|
3233 if (IsLowMemoryStateEnabled()) |
|
3234 { |
|
3235 // No canvas render buffers created in low memory state |
|
3236 return NULL; |
|
3237 } |
|
3238 |
|
3239 TInt cachedEntry = KErrNotFound; |
|
3240 CHuiCanvasRenderBufferImage* newRenderBufferEntry = NULL; |
|
3241 |
|
3242 iSearchedRenderBufferImageEntry->Reset(); |
|
3243 iSearchedRenderBufferImageEntry->iOwner = (TAny*)&aUser; |
|
3244 |
|
3245 cachedEntry = iCachedRenderBuffers.FindInOrder(iSearchedRenderBufferImageEntry, RenderBufferOrderFunc); |
|
3246 |
|
3247 if (cachedEntry == KErrNotFound) |
|
3248 { |
|
3249 // Try first getting reused render buffer |
|
3250 newRenderBufferEntry = ReUseReleasedRenderBuffer(aSizeHint); |
|
3251 |
|
3252 // Create new entry object if needed |
|
3253 if (!newRenderBufferEntry) |
|
3254 { |
|
3255 newRenderBufferEntry = new (ELeave) CHuiCanvasRenderBufferImage; |
|
3256 } |
|
3257 |
|
3258 // Copy attributes (only iOwner attribute) |
|
3259 newRenderBufferEntry->iOwner = iSearchedRenderBufferImageEntry->iOwner; |
|
3260 |
|
3261 CleanupStack::PushL(newRenderBufferEntry); |
|
3262 |
|
3263 // Create new render buffer |
|
3264 if (!newRenderBufferEntry->iCanvasRenderBuffer) |
|
3265 { |
|
3266 newRenderBufferEntry->iCanvasRenderBuffer = iCanvasGc->CreateRenderBufferL(TSize(0,0)); |
|
3267 } |
|
3268 |
|
3269 // Insert to cache array |
|
3270 TInt insertSuccess = iCachedRenderBuffers.InsertInOrder(newRenderBufferEntry, RenderBufferOrderFunc); |
|
3271 __ASSERT_DEBUG( !insertSuccess, USER_INVARIANT() ); |
|
3272 User::LeaveIfError( insertSuccess ); |
|
3273 |
|
3274 // We don't know which index it got, so look it up |
|
3275 cachedEntry = iCachedRenderBuffers.FindInOrder(newRenderBufferEntry, RenderBufferOrderFunc); |
|
3276 |
|
3277 CleanupStack::Pop(newRenderBufferEntry); |
|
3278 } |
|
3279 else |
|
3280 { |
|
3281 // If it was found, great. |
|
3282 } |
|
3283 |
|
3284 iCachedRenderBuffers[cachedEntry]->RefreshUser(aUser); |
|
3285 |
|
3286 return iCachedRenderBuffers[cachedEntry]->iCanvasRenderBuffer; |
|
3287 } |
|
3288 |
|
3289 // --------------------------------------------------------------------------- |
|
3290 // |
|
3291 // --------------------------------------------------------------------------- |
|
3292 // |
|
3293 CHuiCanvasRenderBuffer* CHuiCanvasTextureCache::FindCachedRenderBuffer(const CHuiCanvasVisual& aUser) |
|
3294 { |
|
3295 TInt cachedEntry = KErrNotFound; |
|
3296 |
|
3297 iSearchedRenderBufferImageEntry->Reset(); |
|
3298 iSearchedRenderBufferImageEntry->iOwner = (TAny*)&aUser; |
|
3299 |
|
3300 cachedEntry = iCachedRenderBuffers.FindInOrder(iSearchedRenderBufferImageEntry, RenderBufferOrderFunc); |
|
3301 if (cachedEntry != KErrNotFound) |
|
3302 { |
|
3303 iCachedRenderBuffers[cachedEntry]->RefreshUser(aUser); |
|
3304 return iCachedRenderBuffers[cachedEntry]->iCanvasRenderBuffer; |
|
3305 } |
|
3306 else |
|
3307 { |
|
3308 return NULL; |
|
3309 } |
|
3310 } |
|
3311 |
|
3312 // --------------------------------------------------------------------------- |
|
3313 // |
|
3314 // --------------------------------------------------------------------------- |
|
3315 // |
|
3316 void CHuiCanvasTextureCache::ReleaseCachedRenderBuffer(const CHuiCanvasVisual& aUser) |
|
3317 { |
|
3318 TInt cachedEntry = KErrNotFound; |
|
3319 |
|
3320 iSearchedRenderBufferImageEntry->Reset(); |
|
3321 iSearchedRenderBufferImageEntry->iOwner = (TAny*)&aUser; |
|
3322 |
|
3323 cachedEntry = iCachedRenderBuffers.FindInOrder(iSearchedRenderBufferImageEntry, RenderBufferOrderFunc); |
|
3324 if (cachedEntry != KErrNotFound) |
|
3325 { |
|
3326 CHuiCanvasRenderBufferImage* releasedEntry = iCachedRenderBuffers[cachedEntry]; |
|
3327 iCachedRenderBuffers.Remove(cachedEntry); |
|
3328 releasedEntry->RemoveUser(aUser); |
|
3329 releasedEntry->iOwner = releasedEntry; // No real owner anymore, se it self as owner |
|
3330 |
|
3331 if(!IsLowMemoryStateEnabled()) |
|
3332 { |
|
3333 // re-insert released entry (new position in the array order because we clered iOwner) |
|
3334 TInt insertSuccess = iCachedRenderBuffers.InsertInOrder(releasedEntry, RenderBufferOrderFunc); |
|
3335 |
|
3336 if (insertSuccess != KErrNone) |
|
3337 { |
|
3338 // oh no re-insert failed, now we must delete the entry to avoid memory leak. |
|
3339 delete releasedEntry; |
|
3340 } |
|
3341 } |
|
3342 else |
|
3343 { |
|
3344 delete releasedEntry; |
|
3345 } |
|
3346 |
|
3347 iHasReleasedRenderBuffers = ETrue; |
|
3348 } |
|
3349 } |
|
3350 |
|
3351 // --------------------------------------------------------------------------- |
|
3352 // |
|
3353 // --------------------------------------------------------------------------- |
|
3354 // |
|
3355 CHuiCanvasRenderBufferImage* CHuiCanvasTextureCache::ReUseReleasedRenderBuffer(TSize aSizeHint) |
|
3356 { |
|
3357 if (aSizeHint == TSize(0,0)) |
|
3358 { |
|
3359 return NULL; |
|
3360 } |
|
3361 |
|
3362 for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--) |
|
3363 { |
|
3364 // Check if there are any released buffers with have requested size |
|
3365 if (!iCachedRenderBuffers[i]->IsAnyUser() && |
|
3366 iCachedRenderBuffers[i]->iCanvasRenderBuffer && |
|
3367 iCachedRenderBuffers[i]->iCanvasRenderBuffer->Size() == aSizeHint) |
|
3368 { |
|
3369 // Remove from array and return instance to caller |
|
3370 CHuiCanvasRenderBufferImage* reusedEntry = iCachedRenderBuffers[i]; |
|
3371 iCachedRenderBuffers.Remove(i); |
|
3372 return reusedEntry; |
|
3373 } |
|
3374 } |
|
3375 |
|
3376 return NULL; |
|
3377 } |
|
3378 |
|
3379 void CHuiCanvasTextureCache::EnableLowMemoryState(TBool aEnable) |
|
3380 { |
|
3381 // deprecated |
|
3382 } |
|
3383 |
|
3384 THuiMemoryLevel CHuiCanvasTextureCache::MemoryLevel() |
|
3385 { |
|
3386 return iMemoryLevel; |
|
3387 } |
|
3388 |
|
3389 void CHuiCanvasTextureCache::SetMemoryLevel(THuiMemoryLevel aLevel) |
|
3390 { |
|
3391 iMemoryLevel = aLevel; |
|
3392 |
|
3393 if (iMemoryLevel <= EHuiMemoryLevelLowest) |
|
3394 { |
|
3395 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
3396 RDebug::Print(_L("-- CHuiCanvasTextureCache::SetMemoryLevel: Enabling lowest memory state")); |
|
3397 #endif |
|
3398 |
|
3399 // Set cache sizes to minimum |
|
3400 iMaxTextureMemoryInKBytes = 0; |
|
3401 iMaxRenderBufferMemoryInKBytes = 0; |
|
3402 |
|
3403 // Delete images, even if they are in use |
|
3404 for(TInt i=iCachedImages.Count() - 1; i >= 0; i--) |
|
3405 { |
|
3406 CHuiCanvasGraphicImage* entry = iCachedImages[i]; |
|
3407 iCachedImages.Remove(i); |
|
3408 delete entry; |
|
3409 } |
|
3410 |
|
3411 // Delete texts, even if they are in use |
|
3412 for(TInt i=iCachedTexts.Count() - 1; i >= 0; i--) |
|
3413 { |
|
3414 CHuiCanvasTextImage* entry = iCachedTexts[i]; |
|
3415 iCachedTexts.Remove(i); |
|
3416 delete entry; |
|
3417 } |
|
3418 |
|
3419 |
|
3420 // Delete canvas render buffers, even if they are in use |
|
3421 for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--) |
|
3422 { |
|
3423 CHuiCanvasRenderBufferImage* entry = iCachedRenderBuffers[i]; |
|
3424 iCachedRenderBuffers.Remove(i); |
|
3425 delete entry; |
|
3426 } |
|
3427 } |
|
3428 else if (iMemoryLevel <= EHuiMemoryLevelLow) |
|
3429 { |
|
3430 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
3431 RDebug::Print(_L("-- CHuiCanvasTextureCache::SetMemoryLevel: Enabling low memory state")); |
|
3432 #endif |
|
3433 // Set cache sizes to minimum |
|
3434 iMaxTextureMemoryInKBytes = 0; |
|
3435 iMaxRenderBufferMemoryInKBytes = 0; |
|
3436 |
|
3437 // Set flags to make sure we check all entries |
|
3438 iHasReleasedTexts = ETrue; |
|
3439 iHasReleasedImages = ETrue; |
|
3440 iHasReleasedRenderBuffers = ETrue; |
|
3441 |
|
3442 // Delete released cached entries |
|
3443 DeleteAllReleasedEntries(EFalse); |
|
3444 |
|
3445 // Delete canvas render buffers, even if they are in use |
|
3446 for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--) |
|
3447 { |
|
3448 CHuiCanvasRenderBufferImage* entry = iCachedRenderBuffers[i]; |
|
3449 iCachedRenderBuffers.Remove(i); |
|
3450 delete entry; |
|
3451 } |
|
3452 } |
|
3453 else |
|
3454 { |
|
3455 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL |
|
3456 RDebug::Print(_L("-- CHuiCanvasTextureCache::SetMemoryLevel: Disabling low memory state")); |
|
3457 #endif |
|
3458 |
|
3459 // TODO: This could be configurable cenrep or something ? |
|
3460 iMaxTextureMemoryInKBytes = KHuiMaxRecommendedTextureAmountInKBytes; |
|
3461 iMaxRenderBufferMemoryInKBytes = KHuiMaxRecommendedRenderBufferAmountInKBytes; |
|
3462 } |
|
3463 } |
|
3464 |
|
3465 TBool CHuiCanvasTextureCache::IsLowMemoryStateEnabled() const |
|
3466 { |
|
3467 if (iMemoryLevel < EHuiMemoryLevelReduced) |
|
3468 { |
|
3469 return ETrue; |
|
3470 } |
|
3471 else |
|
3472 { |
|
3473 return EFalse; |
|
3474 } |
|
3475 } |