uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10VGImageBinder.cpp
branchRCL_3
changeset 17 3ac8bf5c5014
parent 0 15bf7259bb7c
child 50 1801340c26a2
--- a/uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10VGImageBinder.cpp	Wed Apr 14 16:53:50 2010 +0300
+++ b/uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10VGImageBinder.cpp	Tue Apr 27 17:34:42 2010 +0300
@@ -1,28 +1,28 @@
 /*
-* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). 
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description:   Class HuiVg10VGImageBinder
-*
-*/
+ * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description:   Class HuiVg10VGImageBinder
+ *
+ */
 
 #include "HuiVg10VgImageBinder.h"
 #include "HuiVg10RenderPlugin.h"
 #include "uiacceltk/HuiUtil.h"
 
 CHuiVg10VgImageBinder::CHuiVg10VgImageBinder(CHuiVg10RenderPlugin* aRenderPlugin):
-    iRenderPlugin(aRenderPlugin)
-    {
-    }
+iRenderPlugin(aRenderPlugin)
+        {
+        }
 
 void CHuiVg10VgImageBinder::ConstructL()
     {
@@ -48,79 +48,127 @@
 
 TInt CHuiVg10VgImageBinder::BindClientBuffer(TUint aBuffer)
     {
-    // Check whether we should use the Alpha format bit
-    VGImageFormat imageFormat = (VGImageFormat)vgGetParameteri(aBuffer, VG_IMAGE_FORMAT);
-    TInt maskBit = 0;
-    if (imageFormat == VG_sRGBA_8888_PRE)
+
+    // This returns the index of the corresponding aBuffer stored in the array. 
+    // If KErrNotFound is returned,it indicates that this is the first BindClientBuffer
+    // call for aBuffer and hence eglPbufferfromclient has to be created for this buffer
+    TInt bufferIndex = iGroupOpacityImages.Find(aBuffer);
+    
+    
+    // This check mandates that iSavedDraw/Read Surfaces are stored only for the first time
+    // (i.e., before any pbufferfromclient surfaces are created).This is because when there are concurrent 
+    // BindToImageL calls,we would eventually be losing track of the base window surface on
+    // top of which the vgImage has to be drawn. 
+    if(iGroupOpacityImages.Count() == 0)							
         {
-        maskBit = EGL_VG_ALPHA_FORMAT_PRE_BIT;
+        // Save current context and surfaces
+        iSavedContext = eglGetCurrentContext();
+        iSavedDrawSurface = eglGetCurrentSurface(EGL_DRAW);
+        iSavedReadSurface = eglGetCurrentSurface(EGL_READ);
         }
-    
-    const TInt BITS_PER_CHANNEL = 8;
-    // Choose an EGL config
-    const EGLint attrs[] =
+
+    // Buffer Index would be KErrNotFound if this is the first BindClientBuffer call for aBuffer
+    // (there would be multiple BindClientBuffer calls for an aBuffer) and hence corresponding
+    // pbufferfromclient surface has to be created for that aBuffer.    
+    if(bufferIndex == KErrNotFound)
         {
-        EGL_RENDERABLE_TYPE,    EGL_OPENVG_BIT,
-        EGL_SURFACE_TYPE,       EGL_PBUFFER_BIT | maskBit,
-        EGL_RED_SIZE,           BITS_PER_CHANNEL,
-        EGL_GREEN_SIZE,         BITS_PER_CHANNEL,
-        EGL_BLUE_SIZE,          BITS_PER_CHANNEL,
-        EGL_ALPHA_SIZE,         BITS_PER_CHANNEL,
-        EGL_NONE
-        };
+        // Check whether we should use the Alpha format bit
+        VGImageFormat imageFormat = (VGImageFormat)vgGetParameteri(aBuffer, VG_IMAGE_FORMAT);
+        TInt maskBit = 0;
+        if (imageFormat == VG_sRGBA_8888_PRE)
+            {
+            maskBit = EGL_VG_ALPHA_FORMAT_PRE_BIT;
+            }
+
+        const TInt BITS_PER_CHANNEL = 8;
+        // Choose an EGL config
+        const EGLint attrs[] =
+            {
+            EGL_RENDERABLE_TYPE,    EGL_OPENVG_BIT,
+            EGL_SURFACE_TYPE,       EGL_PBUFFER_BIT | maskBit,
+            EGL_RED_SIZE,           BITS_PER_CHANNEL,
+            EGL_GREEN_SIZE,         BITS_PER_CHANNEL,
+            EGL_BLUE_SIZE,          BITS_PER_CHANNEL,
+            EGL_ALPHA_SIZE,         BITS_PER_CHANNEL,
+            EGL_NONE
+            };
+
+        // Create a context
+        TInt configCount = iRenderPlugin->EglChooseConfig(attrs);
+        EGLConfig config = iRenderPlugin->EglConfig(0);
+
+        // Create a pbuffer surface
+        iEglPBufferSurface_Client = eglCreatePbufferFromClientBuffer(iRenderPlugin->EglDisplay(),
+                EGL_OPENVG_IMAGE, 
+                static_cast<EGLClientBuffer>(aBuffer),    // Use the param image as buffer
+                config, NULL);
+        if (iEglPBufferSurface_Client == EGL_NO_SURFACE)
+            {
+            HUI_DEBUG1(_L("CHuiVg10VgImageBinder::BindClientBuffer() - EGL Surface could not be created, eglErr: %04x"), eglGetError() );
+            return KErrGeneral;
+            }
+        iGroupOpacitySurfaces.Append(iEglPBufferSurface_Client);
+        iGroupOpacityImages.Append(aBuffer);
+        } 
+        // Control would go to else part indicating that this is not the first BindClientBuffer for aBuffer 
+        // and hence the corresponding eglPBufferfromClient surface could be retrieved with the bufferIndex
+    else				
+        {
+        iEglPBufferSurface_Client = iGroupOpacitySurfaces[bufferIndex];
+        }
+
+    EGLContext context = iRenderPlugin->EglSharedContext();
     
-    // Create a context
-    TInt configCount = iRenderPlugin->EglChooseConfig(attrs);
-    EGLConfig config = iRenderPlugin->EglConfig(0);
+    // eglMakeCurrent with EGL_NO_SURFACE de-couples vgImage from an old eglpbufferfromclient surface.
+    // Otherwise in a multiple BindClientBuffer scenario for the same vgImage, eglMakeCurrent
+    // fails with an EGL_BAD_ACCESS error (vgimage already inuse error)
+    eglMakeCurrent(iRenderPlugin->EglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, context);      
     
-    // Create a pbuffer surface
-    iEglPBufferSurface_Client = eglCreatePbufferFromClientBuffer(iRenderPlugin->EglDisplay(),
-            EGL_OPENVG_IMAGE, 
-            static_cast<EGLClientBuffer>(aBuffer),    // Use the param image as buffer
-            config, NULL);
-    
-    if (iEglPBufferSurface_Client == EGL_NO_SURFACE)
+    // Bind our own PBuffer surface (from VGImage)
+    if ( eglMakeCurrent(iRenderPlugin->EglDisplay(), iEglPBufferSurface_Client, iEglPBufferSurface_Client, context ) == EGL_FALSE )
         {
-        HUI_DEBUG1(_L("CHuiVg10VgImageBinder::BindClientBuffer() - EGL Surface could not be created, eglErr: %04x"), eglGetError() );
+        HUI_DEBUG1(_L("CHuiVg10VgImageBinder::BindClientBuffer() - EGL Surface could not be made current, eglErr: %04x"), eglGetError());
+        TInt eglError = eglGetError();
         return KErrGeneral;
         }
 
-    // Save current context and surfaces
-    iSavedContext = eglGetCurrentContext();
-    iSavedDrawSurface = eglGetCurrentSurface(EGL_DRAW);
-    iSavedReadSurface = eglGetCurrentSurface(EGL_READ);
-
-    EGLContext context = iRenderPlugin->EglSharedContext();
-    
-    // Bind our own PBuffer surface (from VGImage)
-    if ( eglMakeCurrent(iRenderPlugin->EglDisplay(), iEglPBufferSurface_Client, iEglPBufferSurface_Client, context /*iSavedContext*/) == EGL_FALSE )
-        {
-        HUI_DEBUG1(_L("CHuiVg10VgImageBinder::BindClientBuffer() - EGL Surface could not be made current, eglErr: %04x"), eglGetError());
-        return KErrGeneral;
-        }
-    
     // Alles in Ordnung!
     return KErrNone;
     }
 
 TInt CHuiVg10VgImageBinder::UnBindClientBuffer()
     {
-    if ( eglMakeCurrent(iRenderPlugin->EglDisplay(), iSavedDrawSurface, iSavedReadSurface, iSavedContext) == EGL_FALSE )
+    EGLContext context = iRenderPlugin->EglSharedContext();
+    
+    // eglMakeCurrent with EGL_NO_SURFACE de-couples vgImage from an old eglpbufferfromclient surface.
+    // Otherwise in a multiple BindClientBuffer scenario for the same vgImage, eglMakeCurrent
+    // fails with an EGL_BAD_ACCESS error (vgimage already inuse error)
+    eglMakeCurrent(iRenderPlugin->EglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, context);
+	
+    // iSavedDrawSurface and iSavedReadSurface would be the window surface on top of which the
+    // group opacity vgImages(aBuffers) would have to be drawn. This is the reason why we store
+    // iSavedDrawSurface only once at the start of BindClientBuffer routine.
+    if ( eglMakeCurrent(iRenderPlugin->EglDisplay(), iSavedDrawSurface, iSavedReadSurface, context) == EGL_FALSE )
         {
         HUI_DEBUG1(_L("CHuiVg10VgImageBinder::BindClientBuffer() - EGL Surface could not be made current, eglErr: %04x"), eglGetError());
         return KErrGeneral;
         }
-    
-    iSavedDrawSurface = 0;
-    iSavedReadSurface = 0;
-    iSavedContext = 0;
+
+    // When the final UnBindClientBuffer is called and the vgimage has to be drawn on to the window surface.
+    // We would lose the handles if these iSaved surfaces are set to zero. 
+//    iSavedDrawSurface = 0;
+//    iSavedReadSurface = 0;
+//    iSavedContext = 0;
 
     if (iEglPBufferSurface_Client)
         {
+        TInt bufferIndex = iGroupOpacitySurfaces.Find(iEglPBufferSurface_Client);
+        iGroupOpacitySurfaces.Remove(bufferIndex);
+        iGroupOpacityImages.Remove(bufferIndex);
         eglDestroySurface( iRenderPlugin->EglDisplay(), iEglPBufferSurface_Client );
         iEglPBufferSurface_Client = EGL_NO_SURFACE;
         }
-    
+
     // Everything went fine
     return KErrNone;
     }