diff -r 46927d61fef3 -r 3ac8bf5c5014 uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10VGImageBinder.cpp --- 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(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(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; }