|
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: Implementation for CHuiVg10Texture, OpenVG 1.0 Texture. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include <e32def.h> |
|
21 #include <e32math.h> |
|
22 |
|
23 #include "HuiVg10RenderPlugin.h" |
|
24 #include "HuiVg10Texture.h" |
|
25 #include "HuiVg10TextureManager.h" |
|
26 #include "uiacceltk/HuiTextureHandle.h" |
|
27 #include "uiacceltk/HuiEnv.h" |
|
28 #include "uiacceltk/HuiTextureManager.h" |
|
29 #include "uiacceltk/HuiTextureProcessor.h" |
|
30 #include "uiacceltk/HuiUtil.h" |
|
31 #include "uiacceltk/HuiPanic.h" |
|
32 |
|
33 // temporary hack until the openvg headers are fixed.. |
|
34 #ifndef OPENVG_VERSION_1_0_1 |
|
35 #warning using temporary hack to define OPENVG_VERSION_1_0_1, see TSW: SKYA-7QQB8 |
|
36 #define OPENVG_VERSION_1_0_1 |
|
37 #endif |
|
38 |
|
39 #ifdef __NVG |
|
40 #include <EGL/egl.h> |
|
41 #include <nvg.h> |
|
42 #include <AknIconUtils.h> |
|
43 #include "HuiRenderSurface.h" |
|
44 #include "NVGIcon.h" |
|
45 #endif |
|
46 |
|
47 |
|
48 /** |
|
49 * Bitmap color mode conversion. |
|
50 * |
|
51 * @param aBitmap Source bitmap to convert. |
|
52 * @param aDisplayMode Target display mode. |
|
53 * @param aCopyMode Desired copy behavior. |
|
54 * @returns a new bitmap with the desired display mode. |
|
55 */ |
|
56 static CFbsBitmap& ConvertBitmapL(const CFbsBitmap& aBitmap, TDisplayMode aDisplayMode, TBitmapCopyMode aCopyMode = EAllowDuplication, TSize aNewSize = TSize(0,0)) |
|
57 { |
|
58 // Functionality moved to Texture Manager |
|
59 // (to avoid recreating the bitmaps & bmpDevices every time) |
|
60 CHuiTextureManager& tmpMgr = CHuiStatic::Env().TextureManager(); |
|
61 CHuiVg10TextureManager& textureMgr = static_cast<CHuiVg10TextureManager&>(tmpMgr); |
|
62 |
|
63 return textureMgr.ConvertBitmapL(aBitmap, aDisplayMode, aCopyMode, aNewSize); |
|
64 } |
|
65 |
|
66 /** |
|
67 * Replace the alpha channel of an EColor16MA bitmap (in-place). |
|
68 * |
|
69 * @param aBitmap Destination bitmap. |
|
70 * @param aMaskBitmap Alpha channel source bitmap. |
|
71 */ |
|
72 static void ReplaceAlphaChannelL(CFbsBitmap& aBitmap, const CFbsBitmap& aMaskBitmap) |
|
73 { |
|
74 ASSERT(aBitmap.DisplayMode() == EColor16MA); |
|
75 ASSERT(aBitmap.SizeInPixels() == aMaskBitmap.SizeInPixels()); |
|
76 |
|
77 CFbsBitmap& convMask = ConvertBitmapL(aMaskBitmap, EGray256); |
|
78 |
|
79 aBitmap.BeginDataAccess(); |
|
80 convMask.BeginDataAccess(); |
|
81 TSize size = aBitmap.SizeInPixels(); |
|
82 TUint32* dest32 = (TUint32*)aBitmap.DataAddress(); |
|
83 const TUint8* src8 = (const TUint8*)convMask.DataAddress(); |
|
84 TInt destStride = CFbsBitmap::ScanLineLength(size.iWidth, aBitmap.DisplayMode()) >> 2; |
|
85 TInt srcStride = CFbsBitmap::ScanLineLength(size.iWidth, convMask.DisplayMode()); |
|
86 |
|
87 for (TInt y = 0; y < size.iHeight; y++) |
|
88 { |
|
89 TUint32* d = dest32; |
|
90 const TUint8* s = src8; |
|
91 |
|
92 for (TInt x = 0; x < size.iWidth; x++) |
|
93 { |
|
94 *d &= ~0xff000000; |
|
95 *d++ |= (*s++) << 24; |
|
96 } |
|
97 |
|
98 dest32 += destStride; |
|
99 src8 += srcStride; |
|
100 } |
|
101 |
|
102 aBitmap.EndDataAccess(); |
|
103 convMask.EndDataAccess(ETrue); |
|
104 } |
|
105 |
|
106 #if !defined(OPENVG_VERSION_1_0_1) |
|
107 /** |
|
108 * Convert a native Symbian EColor16MU/A bitmap to an OpenVG 1.0 equivalent (in-place). |
|
109 * |
|
110 * @param aBitmap Bitmap to convert. |
|
111 */ |
|
112 static void ConvertPixelComponentOrdering(CFbsBitmap& aBitmap) |
|
113 { |
|
114 ASSERT(aBitmap.DisplayMode() == EColor16MA || aBitmap.DisplayMode() == EColor16MU); |
|
115 |
|
116 aBitmap.BeginDataAccess(); |
|
117 TSize size = aBitmap.SizeInPixels(); |
|
118 TUint32* dest32 = (TUint32*)aBitmap.DataAddress(); |
|
119 TInt destStride = CFbsBitmap::ScanLineLength(size.iWidth, aBitmap.DisplayMode()) >> 2; |
|
120 |
|
121 for (TInt y = 0; y < size.iHeight; y++) |
|
122 { |
|
123 TUint32* d = dest32; |
|
124 |
|
125 for (TInt x = 0; x < size.iWidth; x++) |
|
126 { |
|
127 *d++ = (*d << 8) | ((*d & 0xff000000) >> 24); |
|
128 } |
|
129 |
|
130 dest32 += destStride; |
|
131 } |
|
132 aBitmap.EndDataAccess(); |
|
133 } |
|
134 #endif |
|
135 |
|
136 /* Vg10Texture internal flags. */ |
|
137 enum |
|
138 { |
|
139 /** Content has been uploaded. */ |
|
140 EFlagHasContent = 0x1, |
|
141 |
|
142 /** The texture has an alpha channel. */ |
|
143 EFlagHasAlpha = 0x2 |
|
144 }; |
|
145 |
|
146 |
|
147 CHuiVg10Texture* CHuiVg10Texture::NewL(CHuiVg10RenderPlugin& aRenderPlugin, const THuiTextureHandle* aExistingTexture) |
|
148 { |
|
149 CHuiVg10Texture* self = CHuiVg10Texture::NewLC(aRenderPlugin, aExistingTexture); |
|
150 CleanupStack::Pop(self); |
|
151 return self; |
|
152 } |
|
153 |
|
154 |
|
155 CHuiVg10Texture* CHuiVg10Texture::NewLC(CHuiVg10RenderPlugin& aRenderPlugin, const THuiTextureHandle* aExistingTexture) |
|
156 { |
|
157 CHuiVg10Texture* self = new (ELeave) CHuiVg10Texture(aRenderPlugin); |
|
158 CleanupStack::PushL(self); |
|
159 self->ConstructL(aExistingTexture); |
|
160 return self; |
|
161 } |
|
162 |
|
163 |
|
164 CHuiVg10Texture::CHuiVg10Texture(CHuiVg10RenderPlugin& aRenderPlugin) |
|
165 : iRenderPlugin(aRenderPlugin), |
|
166 iInternalFlags(0), |
|
167 iShadowEnabled(EFalse) |
|
168 { |
|
169 } |
|
170 |
|
171 |
|
172 void CHuiVg10Texture::ConstructL(const THuiTextureHandle* aExistingTexture) |
|
173 { |
|
174 CHuiTexture::BaseConstructL(); |
|
175 |
|
176 SetSegmentCountL(1); |
|
177 SetSegmentName(0, 0); |
|
178 SetSegmentSize(0, TSize(0, 0)); |
|
179 SetSegmentTextureSize(0, TSize(0, 0)); |
|
180 |
|
181 if(aExistingTexture) |
|
182 { |
|
183 // Take over the existing texture (single named texture object). |
|
184 ASSERT(aExistingTexture->SegmentCount() == 1); |
|
185 ASSERT(SegmentCount() == 1); |
|
186 SetSegmentName(0, aExistingTexture->Name()); |
|
187 SetSegmentSize(0, aExistingTexture->SegmentSize(0)); |
|
188 SetSegmentTextureSize(0, aExistingTexture->SegmentTextureSize(0)); |
|
189 SetSize(aExistingTexture->Size()); |
|
190 |
|
191 // Copy attributes |
|
192 const CHuiVg10Texture* vgTex = reinterpret_cast<const CHuiVg10Texture*>(aExistingTexture); |
|
193 iInternalFlags = vgTex->iInternalFlags; |
|
194 // Note: shared shadows not supported |
|
195 } |
|
196 } |
|
197 |
|
198 |
|
199 CHuiVg10Texture::~CHuiVg10Texture() |
|
200 { |
|
201 Reset(); |
|
202 } |
|
203 |
|
204 |
|
205 TBool CHuiVg10Texture::HasAlpha() const |
|
206 { |
|
207 return (iInternalFlags & EFlagHasAlpha) != 0; |
|
208 } |
|
209 |
|
210 |
|
211 TBool CHuiVg10Texture::HasContent() const |
|
212 { |
|
213 if(!CHuiTexture::HasContent()) |
|
214 { |
|
215 return EFalse; |
|
216 } |
|
217 |
|
218 return (iInternalFlags & EFlagHasContent) != 0; |
|
219 } |
|
220 |
|
221 |
|
222 TSize CHuiVg10Texture::MaxTextureSize() const |
|
223 { |
|
224 if (iRenderPlugin.IsReleased()) |
|
225 { |
|
226 HUI_DEBUG(_L("CHuiVg10Texture::MaxTextureSize() - Vg10 context not available, cannot get maximum texture size, returning (0,0).")); |
|
227 return TSize(0,0); |
|
228 } |
|
229 |
|
230 int maxWidth = vgGeti(VG_MAX_IMAGE_WIDTH)-1; |
|
231 int maxHeight = vgGeti(VG_MAX_IMAGE_HEIGHT)-1; |
|
232 HUI_VG_INVARIANT(); |
|
233 ASSERT(maxWidth > 0 && maxHeight > 0); |
|
234 |
|
235 return TSize(maxWidth, maxHeight); |
|
236 } |
|
237 |
|
238 void CHuiVg10Texture::UploadL(const CFbsBitmap& aBitmap, |
|
239 const CFbsBitmap* aMaskBitmap, |
|
240 THuiTextureUploadFlags aTextureFlags) |
|
241 { |
|
242 Reset(); // Must delete old content before calling SetupSegmentsL |
|
243 |
|
244 TBool invalidMaskSize = (aMaskBitmap && (aBitmap.SizeInPixels() != aMaskBitmap->SizeInPixels())); |
|
245 |
|
246 CFbsBitmap* maskBitmap = (CFbsBitmap*)aMaskBitmap; |
|
247 |
|
248 if (invalidMaskSize) |
|
249 { |
|
250 maskBitmap = &ConvertBitmapL(*aMaskBitmap, aMaskBitmap->DisplayMode(), EAlwaysCopy, aBitmap.SizeInPixels()); |
|
251 } |
|
252 |
|
253 SetupSegmentsL(aBitmap.SizeInPixels(), aBitmap.SizeInPixels(), aTextureFlags); |
|
254 SegmentUploadL(0, aBitmap, maskBitmap, aTextureFlags); |
|
255 } |
|
256 |
|
257 void CHuiVg10Texture::UploadL(THuiTextureFormat aTextureFormat, |
|
258 const TSize& aTextureSize, |
|
259 const TUint8* aTextureBuffer, |
|
260 THuiTextureUploadFlags aTextureFlags, |
|
261 TUint aTextureBufferSize) |
|
262 { |
|
263 Reset(); // Must delete old content before calling SetupSegmentsL |
|
264 SetupSegmentsL(aTextureSize, aTextureSize, aTextureFlags); |
|
265 SegmentUploadL(0, aTextureFormat, aTextureSize, aTextureBuffer, aTextureBufferSize); |
|
266 } |
|
267 |
|
268 |
|
269 void CHuiVg10Texture::PartialUploadL(THuiTextureFormat aFormat, |
|
270 const TPoint& aOrigin, |
|
271 const TSize& aSize, |
|
272 const TUint8* aBuffer) |
|
273 { |
|
274 ASSERT(SegmentCount() == 1); |
|
275 SegmentPartialUpload(0, aFormat, aOrigin, aSize, aBuffer); |
|
276 } |
|
277 |
|
278 |
|
279 void CHuiVg10Texture::SegmentUploadL(TInt aSegment, |
|
280 const CFbsBitmap& aBitmap, |
|
281 const CFbsBitmap* aMaskBitmap, |
|
282 THuiTextureUploadFlags aFlags) |
|
283 { |
|
284 ASSERT(aSegment >= 0 && aSegment < SegmentCount()); |
|
285 ASSERT(aBitmap.SizeInPixels() == Size()); |
|
286 ASSERT(aMaskBitmap && aBitmap.SizeInPixels() == aMaskBitmap->SizeInPixels() || !aMaskBitmap); |
|
287 |
|
288 PushEGLContext(); |
|
289 if(aSegment < 0 || aSegment >= SegmentCount()) |
|
290 { |
|
291 User::Leave(KErrArgument); |
|
292 } |
|
293 |
|
294 // Clear any previous image data |
|
295 ResetSegment(aSegment); |
|
296 |
|
297 #ifdef __NVG |
|
298 // Check if the bitmap is extended and has NVG data |
|
299 TUid bitmaptype = aBitmap.ExtendedBitmapType(); |
|
300 TUid masktype = KNullUid; |
|
301 if (aMaskBitmap) |
|
302 { |
|
303 masktype = aMaskBitmap->ExtendedBitmapType(); |
|
304 // extended bitmap and mask |
|
305 if (bitmaptype == masktype && bitmaptype != KNullUid) |
|
306 { |
|
307 SegmentUploadNvgL(aBitmap, aMaskBitmap, aFlags); |
|
308 // We now have working texture data, no need to do anything else |
|
309 PopEGLContext(); |
|
310 return; |
|
311 } |
|
312 } |
|
313 else if (bitmaptype != KNullUid) |
|
314 { |
|
315 SegmentUploadNvgL(aBitmap, aMaskBitmap, aFlags); |
|
316 // We now have working texture data, no need to do anything else |
|
317 PopEGLContext(); |
|
318 return; |
|
319 } |
|
320 #endif |
|
321 |
|
322 VGImageFormat imageSourceFormat = (VGImageFormat)(-1); |
|
323 VGImageFormat imageInternalFormat = VG_sXRGB_8888; // TODO: get the most optimal image format from the renderer |
|
324 VGbitfield qualityFlags = VG_IMAGE_QUALITY_BETTER | VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_NONANTIALIASED; |
|
325 TBool hasAlpha = (aMaskBitmap != NULL); |
|
326 TBool conversionRequired = ETrue; |
|
327 TSize size = Size(); |
|
328 TSize textureSize = MaxTextureSize(); |
|
329 textureSize.iWidth = Min(size.iWidth, textureSize.iWidth); |
|
330 textureSize.iHeight = Min(size.iHeight, textureSize.iHeight); |
|
331 |
|
332 // See if there is a native color mode we could use without conversion |
|
333 switch (aBitmap.DisplayMode()) |
|
334 { |
|
335 case EGray256: |
|
336 imageSourceFormat = VG_A_8; |
|
337 conversionRequired = EFalse; |
|
338 break; |
|
339 case EColor64K: |
|
340 imageSourceFormat = VG_sRGB_565; |
|
341 conversionRequired = EFalse; |
|
342 break; |
|
343 case EColor4K: |
|
344 imageSourceFormat = VG_sRGB_565; |
|
345 conversionRequired = ETrue; |
|
346 break; |
|
347 #if defined(OPENVG_VERSION_1_0_1) |
|
348 case EColor16MU: |
|
349 imageSourceFormat = VG_sXRGB_8888; |
|
350 conversionRequired = EFalse; |
|
351 break; |
|
352 case EColor16M: |
|
353 imageSourceFormat = VG_sXRGB_8888; |
|
354 conversionRequired = ETrue; |
|
355 break; |
|
356 case EColor16MA: |
|
357 imageSourceFormat = VG_sARGB_8888; |
|
358 hasAlpha = ETrue; |
|
359 conversionRequired = EFalse; |
|
360 break; |
|
361 case EColor16MAP: |
|
362 imageSourceFormat = VG_sARGB_8888_PRE; |
|
363 hasAlpha = ETrue; |
|
364 conversionRequired = EFalse; |
|
365 break; |
|
366 #else // defined(OPENVG_VERSION_1_0_1) |
|
367 case EColor16MU: |
|
368 case EColor16M: |
|
369 imageSourceFormat = VG_sRGBX_8888; |
|
370 break; |
|
371 case EColor16MA: |
|
372 imageSourceFormat = VG_sRGBA_8888; |
|
373 hasAlpha = ETrue; |
|
374 break; |
|
375 case EColor16MAP: |
|
376 imageSourceFormat = VG_sRGBA_8888_PRE; |
|
377 hasAlpha = ETrue; |
|
378 break; |
|
379 #endif // defined(OPENVG_VERSION_1_0_1) |
|
380 default: |
|
381 #ifdef _DEBUG |
|
382 RDebug::Printf("CHuiVg10Texture::SegmentUploadL - unknown display mode %d", aBitmap.DisplayMode()); |
|
383 #endif |
|
384 conversionRequired = ETrue; |
|
385 imageSourceFormat = VG_sXRGB_8888; |
|
386 } |
|
387 |
|
388 if (aBitmap.IsCompressedInRAM() || aMaskBitmap) |
|
389 { |
|
390 conversionRequired = ETrue; |
|
391 } |
|
392 |
|
393 if (hasAlpha) |
|
394 { |
|
395 imageInternalFormat = VG_sRGBA_8888_PRE; |
|
396 } |
|
397 else |
|
398 { |
|
399 imageInternalFormat = imageSourceFormat; |
|
400 } |
|
401 |
|
402 // Create the actual image |
|
403 VGImage image = vgCreateImage(imageInternalFormat, textureSize.iWidth, textureSize.iHeight, qualityFlags); |
|
404 |
|
405 if (image == VG_INVALID_HANDLE) |
|
406 { |
|
407 User::Leave(KErrNoMemory); |
|
408 } |
|
409 |
|
410 if (!conversionRequired) |
|
411 { |
|
412 // No data conversion is required and we can upload the pixels as such |
|
413 aBitmap.BeginDataAccess(); |
|
414 const void* data = aBitmap.DataAddress(); |
|
415 TInt stride = CFbsBitmap::ScanLineLength(size.iWidth, aBitmap.DisplayMode()); |
|
416 vgImageSubData(image, data, stride, imageSourceFormat, 0, 0, textureSize.iWidth, textureSize.iHeight); |
|
417 aBitmap.EndDataAccess( ETrue ); |
|
418 } |
|
419 else |
|
420 { |
|
421 // One or more conversion steps are needed |
|
422 if (hasAlpha) |
|
423 { |
|
424 // Alpha channel needs to be accounted for |
|
425 #if defined(OPENVG_VERSION_1_0_1) |
|
426 imageSourceFormat = VG_sARGB_8888; |
|
427 CFbsBitmap& convBitmap = ConvertBitmapL(aBitmap, EColor16MA); |
|
428 #else // defined(OPENVG_VERSION_1_0_1) |
|
429 imageSourceFormat = VG_sRGBA_8888; |
|
430 CFbsBitmap& convBitmap = ConvertBitmapL(aBitmap, EColor16MA); |
|
431 #endif // defined(OPENVG_VERSION_1_0_1) |
|
432 |
|
433 // Bake the alpha channel into the converted bitmap |
|
434 if (aMaskBitmap) |
|
435 { |
|
436 if (aMaskBitmap->IsCompressedInRAM() || masktype != KNullUid) |
|
437 { |
|
438 CFbsBitmap& noncompressedMask = ConvertBitmapL(*aMaskBitmap, EGray256, EAlwaysCopy); |
|
439 ReplaceAlphaChannelL(convBitmap, noncompressedMask); |
|
440 } |
|
441 else |
|
442 { |
|
443 ReplaceAlphaChannelL(convBitmap, *aMaskBitmap); |
|
444 } |
|
445 } |
|
446 #if !defined(OPENVG_VERSION_1_0_1) |
|
447 // Match the native OpenVG 1.0 pixel component ordering |
|
448 ASSERT(convBitmap.Handle() != aBitmap.Handle()); |
|
449 ConvertPixelComponentOrdering(convBitmap); |
|
450 #endif |
|
451 convBitmap.BeginDataAccess(); |
|
452 const void* data = convBitmap.DataAddress(); |
|
453 TInt stride = CFbsBitmap::ScanLineLength(size.iWidth, convBitmap.DisplayMode()); |
|
454 vgImageSubData(image, data, stride, imageSourceFormat, 0, 0, textureSize.iWidth, textureSize.iHeight); |
|
455 convBitmap.EndDataAccess( ETrue ); |
|
456 } |
|
457 else |
|
458 { |
|
459 // No alpha channel -- just opaque pixel data |
|
460 #if defined(OPENVG_VERSION_1_0_1) |
|
461 TDisplayMode mode = EColor16MU; |
|
462 if (imageSourceFormat == VG_sRGB_565) |
|
463 { |
|
464 mode = EColor64K; |
|
465 } |
|
466 else if (imageSourceFormat == VG_A_8) |
|
467 { |
|
468 mode = EGray256; |
|
469 } |
|
470 else |
|
471 { |
|
472 imageSourceFormat = VG_sXRGB_8888; |
|
473 } |
|
474 CFbsBitmap& convBitmap = ConvertBitmapL(aBitmap, mode); |
|
475 #else // defined(OPENVG_VERSION_1_0_1) |
|
476 imageSourceFormat = VG_sRGBX_8888; |
|
477 CFbsBitmap& convBitmap = ConvertBitmapL(aBitmap, EColor16MU); |
|
478 |
|
479 // Match the native OpenVG 1.0 pixel component ordering |
|
480 ASSERT(convBitmap.Handle() != aBitmap.Handle()); |
|
481 ConvertPixelComponentOrdering(convBitmap); |
|
482 #endif // defined(OPENVG_VERSION_1_0_1) |
|
483 |
|
484 convBitmap.BeginDataAccess(); |
|
485 const void* data = convBitmap.DataAddress(); |
|
486 TInt stride = CFbsBitmap::ScanLineLength(size.iWidth, convBitmap.DisplayMode()); |
|
487 vgImageSubData(image, data, stride, imageSourceFormat, 0, 0, textureSize.iWidth, textureSize.iHeight); |
|
488 convBitmap.EndDataAccess( ETrue ); |
|
489 } |
|
490 } |
|
491 |
|
492 // Save the image handle |
|
493 SetSegmentName(0, (TUint)image); |
|
494 |
|
495 // The texture now has content. |
|
496 iInternalFlags |= EFlagHasContent; |
|
497 |
|
498 if (hasAlpha) |
|
499 { |
|
500 iInternalFlags |= EFlagHasAlpha; |
|
501 } |
|
502 |
|
503 // Keep the shadow in sync with the image contents |
|
504 if (IsShadowEnabled()) |
|
505 { |
|
506 // if this fails there is nothing we can do |
|
507 // There will be no shadow if something goes wrong here |
|
508 TRAP_IGNORE( GenerateShadowL() ); |
|
509 } |
|
510 PopEGLContext(); |
|
511 // Wake up refresh. It is likely that the new texture will be visible on |
|
512 // the screen. |
|
513 CHuiStatic::ContinueRefresh(); |
|
514 } |
|
515 |
|
516 static void ConvertBufferRgb888TosRGBX8888(const TUint8* aSrc, TUint8* aDest, TInt aCount) |
|
517 { |
|
518 while (aCount--) |
|
519 { |
|
520 *aDest++ = *aSrc++; |
|
521 *aDest++ = *aSrc++; |
|
522 *aDest++ = *aSrc++; |
|
523 *aDest++ = 0xff; |
|
524 } |
|
525 } |
|
526 |
|
527 static void ConvertBufferLa88TosRGBA8888(const TUint8* aSrc, TUint8* aDest, TInt aCount) |
|
528 { |
|
529 while (aCount--) |
|
530 { |
|
531 TUint8 l = *aSrc++; |
|
532 TUint8 a = *aSrc++; |
|
533 *aDest++ = l; |
|
534 *aDest++ = l; |
|
535 *aDest++ = l; |
|
536 *aDest++ = a; |
|
537 } |
|
538 } |
|
539 |
|
540 #if !defined(OPENVG_VERSION_1_0_1) |
|
541 static void ConvertBufferRgba8888TosRGBA8888(const TUint8* aSrc, TUint8* aDest, TInt aCount) |
|
542 { |
|
543 while (aCount--) |
|
544 { |
|
545 TUint8 r = *aSrc++; |
|
546 TUint8 g = *aSrc++; |
|
547 TUint8 b = *aSrc++; |
|
548 TUint8 a = *aSrc++; |
|
549 *aDest++ = a; |
|
550 *aDest++ = r; |
|
551 *aDest++ = g; |
|
552 *aDest++ = b; |
|
553 } |
|
554 } |
|
555 #endif |
|
556 |
|
557 void CHuiVg10Texture::SegmentClearL(TInt aSegment, |
|
558 TBool aWithAlpha, |
|
559 const TRgb& aColor, |
|
560 TUint8 aAlpha) |
|
561 { |
|
562 ASSERT(aSegment >= 0 && aSegment < SegmentCount()); |
|
563 |
|
564 if(aSegment < 0 || aSegment >= SegmentCount()) |
|
565 { |
|
566 User::Leave(KErrArgument); |
|
567 } |
|
568 |
|
569 // Clear any previous image data |
|
570 TSize size = Size(); |
|
571 ResetSegment(aSegment); |
|
572 |
|
573 // Create the actual image |
|
574 VGImageFormat imageInternalFormat = aWithAlpha ? VG_sRGBA_8888 : VG_sRGBX_8888; |
|
575 VGbitfield qualityFlags = VG_IMAGE_QUALITY_BETTER | VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_NONANTIALIASED; |
|
576 VGImage image = vgCreateImage(imageInternalFormat, size.iWidth, size.iHeight, qualityFlags); |
|
577 |
|
578 if (image == VG_INVALID_HANDLE) |
|
579 { |
|
580 User::Leave(KErrNoMemory); |
|
581 } |
|
582 |
|
583 // Set the clear color |
|
584 VGfloat scale = 1.0f / 255.0f; |
|
585 VGfloat color[] = { |
|
586 aColor.Red() * scale, |
|
587 aColor.Green() * scale, |
|
588 aColor.Blue() * scale, |
|
589 aWithAlpha ? (aAlpha * scale) : 1.0f |
|
590 }; |
|
591 |
|
592 vgSetfv(VG_CLEAR_COLOR, 4, color); |
|
593 vgClearImage(image, 0, 0, size.iWidth, size.iHeight); |
|
594 |
|
595 // The texture now has content. |
|
596 iInternalFlags |= EFlagHasContent; |
|
597 |
|
598 if (aWithAlpha) |
|
599 { |
|
600 iInternalFlags |= EFlagHasAlpha; |
|
601 } |
|
602 |
|
603 // Keep the shadow in sync with the image contents |
|
604 if (IsShadowEnabled()) |
|
605 { |
|
606 GenerateShadowL(); |
|
607 } |
|
608 |
|
609 HUI_VG_INVARIANT(); |
|
610 } |
|
611 |
|
612 void CHuiVg10Texture::SegmentUploadL(TInt aSegment, |
|
613 THuiTextureFormat aFormat, |
|
614 const TSize& aSize, |
|
615 const TUint8* aBuffer, |
|
616 TUint /*aBufferSize*/) |
|
617 { |
|
618 ASSERT(aSegment >= 0 && aSegment < SegmentCount()); |
|
619 ASSERT(aSize == Size()); |
|
620 |
|
621 SegmentPartialUploadInternal(aSegment, aFormat, TPoint(0, 0), aSize, aBuffer, ETrue); |
|
622 } |
|
623 |
|
624 void CHuiVg10Texture::SegmentPartialUpload( |
|
625 TInt aSegment, |
|
626 THuiTextureFormat aFormat, |
|
627 const TPoint& aOrigin, |
|
628 const TSize& aSize, |
|
629 const TUint8* aBuffer) |
|
630 { |
|
631 SegmentPartialUploadInternal(aSegment, aFormat, aOrigin, aSize, aBuffer, EFalse); |
|
632 } |
|
633 |
|
634 void CHuiVg10Texture::SegmentPartialUploadInternal( |
|
635 TInt aSegment, |
|
636 THuiTextureFormat aFormat, |
|
637 const TPoint& aOrigin, |
|
638 const TSize& aSize, |
|
639 const TUint8* aBuffer, |
|
640 TBool aCreateImage) |
|
641 { |
|
642 ASSERT(aSegment >= 0 && aSegment < SegmentCount()); |
|
643 |
|
644 if (aSegment < 0 || aSegment >= SegmentCount()) |
|
645 { |
|
646 // we return without doing anything because we are called by a non-leaving function |
|
647 return; |
|
648 } |
|
649 |
|
650 if (aOrigin.iX < 0 || aOrigin.iY < 0) |
|
651 { |
|
652 // we return without doing anything because we are called by a non-leaving function |
|
653 return; |
|
654 } |
|
655 |
|
656 HUI_DEBUG4(_L("CHuiVg10Texture::SegmentPartialUploadInternal() - Uploading partial image (%ix%i pixels, offset x: %i y: %i)."), |
|
657 aSize.iWidth, aSize.iHeight, aOrigin.iX, aOrigin.iY); |
|
658 |
|
659 VGImageFormat imageSourceFormat = (VGImageFormat)(-1); |
|
660 VGImageFormat imageInternalFormat = VG_sRGBX_8888; // TODO: get the most optimal image format from the renderer |
|
661 VGbitfield qualityFlags = VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER; // TODO: get this from hitchcock |
|
662 TBool hasAlpha = EFalse; |
|
663 TBool conversionRequired = ETrue; |
|
664 TInt sourceStride = 0; |
|
665 |
|
666 switch (aFormat) |
|
667 { |
|
668 case EHuiTextureFormatRgb565: |
|
669 imageSourceFormat = VG_sRGB_565; |
|
670 conversionRequired = EFalse; |
|
671 sourceStride = aSize.iWidth * 2; |
|
672 break; |
|
673 case EHuiTextureFormatRgb888: |
|
674 imageSourceFormat = VG_sRGBX_8888; |
|
675 sourceStride = aSize.iWidth * 4; |
|
676 break; |
|
677 case EHuiTextureFormatLa88: |
|
678 // We have to expand this format to RGBA, since there is no luminance-alpha format in OpenVG 1.0.1 |
|
679 imageSourceFormat = VG_sRGBA_8888; |
|
680 sourceStride = aSize.iWidth * 4; |
|
681 hasAlpha = ETrue; |
|
682 break; |
|
683 #if defined(OPENVG_VERSION_1_0_1) |
|
684 case EHuiTextureFormatRgba8888: |
|
685 imageSourceFormat = VG_sARGB_8888; |
|
686 conversionRequired = EFalse; |
|
687 hasAlpha = ETrue; |
|
688 sourceStride = aSize.iWidth * 4; |
|
689 break; |
|
690 #else // defined(OPENVG_VERSION_1_0_1) |
|
691 case EHuiTextureFormatRgba8888: |
|
692 imageSourceFormat = VG_sRGBA_8888; |
|
693 sourceStride = aSize.iWidth * 4; |
|
694 hasAlpha = ETrue; |
|
695 break; |
|
696 #endif // defined(OPENVG_VERSION_1_0_1) |
|
697 |
|
698 // Compressed formats are not supported |
|
699 default: |
|
700 // we return without doing anything because we are called by a non-leaving function |
|
701 return; |
|
702 } |
|
703 |
|
704 // Use a matching internal format |
|
705 imageInternalFormat = imageSourceFormat; |
|
706 |
|
707 // Create the actual image if required |
|
708 VGImage image = VG_INVALID_HANDLE; |
|
709 |
|
710 if (aCreateImage) |
|
711 { |
|
712 image = vgCreateImage(imageInternalFormat, aSize.iWidth, aSize.iHeight, qualityFlags); |
|
713 } |
|
714 else |
|
715 { |
|
716 image = (VGImage)SegmentName(0); |
|
717 |
|
718 // Verify the dimensions |
|
719 if (aOrigin.iX + aSize.iWidth >= Size().iWidth || |
|
720 aOrigin.iY + aSize.iHeight >= Size().iHeight) |
|
721 { |
|
722 // we return without doing anything because we are called by a non-leaving function |
|
723 return; |
|
724 } |
|
725 } |
|
726 |
|
727 if (image == VG_INVALID_HANDLE) |
|
728 { |
|
729 // we return without doing anything because we are called by a non-leaving function |
|
730 return; |
|
731 } |
|
732 |
|
733 if (!conversionRequired) |
|
734 { |
|
735 // No data conversion is required and we can upload the pixels as such |
|
736 vgImageSubData(image, aBuffer, sourceStride, imageSourceFormat, aOrigin.iX, aOrigin.iY, aSize.iWidth, aSize.iHeight); |
|
737 HUI_VG_INVARIANT(); |
|
738 } |
|
739 else |
|
740 { |
|
741 // One or more conversion steps are needed |
|
742 TInt pixels = aSize.iWidth * aSize.iHeight; |
|
743 TUint8* convBuffer = NULL; |
|
744 convBuffer = new TUint8[sourceStride * aSize.iHeight]; |
|
745 // there are no leaving functions until our buffer is deleted |
|
746 // We cannot put convBuffer onto cleanup stack because we cannot leave. |
|
747 |
|
748 if ( !convBuffer ) |
|
749 { |
|
750 // we return without doing anything because we are called by a non-leaving function |
|
751 return; |
|
752 } |
|
753 |
|
754 switch (aFormat) |
|
755 { |
|
756 case EHuiTextureFormatRgb888: |
|
757 ConvertBufferRgb888TosRGBX8888(aBuffer, convBuffer, pixels); |
|
758 break; |
|
759 case EHuiTextureFormatLa88: |
|
760 ConvertBufferLa88TosRGBA8888(aBuffer, convBuffer, pixels); |
|
761 break; |
|
762 #if !defined(OPENVG_VERSION_1_0_1) |
|
763 case EHuiTextureFormatRgba8888: |
|
764 ConvertBufferRgba8888TosRGBA8888(aBuffer, convBuffer, pixels); |
|
765 break; |
|
766 #endif // defined(OPENVG_VERSION_1_0_1) |
|
767 default: |
|
768 ASSERT(0); |
|
769 } |
|
770 |
|
771 vgImageSubData(image, convBuffer, sourceStride, imageSourceFormat, aOrigin.iX, aOrigin.iY, aSize.iWidth, aSize.iHeight); |
|
772 delete[] convBuffer; |
|
773 HUI_VG_INVARIANT(); |
|
774 } |
|
775 |
|
776 // Save the image handle |
|
777 SetSegmentName(0, (TUint)image); |
|
778 |
|
779 // The texture now has content. |
|
780 iInternalFlags |= EFlagHasContent; |
|
781 |
|
782 if (hasAlpha) |
|
783 { |
|
784 iInternalFlags |= EFlagHasAlpha; |
|
785 } |
|
786 |
|
787 // Keep the shadow in sync with the image contents |
|
788 if (IsShadowEnabled()) |
|
789 { |
|
790 // We cannot leave, we just try our best. |
|
791 // If this fails, we have no shadow |
|
792 TRAP_IGNORE( GenerateShadowL() ); |
|
793 } |
|
794 |
|
795 HUI_VG_INVARIANT(); |
|
796 } |
|
797 |
|
798 void CHuiVg10Texture::Reset() |
|
799 { |
|
800 CHuiTexture::Reset(); |
|
801 |
|
802 if (iShadow.Name()) |
|
803 { |
|
804 vgDestroyImage((VGImage)iShadow.Name()); |
|
805 iShadow.SetName(0); |
|
806 } |
|
807 |
|
808 iShadowEnabled = EFalse; |
|
809 |
|
810 #ifdef __NVG |
|
811 CHuiTexture::SetNvgContent(EFalse); |
|
812 iIsExtended = EFalse; |
|
813 |
|
814 delete iNVGData; |
|
815 iNVGData = NULL; |
|
816 delete iIconCommands; |
|
817 iIconCommands = NULL; |
|
818 #endif |
|
819 } |
|
820 |
|
821 void CHuiVg10Texture::ResetSegment(TInt aSegment) |
|
822 { |
|
823 HUI_DEBUG1(_L("CHuiVg10Texture::ResetSegment() - Trying to delete image for segment %i."), aSegment); |
|
824 HUI_VG_INVARIANT(); |
|
825 ASSERT(aSegment>=0 && aSegment < SegmentCount()); |
|
826 |
|
827 VGImage image = (VGImage)SegmentName(aSegment); |
|
828 if (image != VG_INVALID_HANDLE) |
|
829 { |
|
830 vgDestroyImage(image); |
|
831 } |
|
832 |
|
833 SetSegmentName(aSegment, VG_INVALID_HANDLE); |
|
834 SetSegmentTextureSize(aSegment, TSize(0, 0)); |
|
835 SetSegmentSize(aSegment, TSize(0, 0)); |
|
836 SetSegmentOffset(aSegment, TPoint(0, 0)); |
|
837 |
|
838 // There is no content anymore |
|
839 iInternalFlags &= ~(EFlagHasContent | EFlagHasAlpha); |
|
840 |
|
841 HUI_VG_INVARIANT(); |
|
842 } |
|
843 |
|
844 |
|
845 void CHuiVg10Texture::InitSegmentL(TInt /*aSegment*/) |
|
846 { |
|
847 // Nothing to do |
|
848 } |
|
849 |
|
850 |
|
851 void CHuiVg10Texture::SetupSegmentsL(const TSize& aLogicalSize, |
|
852 const TSize& aTextureSize, |
|
853 THuiTextureUploadFlags aFlags) |
|
854 { |
|
855 // Assert that the sizes are valid. |
|
856 ASSERT(aTextureSize.iWidth > 0 && aTextureSize.iHeight > 0); |
|
857 ASSERT(aLogicalSize.iWidth > 0 && aLogicalSize.iHeight > 0); |
|
858 |
|
859 HUI_DEBUG4(_L("CHuiVg10Texture::SetupSegments() - Configuring a single %ix%i texture segment for %ix%i bitmap."), |
|
860 aTextureSize.iWidth, aTextureSize.iHeight, |
|
861 aTextureSize.iWidth, aTextureSize.iHeight); |
|
862 |
|
863 // All textures use only a single segment with OpenVG. |
|
864 SetSegmentCountL(1); |
|
865 |
|
866 SetSegment(0, aLogicalSize, TPoint(0, 0), aTextureSize); |
|
867 SetSegmentName(0, (TUint)VG_INVALID_HANDLE); |
|
868 |
|
869 // The logical size always matches the texture size |
|
870 SetSize(aLogicalSize); |
|
871 |
|
872 // Enable shadow generation if requested |
|
873 if (aFlags & EHuiTextureUploadFlagGenerateShadow) |
|
874 { |
|
875 EnableShadow(ETrue); |
|
876 } |
|
877 } |
|
878 |
|
879 void CHuiVg10Texture::TextureExtension(const TUid& aExtensionUid, TAny** aExtensionParameters) |
|
880 { |
|
881 CHuiTexture::TextureExtension(aExtensionUid, aExtensionParameters); |
|
882 } |
|
883 |
|
884 void CHuiVg10Texture::EnableShadow(TBool aEnable) |
|
885 { |
|
886 CHuiTexture::EnableShadow(aEnable); |
|
887 iShadowEnabled = aEnable; |
|
888 |
|
889 if (!aEnable && iShadow.Name()) |
|
890 { |
|
891 vgDestroyImage((VGImage)iShadow.Name()); |
|
892 iShadow.SetName(0); |
|
893 HUI_VG_INVARIANT(); |
|
894 } |
|
895 |
|
896 if (aEnable) |
|
897 { |
|
898 // We cannot leave, we just try our best. |
|
899 // If this fails, we have no shadow |
|
900 TRAP_IGNORE( GenerateShadowL() ); |
|
901 } |
|
902 |
|
903 HUI_VG_INVARIANT(); |
|
904 } |
|
905 |
|
906 TBool CHuiVg10Texture::IsShadowEnabled() const |
|
907 { |
|
908 return iShadowEnabled; |
|
909 } |
|
910 |
|
911 TBool CHuiVg10Texture::GetShadowTexture(THuiTextureHandle& aHandle) const |
|
912 { |
|
913 if (iShadowEnabled && iShadow.SegmentName(0)) |
|
914 { |
|
915 aHandle = iShadow; |
|
916 return ETrue; |
|
917 } |
|
918 return EFalse; |
|
919 } |
|
920 |
|
921 void CHuiVg10Texture::UpdateShadowSizeL(const TSize& aSize) |
|
922 { |
|
923 VGImage shadow = VG_INVALID_HANDLE; |
|
924 |
|
925 if (iShadow.Name()) |
|
926 { |
|
927 shadow = (VGImage)(iShadow.Name()); |
|
928 TInt w = vgGetParameteri(shadow, VG_IMAGE_WIDTH); |
|
929 TInt h = vgGetParameteri(shadow, VG_IMAGE_HEIGHT); |
|
930 |
|
931 if (w != aSize.iWidth || h != aSize.iHeight) |
|
932 { |
|
933 // Destroy the old shadow image -- a new one will be created below |
|
934 vgDestroyImage(shadow); |
|
935 iShadow.SetName(0); |
|
936 } |
|
937 else |
|
938 { |
|
939 return; |
|
940 } |
|
941 } |
|
942 |
|
943 ASSERT(!iShadow.Name()); |
|
944 |
|
945 shadow = vgCreateImage(VG_sRGBA_8888_PRE, aSize.iWidth, aSize.iHeight, |
|
946 VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_NONANTIALIASED); |
|
947 |
|
948 if (shadow == VG_INVALID_HANDLE) |
|
949 { |
|
950 return; |
|
951 } |
|
952 iShadow.SetName(shadow); |
|
953 iShadow.SetSize(aSize); |
|
954 |
|
955 HUI_VG_INVARIANT(); |
|
956 } |
|
957 |
|
958 void CHuiVg10Texture::GenerateShadowL() |
|
959 { |
|
960 if (iRenderPlugin.IsReleased()) |
|
961 { |
|
962 HUI_DEBUG(_L("CHuiVg10Texture::GenerateShadowL - VG context not available, cannot generate texture object.")); |
|
963 return; |
|
964 } |
|
965 |
|
966 if (!IsShadowEnabled() || !(iInternalFlags & EFlagHasContent)) |
|
967 { |
|
968 return; |
|
969 } |
|
970 |
|
971 CHuiTextureProcessor& proc = CHuiStatic::Env().TextureManager().Processor(); |
|
972 TSize size = Size(); |
|
973 |
|
974 switch(ShadowStyle()) |
|
975 { |
|
976 case EHuiTextureShadowStyleIcon: |
|
977 { |
|
978 // TODO: Allow for smaller shadow images as an optimization |
|
979 TSize shadowSize(size.iWidth, size.iHeight); |
|
980 UpdateShadowSizeL(shadowSize); |
|
981 proc.BlurL(Handle(), iShadow, shadowSize, 4, |
|
982 CHuiTextureProcessor::EBlurFlagWhite | |
|
983 CHuiTextureProcessor::EBlurFlagAlpha | |
|
984 CHuiTextureProcessor::EBlurFlagExpandEdges); |
|
985 break; |
|
986 } |
|
987 |
|
988 case EHuiTextureShadowStyleRasterizedText: |
|
989 { |
|
990 TSize shadowSize(size.iWidth, size.iHeight); |
|
991 UpdateShadowSizeL(shadowSize); |
|
992 proc.BlurL(Handle(), iShadow, shadowSize, 4, |
|
993 CHuiTextureProcessor::EBlurFlagWhite | |
|
994 CHuiTextureProcessor::EBlurFlagAlpha | |
|
995 CHuiTextureProcessor::EBlurFlagExpandEdges); |
|
996 break; |
|
997 } |
|
998 |
|
999 default: |
|
1000 break; |
|
1001 } |
|
1002 |
|
1003 HUI_VG_INVARIANT(); |
|
1004 } |
|
1005 |
|
1006 #ifdef __NVG |
|
1007 HBufC8* CHuiVg10Texture::ReadNVGDataL(const CFbsBitmap& aBitmap) |
|
1008 { |
|
1009 // Fetch the extended data |
|
1010 aBitmap.BeginDataAccess(); |
|
1011 const TUint32* data = aBitmap.DataAddress(); |
|
1012 TInt dataSize = aBitmap.DataSize(); |
|
1013 TUint8* compressedData = new (ELeave) TUint8[dataSize]; |
|
1014 CleanupStack::PushL(compressedData); |
|
1015 Mem::Copy(compressedData, data, dataSize); |
|
1016 aBitmap.EndDataAccess(ETrue); |
|
1017 |
|
1018 // Create a descriptor out of the extended bitmap data. The iNVGData |
|
1019 // will now contain the direct OpenVG commands |
|
1020 TPtr8 nvgDataPtr(compressedData, dataSize, dataSize); |
|
1021 HBufC8* dataBuf = nvgDataPtr.AllocL(); |
|
1022 |
|
1023 CleanupStack::PopAndDestroy(compressedData); |
|
1024 return dataBuf; |
|
1025 } |
|
1026 |
|
1027 void CHuiVg10Texture::SegmentUploadNvgL(const CFbsBitmap& aBitmap, const CFbsBitmap* aMaskBitmap, THuiTextureUploadFlags aFlags) |
|
1028 { |
|
1029 HUI_VG_INVARIANT(); |
|
1030 |
|
1031 VGImage image = VG_INVALID_HANDLE; |
|
1032 HBufC8* dataBuf = ReadNVGDataL(aBitmap); |
|
1033 CleanupStack::PushL(dataBuf); |
|
1034 HBufC8* maskDataBuf = NULL; |
|
1035 TAknIconHeader header = GetNvgIconHeader(dataBuf); |
|
1036 TAknIconHeader maskHeader(header); // DUMMY Creation, since default constructor is missing! |
|
1037 |
|
1038 if (aMaskBitmap) |
|
1039 { |
|
1040 maskDataBuf = ReadNVGDataL(*aMaskBitmap); |
|
1041 CleanupStack::PushL(maskDataBuf); |
|
1042 maskHeader = GetNvgIconHeader(maskDataBuf); |
|
1043 } |
|
1044 |
|
1045 // The trick here is to check the texture upload flags, and determine |
|
1046 // whether we want to draw from NVG object cache directly or raster |
|
1047 // the NVG data to a PBuffer |
|
1048 if (aFlags & EHuiTextureUploadFlagUsePureNvg) |
|
1049 { |
|
1050 // Save the NVG data for future use |
|
1051 if (iNVGData) |
|
1052 { |
|
1053 delete iNVGData; |
|
1054 iNVGData = NULL; |
|
1055 } |
|
1056 iNVGData = dataBuf; |
|
1057 |
|
1058 // TODO: If the NVG ObjectCache is still up-to-date, we could possibly |
|
1059 // create the object cached NVG icon for faster drawing, and maybe |
|
1060 // discard the iNVGData completely (to save RAM?) |
|
1061 CreateObjCachedNVGIconL(); // NOTE: The OPENVG_OBJECT_CACHING has to be defined in NVG! |
|
1062 |
|
1063 // Mark the texture as an NVG texture |
|
1064 CHuiTexture::SetNvgContent(ETrue); |
|
1065 iIsExtended = ETrue; |
|
1066 } |
|
1067 else // By default, use the "OPTION C" -way! |
|
1068 { |
|
1069 // Use the same way to create the rendered image as in OPTION_C (see below) |
|
1070 CNvgEngine& nvgEngine = iRenderPlugin.NvgEngine(); |
|
1071 iIsExtended = ETrue; // I'm an NVG texture yet.. |
|
1072 |
|
1073 // Make sure we don't leak memory |
|
1074 if (iNVGData) |
|
1075 { |
|
1076 delete iNVGData; |
|
1077 iNVGData = NULL; |
|
1078 } |
|
1079 |
|
1080 // Create the real image from NVG databuf |
|
1081 iNVGData = dataBuf; |
|
1082 image = CreateRenderedImage(&nvgEngine, dataBuf, Size()); |
|
1083 |
|
1084 // New functionality for checking the mask |
|
1085 if (header.GetBitmapId() != maskHeader.GetBitmapId() && |
|
1086 CompareNvgData(dataBuf, maskDataBuf) != 0) |
|
1087 { |
|
1088 VGImage maskImg = VG_INVALID_HANDLE; |
|
1089 // The mask is from different bitmap => we have to create |
|
1090 // a separate mask image for masking the NVG icon |
|
1091 maskImg = CreateRenderedImage(&nvgEngine, maskDataBuf, Size()); |
|
1092 ReplaceVGImageAlphaChannelL(image, maskImg, Size()); |
|
1093 vgDestroyImage(maskImg); |
|
1094 } |
|
1095 |
|
1096 // Save the image handle |
|
1097 SetSegmentName(0, (TUint)image); |
|
1098 |
|
1099 // No need for object cached cmds, if any did exist |
|
1100 delete iIconCommands; // No effect, if iIconCommands aren't created |
|
1101 iIconCommands = NULL; |
|
1102 |
|
1103 // If the VGImage texture creation was successful, we are no longer "NVG |
|
1104 // texture" in a sense. If not, we will use the NVG data directly for drawing |
|
1105 if (image != VG_INVALID_HANDLE) |
|
1106 { |
|
1107 CHuiTexture::SetNvgContent(EFalse); |
|
1108 iIsExtended = EFalse; |
|
1109 } |
|
1110 } |
|
1111 |
|
1112 if (aMaskBitmap) |
|
1113 { |
|
1114 CleanupStack::PopAndDestroy(maskDataBuf); |
|
1115 } |
|
1116 CleanupStack::Pop(dataBuf); |
|
1117 |
|
1118 // The texture now has content. |
|
1119 iInternalFlags |= EFlagHasContent; |
|
1120 iInternalFlags |= EFlagHasAlpha; |
|
1121 |
|
1122 HUI_VG_INVARIANT(); |
|
1123 } |
|
1124 |
|
1125 TInt CHuiVg10Texture::CompareNvgData(HBufC8* aNVGData1, HBufC8* aNVGData2) |
|
1126 { |
|
1127 TInt lengthAfterHeader1 = aNVGData1->Length() - KIconHeaderLength; |
|
1128 TInt lengthAfterHeader2 = aNVGData2->Length() - KIconHeaderLength; |
|
1129 |
|
1130 TPtr8 firstNoHeader((TUint8 *)aNVGData1->Des().Ptr() + KIconHeaderLength, lengthAfterHeader1, lengthAfterHeader1); |
|
1131 TPtr8 secondNoHeader((TUint8 *)aNVGData2->Des().Ptr() + KIconHeaderLength, lengthAfterHeader2, lengthAfterHeader2); |
|
1132 |
|
1133 TInt returnValue = firstNoHeader.Compare(secondNoHeader); |
|
1134 return returnValue; |
|
1135 } |
|
1136 |
|
1137 VGImage CHuiVg10Texture::CreateRenderedImage(CNvgEngine* aNvgEngine, HBufC8* aNVGData, const TSize& aDestSize) |
|
1138 { |
|
1139 HUI_VG_INVARIANT(); |
|
1140 |
|
1141 // Image placeholder |
|
1142 VGImage image = VG_INVALID_HANDLE; |
|
1143 |
|
1144 if ( !iIsExtended ) |
|
1145 { |
|
1146 // If called outside of the context, do nothing. |
|
1147 // Image will be VG_INVALID_HANDLE |
|
1148 HUI_DEBUG(_L("CHuiVg10Texture::CreateRenderedImage() - Texture not extended, can't create rendered image")); |
|
1149 return image; |
|
1150 } |
|
1151 |
|
1152 // Check if we already have an existing image. |
|
1153 if (SegmentCount() == 1) |
|
1154 { |
|
1155 image = (VGImage)SegmentName(0); |
|
1156 if( image != VG_INVALID_HANDLE ) |
|
1157 { |
|
1158 HUI_DEBUG1(_L("CHuiVg10Texture::CreateRenderedImage() - Image already exists: %d"), image); |
|
1159 return image; |
|
1160 } |
|
1161 } |
|
1162 |
|
1163 // NVGEngine is needed to do the drawing of the extended bitmap to VGImage |
|
1164 if (!aNvgEngine || !aNVGData) |
|
1165 { |
|
1166 HUI_DEBUG(_L("CHuiVg10Texture::CreateRenderedImage() - No NvgEngine / NVGData!")); |
|
1167 return image; |
|
1168 } |
|
1169 |
|
1170 // Get the needed egl contexts & stuff for creating the proper eglSurface |
|
1171 EGLContext context = iRenderPlugin.EglSharedContext(); |
|
1172 MHuiRenderSurface* oldSurface = CHuiStatic::CurrentRenderSurface(); |
|
1173 |
|
1174 #ifndef __WINS__ // Should possibly query the supported mode instead? |
|
1175 VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE; |
|
1176 #else |
|
1177 VGImageFormat imageInternalFormat = VG_sARGB_8888; |
|
1178 #endif |
|
1179 |
|
1180 VGbitfield qualityFlags = VG_IMAGE_QUALITY_NONANTIALIASED; // | VG_IMAGE_QUALITY_BETTER | VG_IMAGE_QUALITY_FASTER; |
|
1181 image = vgCreateImage(imageInternalFormat, aDestSize.iWidth, aDestSize.iHeight, qualityFlags); |
|
1182 |
|
1183 // Get the configs and displays etc. needed for creating the surface |
|
1184 EGLDisplay display = iRenderPlugin.EglDisplay(); |
|
1185 |
|
1186 #if 1 |
|
1187 // Returns the same config, as below! |
|
1188 // The config used with the current renderer surface has the same parameters |
|
1189 // that are needed with the PBufferSurface from vgImage |
|
1190 EGLConfig config = iRenderPlugin.EglConfig(0); |
|
1191 #else |
|
1192 // This structure can be used, if surface config params have to be changed |
|
1193 // Better way though might be to change the vgImage VGImageFormat accordingly.. |
|
1194 const TInt BITS_PER_CHANNEL = 8; |
|
1195 // Choose an EGL config |
|
1196 const EGLint attrs[] = |
|
1197 { |
|
1198 EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, |
|
1199 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT, |
|
1200 EGL_RED_SIZE, BITS_PER_CHANNEL, |
|
1201 EGL_GREEN_SIZE, BITS_PER_CHANNEL, |
|
1202 EGL_BLUE_SIZE, BITS_PER_CHANNEL, |
|
1203 EGL_ALPHA_SIZE, BITS_PER_CHANNEL, |
|
1204 EGL_NONE |
|
1205 }; |
|
1206 TInt configCount = iRenderPlugin.EglChooseConfig(attrs); |
|
1207 ASSERT(configCount > 0); |
|
1208 EGLConfig config = iRenderPlugin.EglConfig(0); |
|
1209 #endif |
|
1210 |
|
1211 // The VGImage will act as the surface, so the drawing will go directly to the VGImage |
|
1212 EGLSurface newSurface = eglCreatePbufferFromClientBuffer( |
|
1213 display, EGL_OPENVG_IMAGE, |
|
1214 static_cast<EGLClientBuffer>(image), // Use the image as buffer |
|
1215 config, NULL); |
|
1216 |
|
1217 // Report error in debug mode, if failed creating the surface |
|
1218 if ( newSurface == EGL_NO_SURFACE ) |
|
1219 { |
|
1220 HUI_DEBUG1(_L("CHuiVg10Texture::CreateRenderedImage() - EGL Surface could not be created, eglErr: %04x"), eglGetError() ); |
|
1221 if ( image != VG_INVALID_HANDLE ) |
|
1222 { |
|
1223 vgDestroyImage( image ); |
|
1224 image = VG_INVALID_HANDLE; |
|
1225 } |
|
1226 |
|
1227 HUI_VG_INVARIANT(); |
|
1228 return image; |
|
1229 } |
|
1230 |
|
1231 // Set the new VGImage related eglSurface as current, and start drawing onto it! |
|
1232 // We use the old context, our surface should be compatible with it |
|
1233 if ( eglMakeCurrent( display, newSurface, newSurface, context ) == EGL_FALSE ) |
|
1234 { |
|
1235 // Report error in debug mode |
|
1236 HUI_DEBUG1(_L("CHuiVg10Texture::CreateRenderedImage() - EGL Surface could not be made current, eglErr: %04x"), eglGetError()); |
|
1237 if ( image != VG_INVALID_HANDLE ) |
|
1238 { |
|
1239 vgDestroyImage( image ); |
|
1240 image = VG_INVALID_HANDLE; |
|
1241 } |
|
1242 |
|
1243 eglDestroySurface( display, newSurface ); |
|
1244 HUI_VG_INVARIANT(); |
|
1245 return image; |
|
1246 } |
|
1247 CHuiStatic::SetCurrentRenderSurface( NULL ); |
|
1248 |
|
1249 |
|
1250 // VKN TODO: It would be better, if the GC could somehow spot that openVg |
|
1251 // state has changed, and would restore it's own state. Could use the same |
|
1252 // AddRestoreStateFlags as the paint is currently using.. |
|
1253 // |
|
1254 // Get the current statematrix and store it for the duration of NVG drawing |
|
1255 TReal32 matrix[9]; |
|
1256 vgGetMatrix(matrix); |
|
1257 vgLoadIdentity(); |
|
1258 |
|
1259 // Render the NVGtexture into the image buffer. No transformations are done for this. |
|
1260 SetNvgParamsFromIconHeader(*aNvgEngine, aNVGData); |
|
1261 |
|
1262 if (iIconCommands) |
|
1263 { |
|
1264 //HUI_DEBUG(_L("CHuiVg10Texture::CreateRenderedImage() - Drawing iIconCommands")); |
|
1265 iIconCommands->Draw(aDestSize, aNvgEngine); |
|
1266 } |
|
1267 else |
|
1268 { |
|
1269 // If ObjectCached version failed, try to use the old way |
|
1270 //HUI_DEBUG(_L("CHuiVg10Texture::CreateRenderedImage() - Drawing with DrawNvg")); |
|
1271 VGint blendMode = vgGeti(VG_BLEND_MODE); |
|
1272 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER); |
|
1273 aNvgEngine->DrawNvg(GetNvgDataWithoutHeader(aNVGData), aDestSize, NULL, NULL); |
|
1274 vgSeti(VG_BLEND_MODE, blendMode); |
|
1275 } |
|
1276 |
|
1277 // NVG-TLV icon margin special case check: |
|
1278 // Check, if the icon has to be margin corrected |
|
1279 TAknIconHeader iconheader = GetNvgIconHeader(aNVGData); |
|
1280 TSize size = aDestSize; // For using the correct size also later on |
|
1281 if (iconheader.IsMarginCorrection()) |
|
1282 { |
|
1283 size = ApplyMargin(image, aDestSize, display, newSurface, context); |
|
1284 if( size != aDestSize) |
|
1285 { |
|
1286 // Redo the drawing, this time to the correct size |
|
1287 if (iIconCommands) |
|
1288 iIconCommands->Draw(size, aNvgEngine); |
|
1289 else |
|
1290 aNvgEngine->DrawNvg(GetNvgDataWithoutHeader(aNVGData), size, NULL, NULL); |
|
1291 } |
|
1292 } |
|
1293 |
|
1294 // The NVG draw messes up the paint, scissoring & rects, so mark them as dirty |
|
1295 TInt dirtyFlags = EHuiVg10GcStateFlagDirtyPaint | |
|
1296 EHuiVg10GcStateFlagDirtyScissor | |
|
1297 EHuiVg10GcStateFlagDirtyScissorRects; |
|
1298 iRenderPlugin.AddRestoreStateFlags(dirtyFlags); |
|
1299 |
|
1300 #ifdef _DEBUG |
|
1301 // TODO: There's something in the DrawNvg() code, which causes OpenVg to set |
|
1302 // error code => PANIC, if not for this temp check here. REMOVE ONCE THE TSW ERROR IS FIXED! |
|
1303 VGErrorCode err = vgGetError(); |
|
1304 if (err) |
|
1305 { |
|
1306 RDebug::Print(_L("CHuiVG10Texture::CreateRenderedImage - Error in NVG draw: %04x"), err); |
|
1307 } |
|
1308 #endif |
|
1309 |
|
1310 HUI_VG_INVARIANT(); |
|
1311 |
|
1312 vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); |
|
1313 vgLoadMatrix(matrix); |
|
1314 oldSurface->MakeCurrent(); // This will also call the SetCurrentRenderSurface |
|
1315 |
|
1316 // Now we should have a rendered image in the image variable! |
|
1317 // Release the surface, but not the context because we used a shared context |
|
1318 if ( newSurface != EGL_NO_SURFACE ) |
|
1319 { |
|
1320 eglDestroySurface( display, newSurface ); |
|
1321 } |
|
1322 |
|
1323 // NVG-TLV color correction special case check: If the icon has |
|
1324 // some color specified in the icon header, set the new icon color |
|
1325 TUint32 iconColor = iconheader.GetIconColor(); |
|
1326 if (iconColor & 0x00FFFFFF) |
|
1327 { |
|
1328 SetIconColor(image, size, iconColor); |
|
1329 } |
|
1330 |
|
1331 HUI_VG_INVARIANT(); |
|
1332 |
|
1333 return image; |
|
1334 } |
|
1335 |
|
1336 TBool CHuiVg10Texture::IsExtended() const |
|
1337 { |
|
1338 return iIsExtended; |
|
1339 } |
|
1340 |
|
1341 HBufC8* CHuiVg10Texture::GetExtendedTextureData() const |
|
1342 { |
|
1343 return iNVGData; |
|
1344 } |
|
1345 |
|
1346 MNVGIcon* CHuiVg10Texture::GetIconCommandsData() const |
|
1347 { |
|
1348 return iIconCommands; |
|
1349 } |
|
1350 |
|
1351 void CHuiVg10Texture::CreateObjCachedNVGIconL() |
|
1352 { |
|
1353 HUI_VG_INVARIANT(); |
|
1354 // Just to be sure that we don't leak memory |
|
1355 if (iIconCommands) |
|
1356 { |
|
1357 HUI_DEBUG(_L("CHuiVg10Texture::CreateObjCachedNVGIconL() - deleting old iIconCommands. Should never come here")); |
|
1358 delete iIconCommands; |
|
1359 iIconCommands = NULL; |
|
1360 } |
|
1361 |
|
1362 // Fetch the NvgDecoder engine for creating the obj cached icon |
|
1363 CNvgEngine& nvgEngine = iRenderPlugin.NvgEngine(); |
|
1364 |
|
1365 //Set Parameters from Icon Header |
|
1366 SetNvgParamsFromIconHeader(nvgEngine, iNVGData); |
|
1367 |
|
1368 // Parse the header info out of the nvg data |
|
1369 TPtr8 nvgDataVoidIC = GetNvgDataWithoutHeader(iNVGData); |
|
1370 |
|
1371 iIconCommands = nvgEngine.CreateNVGIcon(nvgDataVoidIC, Size()); |
|
1372 |
|
1373 HUI_VG_INVARIANT(); |
|
1374 } |
|
1375 |
|
1376 TAknIconHeader CHuiVg10Texture::GetNvgIconHeader(HBufC8* aNVGData) |
|
1377 { |
|
1378 // Parse the icon header info from the extended data |
|
1379 TPtr8 IconHeaderPtr((TUint8*)aNVGData->Des().Ptr(), KIconHeaderLength, KIconHeaderLength); |
|
1380 TAknIconHeader iconheader(IconHeaderPtr); |
|
1381 |
|
1382 return iconheader; |
|
1383 } |
|
1384 |
|
1385 TPtr8 CHuiVg10Texture::GetNvgDataWithoutHeader(HBufC8* aNVGData) |
|
1386 { |
|
1387 // The rest of the data (after the iconheader) are the OVG drawing instructions |
|
1388 TInt lengthAfterHeader = aNVGData->Length() - KIconHeaderLength; |
|
1389 TPtr8 nvgDataVoidIC((TUint8 *)aNVGData->Des().Ptr() + KIconHeaderLength, lengthAfterHeader, lengthAfterHeader); |
|
1390 |
|
1391 return nvgDataVoidIC; |
|
1392 } |
|
1393 |
|
1394 void CHuiVg10Texture::SetNvgParamsFromIconHeader(CNvgEngine& aNvgEngine, HBufC8* aNVGData) |
|
1395 { |
|
1396 TAknIconHeader iconheader = GetNvgIconHeader(aNVGData); |
|
1397 |
|
1398 // Set preserve aspect ratio according to the header info |
|
1399 TNvgAlignStatusType alignTypeValue = ENvgPreserveAspectRatio_XmidYmid; |
|
1400 TNvgMeetOrSliceType meetOrSliceTypeValue = ENvgMeet; |
|
1401 |
|
1402 switch ( iconheader.GetScaleMode() ) |
|
1403 { |
|
1404 case EAspectRatioPreserved: // Fall through |
|
1405 { |
|
1406 // Use default |
|
1407 break; |
|
1408 } |
|
1409 |
|
1410 // Ensures NVG content fully covers |
|
1411 // the area of the icon whilst preserving aspect ratio. |
|
1412 case EAspectRatioPreservedSlice: |
|
1413 { |
|
1414 // alignTypeValue use default |
|
1415 meetOrSliceTypeValue = ENvgSlice; |
|
1416 break; |
|
1417 } |
|
1418 |
|
1419 // EAspectRatioPreservedAndUnusedSpaceRemoved is mapped to the same |
|
1420 // values as EAspectRatioNotPreserved because we already have a |
|
1421 // frame buffer with the dimensions that preserves the aspect ratio. |
|
1422 // This mapping ensures that NVG engine does not calculate aspect |
|
1423 // ratio twice and potentially resulting in precision loss. |
|
1424 case EAspectRatioPreservedAndUnusedSpaceRemoved: |
|
1425 case EAspectRatioNotPreserved: |
|
1426 { |
|
1427 alignTypeValue = ENvgPreserveAspectRatio_None; |
|
1428 // meetOrSliceTypeValue used default |
|
1429 break; |
|
1430 } |
|
1431 } |
|
1432 aNvgEngine.SetPreserveAspectRatio(alignTypeValue, meetOrSliceTypeValue); |
|
1433 aNvgEngine.Rotate(iconheader.GetRotation(),Size().iWidth >>1, Size().iHeight >>1); |
|
1434 } |
|
1435 |
|
1436 TSize CHuiVg10Texture::ApplyMargin(VGImage aImage, TSize aSize, EGLDisplay aDisplay, EGLSurface aSurface, EGLContext aContext) |
|
1437 { |
|
1438 HUI_VG_INVARIANT(); |
|
1439 // If the icon is also a current EGL surface, the getImageSubData |
|
1440 // won't succeed and return "image in use" -error.. |
|
1441 if ( eglMakeCurrent( aDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ) == EGL_FALSE ) |
|
1442 { |
|
1443 HUI_DEBUG1(_L("CHuiVg10Texture::ApplyMargin() - EGL NO_Surface could not be made current, eglErr: %04x"), eglGetError()); |
|
1444 return aSize; |
|
1445 } |
|
1446 |
|
1447 #ifndef __WINS__ // Should possibly query the supported mode instead? |
|
1448 VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE; |
|
1449 #else |
|
1450 // This doesn't work in the Emulator anyways.. => remove? |
|
1451 VGImageFormat imageInternalFormat = VG_sARGB_8888; |
|
1452 #endif |
|
1453 |
|
1454 TInt stride = aSize.iWidth * 4; // VG_sARGB_8888(_PRE) is four bytes long (8888) |
|
1455 HBufC8* buf = HBufC8::New(stride); |
|
1456 if (!buf) |
|
1457 { |
|
1458 HUI_DEBUG(_L("CHuiVg10Texture::ApplyMargin() - Ran out of memory!")); |
|
1459 return aSize; |
|
1460 } |
|
1461 TUint32* ptr = (TUint32*)(buf->Des()).Ptr(); |
|
1462 |
|
1463 const TInt lValidMargin = aSize.iHeight * 12 / 100; |
|
1464 |
|
1465 const TInt Ha = aSize.iHeight; |
|
1466 TInt hTa = 0; |
|
1467 TInt hNT = 0; |
|
1468 TInt C = 0; |
|
1469 TInt hNTN = Ha - 2.0 * 0.12 * Ha; |
|
1470 TReal R = 1.0; |
|
1471 TInt HaN = Ha; |
|
1472 |
|
1473 const TInt lastColumn = aSize.iHeight - 1; |
|
1474 for (TInt curRow = 0; curRow < lValidMargin; curRow++) |
|
1475 { |
|
1476 const TInt y = (aSize.iHeight - 1) - curRow; // h - 1 is the last line |
|
1477 // Get just one stride at a time (iWidth wide, 1 pixel high) |
|
1478 vgGetImageSubData(aImage, ptr, stride, imageInternalFormat, 0, y, aSize.iWidth, 1); |
|
1479 for (TInt s = lastColumn; s >= 0; --s) |
|
1480 { |
|
1481 if (ptr[s] & 0xFF000000) |
|
1482 { |
|
1483 hTa = curRow; |
|
1484 hNT = Ha - 2 * hTa; |
|
1485 C = 2 * hTa; |
|
1486 R = ( ( (TReal)hNTN / (TReal)hNT ) > 1.0 ) ? 1 : (TReal)hNTN / (TReal)hNT; |
|
1487 HaN = Ha * R - C * R + C; |
|
1488 curRow = lValidMargin; // to exit the outer loop |
|
1489 break; // to exit the inner |
|
1490 } |
|
1491 } |
|
1492 } |
|
1493 delete buf; |
|
1494 HUI_VG_INVARIANT(); |
|
1495 |
|
1496 // Make the PBuffer surface current again |
|
1497 if ( eglMakeCurrent(aDisplay, aSurface, aSurface, aContext) == EGL_FALSE ) |
|
1498 { |
|
1499 HUI_DEBUG1(_L("CHuiVg10Texture::ApplyMargin() - EGL aSurface could not be made current, eglErr: %04x"), eglGetError()); |
|
1500 return aSize; |
|
1501 } |
|
1502 |
|
1503 // If icon size has to be changed, clear out old area for new DrawNVG round! |
|
1504 if(aSize.iHeight > HaN) |
|
1505 { |
|
1506 vgLoadIdentity(); |
|
1507 |
|
1508 VGfloat color[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; |
|
1509 vgSetfv(VG_CLEAR_COLOR, 4, color); |
|
1510 vgClear(0, 0, aSize.iWidth, aSize.iHeight); |
|
1511 // Or should it be clearImage instead? |
|
1512 //vgClearImage(aImage, 0, 0, aSize.iWidth, aSize.iHeight); |
|
1513 |
|
1514 VGfloat Hr = (VGfloat)HaN/(aSize.iHeight); |
|
1515 TInt WaN = aSize.iWidth*Hr; |
|
1516 |
|
1517 VGfloat Tx = (aSize.iHeight-HaN)/2; |
|
1518 VGfloat Ty = (aSize.iWidth-WaN)/2; |
|
1519 vgTranslate(Tx,Ty); |
|
1520 |
|
1521 HUI_VG_INVARIANT(); |
|
1522 return(TSize(HaN,WaN)); |
|
1523 } |
|
1524 |
|
1525 HUI_VG_INVARIANT(); |
|
1526 return aSize; |
|
1527 } |
|
1528 |
|
1529 void CHuiVg10Texture::SetIconColor(VGImage& aSrcImage, TSize aSize, TUint32 aColor) |
|
1530 { |
|
1531 // TODO: DOESN'T WORK IN EMULATOR FOR SOME REASON! Figure out why! |
|
1532 HUI_VG_INVARIANT(); |
|
1533 |
|
1534 vgSeti(VG_FILTER_FORMAT_LINEAR, VG_FALSE); |
|
1535 |
|
1536 #ifndef __WINS__ // Should possibly query the supported mode instead? |
|
1537 VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE; |
|
1538 // TODO: !!! SHOULD FORMAT_PREMULTIPLIED BE APPLIED?? !!! |
|
1539 //vgSeti(VG_FILTER_FORMAT_PREMULTIPLIED, VG_TRUE); |
|
1540 #else |
|
1541 // This doesn't work in the Emulator anyways.. => remove? |
|
1542 VGImageFormat imageInternalFormat = VG_sARGB_8888; |
|
1543 #endif |
|
1544 |
|
1545 // Rip the RGB components from the aColor param & scale to [0..1] |
|
1546 VGfloat red = (aColor&0xff)/255.0f; |
|
1547 VGfloat green = ((aColor>>8)&0xff)/255.0f; |
|
1548 VGfloat blue = ((aColor>>16)&0xff)/255.0f; |
|
1549 |
|
1550 //vgSeti(VG_FILTER_CHANNEL_MASK, VG_ALPHA ); |
|
1551 // This matrix will set all color components in the source image to 0, |
|
1552 // and replaces the RGB with the values from the iconheader |
|
1553 VGfloat matrix[20] = { |
|
1554 0,0,0,0, |
|
1555 0,0,0,0, |
|
1556 0,0,0,0, |
|
1557 0,0,0,1, // <- Preserves the original alpha value |
|
1558 red, green, blue, 0}; |
|
1559 |
|
1560 // Create the destination image & start modifying colors |
|
1561 VGImage dstImg = vgCreateImage(imageInternalFormat, aSize.iWidth, aSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); |
|
1562 vgColorMatrix(dstImg, aSrcImage, matrix); |
|
1563 HUI_VG_INVARIANT(); |
|
1564 |
|
1565 // Destroy the old source image and return the new image with changed colors |
|
1566 vgDestroyImage(aSrcImage); |
|
1567 aSrcImage = dstImg; |
|
1568 |
|
1569 HUI_VG_INVARIANT(); |
|
1570 } |
|
1571 |
|
1572 void CHuiVg10Texture::ReplaceVGImageAlphaChannelL(VGImage aImage, VGImage aMaskImage, TSize aSize) |
|
1573 { |
|
1574 HUI_VG_INVARIANT(); |
|
1575 |
|
1576 #ifndef __WINS__ // Should possibly query the supported mode instead? |
|
1577 VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE; |
|
1578 #else |
|
1579 VGImageFormat imageInternalFormat = VG_sARGB_8888; |
|
1580 #endif |
|
1581 TInt height = aSize.iHeight; |
|
1582 TInt width = aSize.iWidth; |
|
1583 const TInt colorDepth = 4; // VG_sARGB_8888(_PRE) 4 bytes long |
|
1584 TInt stride = width * colorDepth; |
|
1585 |
|
1586 // Create the pointers to RAM in which the image data will be saved temporarily |
|
1587 HBufC8* imgBuf = HBufC8::NewL(width * height * colorDepth); |
|
1588 CleanupStack::PushL(imgBuf); |
|
1589 TUint32* imgPtr = (TUint32*)(imgBuf->Des()).Ptr(); |
|
1590 const TUint32* imgSavePtr = (TUint32*)(imgBuf->Des()).Ptr(); |
|
1591 |
|
1592 HBufC8* maskBuf = HBufC8::NewL(width * height * colorDepth); |
|
1593 CleanupStack::PushL(maskBuf); |
|
1594 TUint32* maskPtr = (TUint32*)(maskBuf->Des()).Ptr(); |
|
1595 |
|
1596 // Get the image pixel data |
|
1597 vgGetImageSubData(aImage, imgPtr, stride, imageInternalFormat, 0, 0, width, height); |
|
1598 vgGetImageSubData(aMaskImage, maskPtr, stride, imageInternalFormat, 0, 0, width, height); |
|
1599 |
|
1600 // Replace destination image's alpha values with mask image |
|
1601 for (TInt y = 0; y < height; y++) |
|
1602 { |
|
1603 for (TInt x = 0; x < width; x++) |
|
1604 { |
|
1605 *maskPtr &= 0xff000000; // Remove other than alpha component from source pixel |
|
1606 *imgPtr &= ~0xff000000; // Remove alpha channel value from destination pixel |
|
1607 *imgPtr++ |= *maskPtr++; // Bitwise OR the maskImg alpha info to destination image pixel |
|
1608 } |
|
1609 } |
|
1610 |
|
1611 // Replace the destination image with combined alpha information from src image |
|
1612 vgImageSubData(aImage, imgSavePtr, stride, imageInternalFormat, 0, 0, width, height); |
|
1613 |
|
1614 CleanupStack::PopAndDestroy(maskBuf); |
|
1615 CleanupStack::PopAndDestroy(imgBuf); |
|
1616 |
|
1617 HUI_VG_INVARIANT(); |
|
1618 } |
|
1619 #endif |
|
1620 |
|
1621 |
|
1622 void CHuiVg10Texture::PushEGLContext() |
|
1623 { |
|
1624 iPreviousEGLState.iContext= eglGetCurrentContext(); |
|
1625 TEGLState& state = iRenderPlugin.GetUploadState(); |
|
1626 if (state.iContext == KErrNotFound) |
|
1627 { |
|
1628 TEGLState& state = iRenderPlugin.GetUploadState(); |
|
1629 // the first context used for uploading will be used for all texture uploads |
|
1630 state.iContext = iPreviousEGLState.iContext; |
|
1631 state.iDrawSurface = eglGetCurrentSurface(EGL_DRAW); |
|
1632 state.iReadSurface = eglGetCurrentSurface(EGL_READ); |
|
1633 state.iDisplay = eglGetCurrentDisplay(); |
|
1634 } |
|
1635 else |
|
1636 { |
|
1637 // change context only if necessary |
|
1638 if (iPreviousEGLState.iContext != state.iContext) |
|
1639 { |
|
1640 iPreviousEGLState.iDrawSurface = eglGetCurrentSurface(EGL_DRAW); |
|
1641 iPreviousEGLState.iReadSurface = eglGetCurrentSurface(EGL_READ); |
|
1642 iPreviousEGLState.iDisplay = eglGetCurrentDisplay(); |
|
1643 eglMakeCurrent(state.iDisplay, state.iDrawSurface, state.iReadSurface, state.iContext); |
|
1644 } |
|
1645 } |
|
1646 } |
|
1647 |
|
1648 void CHuiVg10Texture::PopEGLContext() |
|
1649 { |
|
1650 if (iPreviousEGLState.iContext != iRenderPlugin.GetUploadState().iContext) |
|
1651 { |
|
1652 eglMakeCurrent(iPreviousEGLState.iDisplay, iPreviousEGLState.iDrawSurface, iPreviousEGLState.iReadSurface,iPreviousEGLState.iContext); |
|
1653 } |
|
1654 } |
|
1655 // End of file |
|
1656 |