uiacceltk/hitchcock/coretoolkit/rendervg10/src/huivg10canvasrenderbuffer.cpp
changeset 0 15bf7259bb7c
child 17 3ac8bf5c5014
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     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:   Class canvas renderering target
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "huivg10canvasrenderbuffer.h"
       
    21 #include "HuiVg10RenderPlugin.h"
       
    22 #include "uiacceltk/HuiUtil.h"
       
    23 #include "uiacceltk/HuiEnv.h"
       
    24 #include "HuiVg10RenderPlugin.h"
       
    25 #include "uiacceltk/HuiDisplay.h"
       
    26 
       
    27 //#define HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
    28 
       
    29 
       
    30 CHuiVg10CanvasRenderBuffer::CHuiVg10CanvasRenderBuffer()
       
    31     {       
       
    32     }
       
    33 
       
    34 CHuiVg10CanvasRenderBuffer::~CHuiVg10CanvasRenderBuffer()
       
    35     {
       
    36     UnInitialize();
       
    37     }
       
    38 
       
    39 void CHuiVg10CanvasRenderBuffer::UnInitialize()
       
    40     {
       
    41     CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
       
    42 
       
    43     UnBind();
       
    44 
       
    45     if (iGc)
       
    46         {
       
    47         delete iGc;
       
    48         iGc = 0;
       
    49         }
       
    50     
       
    51     if (iRotatedImage)
       
    52         {
       
    53         vgDestroyImage(iRotatedImage);
       
    54         iRotatedImage = VG_INVALID_HANDLE;
       
    55         }
       
    56 
       
    57     if (iImage)
       
    58         {
       
    59         vgDestroyImage(iImage);
       
    60         iImage = VG_INVALID_HANDLE;
       
    61         }
       
    62     
       
    63     if (iSurface)
       
    64         {
       
    65         eglDestroySurface(renderer.EglDisplay(), iSurface);
       
    66         iSurface = 0;
       
    67         }
       
    68     
       
    69     if (iContext)
       
    70         {
       
    71         eglDestroyContext(renderer.EglDisplay(), iContext);      
       
    72         iContext = 0;
       
    73         }
       
    74 
       
    75     iInitialized = EFalse;
       
    76     }
       
    77 
       
    78 void CHuiVg10CanvasRenderBuffer::InitializeL(const TSize& aSize)
       
    79     {    
       
    80     if (iSize == aSize && iImage && iContext && iSurface)
       
    81         {
       
    82         // Already initalized
       
    83         return;
       
    84         }
       
    85 
       
    86     CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
       
    87     
       
    88     // Just in case...
       
    89     UnInitialize();
       
    90 
       
    91     PushEGLContext();
       
    92     
       
    93 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
    94         TTime startTime;
       
    95         startTime.UniversalTime();
       
    96 #endif
       
    97     
       
    98     iSize = aSize;        
       
    99 
       
   100 #ifndef __WINS__ // Should possibly query the supported mode instead?
       
   101     VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE;
       
   102 #else
       
   103     VGImageFormat imageInternalFormat = VG_sARGB_8888;
       
   104 #endif
       
   105     
       
   106     iImage = vgCreateImage(imageInternalFormat, iSize.iWidth, iSize.iHeight, 
       
   107                            VG_IMAGE_QUALITY_NONANTIALIASED);
       
   108 
       
   109     if (iImage == VG_INVALID_HANDLE)
       
   110         {
       
   111         PopEGLContext();
       
   112 
       
   113         VGErrorCode err = vgGetError();
       
   114         RDebug::Print(_L("CHuiVg10CanvasRenderBuffer::InitializeL() - vgCreateImage failed: VgError -- %04x"), err);
       
   115         User::Leave(KErrGeneral);
       
   116         }
       
   117         
       
   118     const TInt BITS_PER_CHANNEL = 8;
       
   119     
       
   120     // Choose an EGL config
       
   121     const EGLint attrs[] =
       
   122         {
       
   123         EGL_SURFACE_TYPE,       EGL_PBUFFER_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT,
       
   124         EGL_RENDERABLE_TYPE,    EGL_OPENVG_BIT,
       
   125         EGL_RED_SIZE,           BITS_PER_CHANNEL,
       
   126         EGL_GREEN_SIZE,         BITS_PER_CHANNEL,
       
   127         EGL_BLUE_SIZE,          BITS_PER_CHANNEL,
       
   128         EGL_ALPHA_SIZE,         BITS_PER_CHANNEL,
       
   129         EGL_NONE
       
   130         };
       
   131     TInt configCount = renderer.EglChooseConfig(attrs);
       
   132     ASSERT(configCount > 0);
       
   133 
       
   134     if (configCount <= 0)
       
   135         {
       
   136         PopEGLContext();
       
   137 
       
   138         RDebug::Print(_L("CHuiVg10CanvasRenderBuffer::InitializeL() - no EGL config found !"));
       
   139         User::Leave(KErrGeneral);
       
   140         }    
       
   141     
       
   142     EGLConfig config = renderer.EglConfig(0);
       
   143     
       
   144     // Create a context
       
   145     iContext = eglCreateContext(renderer.EglDisplay(), config,
       
   146             renderer.EglSharedContext(), NULL);
       
   147 
       
   148     if(!iContext)
       
   149         {
       
   150         PopEGLContext();
       
   151 
       
   152         EGLint err = eglGetError();
       
   153         RDebug::Print(_L("CHuiVg10CanvasRenderBuffer::InitializeL() - EGLContext creation failed: EglError -- %04x"), err);
       
   154         User::Leave(KErrGeneral);
       
   155         }
       
   156 
       
   157     // Create a pbuffer surface
       
   158     iSurface = eglCreatePbufferFromClientBuffer(renderer.EglDisplay(), EGL_OPENVG_IMAGE,
       
   159                                                 iImage, config, NULL);
       
   160     if(!iSurface)
       
   161         {
       
   162         PopEGLContext();
       
   163 
       
   164         EGLint err = eglGetError();
       
   165         RDebug::Print(_L("CHuiVg10CanvasRenderBuffer::InitializeL() - EGLSurface creation failed: EglError -- %04x"), err);
       
   166         User::Leave(KErrGeneral);
       
   167         }
       
   168     
       
   169     // Initialize the context (TODO: We perhaps do not really need to do this by creating Cg 
       
   170     iGc = renderer.CreateGcL();
       
   171     Bind();
       
   172     iGc->InitState();
       
   173         
       
   174     VGfloat color[] = 
       
   175                 {
       
   176                 0.f, 0.f, 0.f, 0.f
       
   177                 };
       
   178     vgSetfv(VG_CLEAR_COLOR, sizeof(color) / sizeof(VGfloat), color);
       
   179     vgClear(0, 0, iSize.iWidth, iSize.iHeight);
       
   180     UnBind();
       
   181 
       
   182     // Let renderer know that we have been fiddlling with OpenVg state directly
       
   183     // "iGc->InitState" confuses scissoring setting, so lets notify it.
       
   184     renderer.AddRestoreStateFlags(EHuiVg10GcStateFlagDirtyScissor);    
       
   185     renderer.AddRestoreStateFlags(EHuiVg10GcStateFlagDirtyBlendMode);    
       
   186     
       
   187  #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
   188         TTime endTime;
       
   189         endTime.UniversalTime();
       
   190         TInt timeInMs =  endTime.MicroSecondsFrom( startTime ).Int64()/1000;           
       
   191         RDebug::Print(_L("> CHuiVg10CanvasRenderBuffer::InitializeL took %i ms"), timeInMs);
       
   192 #endif
       
   193 
       
   194     iInitialized = ETrue;
       
   195     
       
   196     PopEGLContext();
       
   197     }
       
   198 
       
   199 void CHuiVg10CanvasRenderBuffer::Bind()
       
   200     {
       
   201     // Make sure it is safe to call even if "UnBind" has not been called or this function
       
   202     // has already been called.
       
   203     if (!iSurface || !iContext || iSavedContext || iSavedDrawSurface || iSavedReadSurface)
       
   204         {
       
   205         return;
       
   206         }
       
   207     
       
   208     // Save current context and surfaces
       
   209     iSavedContext = eglGetCurrentContext();
       
   210     iSavedDrawSurface = eglGetCurrentSurface(EGL_DRAW);
       
   211     iSavedReadSurface = eglGetCurrentSurface(EGL_READ);
       
   212     
       
   213     // Bind our own surface
       
   214     CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
       
   215     eglMakeCurrent(renderer.EglDisplay(), iSurface, iSurface, iContext);
       
   216     }
       
   217 
       
   218 void CHuiVg10CanvasRenderBuffer::UnBind()
       
   219     {
       
   220     // Make sure it is safe to call even if "Bind" has not been called or this
       
   221     // function has already been called.
       
   222     if (!iSavedDrawSurface || !iSavedReadSurface || !iSavedContext)
       
   223         {
       
   224         return;
       
   225         }        
       
   226     
       
   227     // Restore original surface & context
       
   228     CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
       
   229 	
       
   230 	// Todo: Should check whether the saved surface was UI surface 
       
   231 	// and call CHuiVg10RenderSurface::MakeCurrent() for that instead
       
   232 	CHuiEnv* env = CHuiEnv::Static();  
       
   233 	if (env && env->iSwapObserver)
       
   234 	    {    
       
   235         env->iSwapObserver->ReleaseWindowServer();
       
   236 	    }
       
   237 
       
   238     eglMakeCurrent(renderer.EglDisplay(), iSavedDrawSurface, iSavedReadSurface,
       
   239         iSavedContext);
       
   240         
       
   241     if (env && env->iSwapObserver)
       
   242         {
       
   243         env->iSwapObserver->ReleaseWindowServer(EFalse);
       
   244         }
       
   245     
       
   246     iSavedDrawSurface = 0;
       
   247     iSavedReadSurface = 0;
       
   248     iSavedContext = 0;    
       
   249     }
       
   250 
       
   251 VGImage CHuiVg10CanvasRenderBuffer::Image() const
       
   252     {
       
   253     return iImage;
       
   254     }
       
   255 
       
   256 
       
   257 void CHuiVg10CanvasRenderBuffer::PushEGLContext()
       
   258     {
       
   259     CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
       
   260     iPreviousEGLState.iContext= eglGetCurrentContext(); 
       
   261     TEGLState& state = renderer.GetUploadState();
       
   262     if (state.iContext == KErrNotFound)
       
   263         {
       
   264         TEGLState& state = renderer.GetUploadState();
       
   265         // the first context used for uploading will be used for all texture uploads
       
   266         state.iContext      = iPreviousEGLState.iContext; 
       
   267         state.iDrawSurface  = eglGetCurrentSurface(EGL_DRAW);
       
   268         state.iReadSurface  = eglGetCurrentSurface(EGL_READ);
       
   269         state.iDisplay      = eglGetCurrentDisplay();
       
   270         }
       
   271     else
       
   272         {
       
   273         // change context only if necessary
       
   274         if (iPreviousEGLState.iContext != state.iContext)
       
   275             {
       
   276             iPreviousEGLState.iDrawSurface  = eglGetCurrentSurface(EGL_DRAW);
       
   277             iPreviousEGLState.iReadSurface  = eglGetCurrentSurface(EGL_READ);
       
   278             iPreviousEGLState.iDisplay      = eglGetCurrentDisplay();
       
   279             eglMakeCurrent(state.iDisplay, state.iDrawSurface, state.iReadSurface, state.iContext);
       
   280             }
       
   281         }
       
   282     }
       
   283 
       
   284 void CHuiVg10CanvasRenderBuffer::PopEGLContext()
       
   285     {
       
   286     CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
       
   287     if (iPreviousEGLState.iContext != renderer.GetUploadState().iContext)
       
   288         {
       
   289         eglMakeCurrent(iPreviousEGLState.iDisplay,  iPreviousEGLState.iDrawSurface, iPreviousEGLState.iReadSurface,iPreviousEGLState.iContext);
       
   290         }
       
   291     }
       
   292 
       
   293 void CHuiVg10CanvasRenderBuffer::Copy(const CHuiCanvasRenderBuffer& aSourceBuffer)
       
   294     {
       
   295     if (iSize != aSourceBuffer.Size())
       
   296         {
       
   297         return;
       
   298         }
       
   299     
       
   300     CHuiVg10CanvasRenderBuffer* sourcebuffer = (CHuiVg10CanvasRenderBuffer*) &aSourceBuffer;    
       
   301     vgCopyImage(iImage, 0, 0, 
       
   302             sourcebuffer->Image(), 0, 0, 
       
   303             iSize.iWidth, iSize.iHeight, VG_FALSE);
       
   304     }
       
   305 
       
   306 void CHuiVg10CanvasRenderBuffer::Copy(TPoint aPoint)
       
   307     {
       
   308     ReadBackground(aPoint);
       
   309     }
       
   310 
       
   311 void CHuiVg10CanvasRenderBuffer::ReadBackground(TPoint aPosition)
       
   312     {
       
   313     CHuiDisplay& display = CHuiStatic::Env().PrimaryDisplay();        
       
   314     TBool rotatedDisplay = display.Orientation() == CHuiGc::EOrientationCCW90 || display.Orientation() == CHuiGc::EOrientationCW90;
       
   315     TRect renderBufferLocation = TRect(aPosition, iSize);
       
   316     
       
   317     TRect displayArea = display.VisibleArea();
       
   318     
       
   319     TInt displayHeight = displayArea.Height();
       
   320     TInt displayWidth = displayArea.Width();
       
   321    
       
   322     TSize rotatedSize = iSize;
       
   323     TPoint rotatedPos = aPosition;
       
   324     
       
   325     // Read pixels from surface        
       
   326     if (rotatedDisplay)
       
   327         {
       
   328         if (iRotatedImage == VG_INVALID_HANDLE)
       
   329             {
       
   330             PushEGLContext();
       
   331             
       
   332             #ifndef __WINS__ // Should possibly query the supported mode instead?
       
   333                 VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE;
       
   334             #else
       
   335                 VGImageFormat imageInternalFormat = VG_sARGB_8888;
       
   336             #endif
       
   337 
       
   338             TSize rotatedImageSize = TSize(iSize.iHeight, iSize.iWidth);
       
   339             iRotatedImage = vgCreateImage(imageInternalFormat, rotatedImageSize.iWidth, rotatedImageSize.iHeight, 
       
   340                                VG_IMAGE_QUALITY_NONANTIALIASED);
       
   341 
       
   342             PopEGLContext();
       
   343             }
       
   344         
       
   345         
       
   346         // If we have rotation on CHuiGc level, we must manually take that into account when
       
   347         // accessing pixels directly                
       
   348         if(display.Orientation() == CHuiGc::EOrientationCCW90)
       
   349             {
       
   350             // Rotate the buffer location relative to real surface coordinates
       
   351             rotatedSize = TSize(iSize.iHeight, iSize.iWidth);
       
   352             rotatedPos = TPoint(displayHeight - aPosition.iY - iSize.iHeight, aPosition.iX);                        
       
   353             renderBufferLocation = TRect(rotatedPos, rotatedSize);            
       
   354             }
       
   355         else if(display.Orientation() == CHuiGc::EOrientationCW90)
       
   356             {
       
   357             // Rotate the buffer location relative to real surface coordinates
       
   358             rotatedSize = TSize(iSize.iHeight, iSize.iWidth);
       
   359             rotatedPos = TPoint(aPosition.iY, displayWidth - aPosition.iX - iSize.iWidth);            
       
   360             renderBufferLocation = TRect(rotatedPos, rotatedSize);
       
   361             }
       
   362         else
       
   363             {
       
   364             // nothing
       
   365             }        
       
   366 
       
   367         // If screen is rotated but surface is not in native orientation, this gets difficult
       
   368         // because vgGetPixels is not affected by transformations.
       
   369 
       
   370         // Swap h and w so that those are the "real" values from surface point of view.
       
   371         displayHeight = displayWidth;
       
   372 
       
   373         #ifdef HUIFX_TRACE    
       
   374         RDebug::Print(_L("CHuiFxVg10OffscreenRenderbuffer::PrepareForReuse - renderBufferLocation: %i,%i, %i,%i "), 
       
   375                 renderBufferLocation.iTl.iX,
       
   376                 renderBufferLocation.iTl.iY,
       
   377                 renderBufferLocation.iBr.iX,
       
   378                 renderBufferLocation.iBr.iY);
       
   379 
       
   380         TRect vgRect(TPoint(renderBufferLocation.iTl.iX, displayHeight - renderBufferLocation.iTl.iY - rotatedSize.iHeight), rotatedSize);
       
   381 
       
   382         RDebug::Print(_L("CHuiFxVg10OffscreenRenderbuffer::PrepareForReuse - vgRect: %i,%i, %i,%i "), 
       
   383                 vgRect.iTl.iX,
       
   384                 vgRect.iTl.iY,
       
   385                 vgRect.iBr.iX,
       
   386                 vgRect.iBr.iY);
       
   387         #endif
       
   388         
       
   389         // So...first get pixels from surface into rotated image
       
   390         vgGetPixels(iRotatedImage, 0, 0, renderBufferLocation.iTl.iX, displayHeight - renderBufferLocation.iTl.iY - rotatedSize.iHeight, rotatedSize.iWidth, rotatedSize.iHeight);
       
   391         
       
   392         // Draw rotated image into real buffer image, first bind it as render target...
       
   393         Bind();            
       
   394         
       
   395         // ...store some states...
       
   396         const TInt VG_MATRIX_SIZE = 9;
       
   397         VGfloat oldMatrix[VG_MATRIX_SIZE];
       
   398         vgGetMatrix(oldMatrix);
       
   399 
       
   400         // ...set some vg states...
       
   401         vgLoadIdentity();
       
   402         vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
       
   403         vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
       
   404         vgSeti(VG_SCISSORING, VG_FALSE);
       
   405 
       
   406         TInt w = iSize.iWidth;
       
   407         TInt h = iSize.iHeight;
       
   408         
       
   409         // ...select right rotation...
       
   410         if (display.Orientation() == CHuiGc::EOrientationCW90)
       
   411             {
       
   412             // Rotate around origo and move back to displayarea
       
   413             vgRotate(-90);
       
   414             vgTranslate(-h, 0);
       
   415             }
       
   416         else if (display.Orientation() == CHuiGc::EOrientationCCW90)
       
   417             {
       
   418             // Rotate around origo and move back to displayarea
       
   419             vgRotate(90);
       
   420             vgTranslate(0, -w);
       
   421             }
       
   422         else if (display.Orientation() == CHuiGc::EOrientation180)
       
   423             {
       
   424             // Rotate around origo and move back to displayarea
       
   425             vgRotate(180);
       
   426             vgTranslate(-w, -h);            
       
   427             }
       
   428         else
       
   429             {
       
   430             }        
       
   431         
       
   432         // ...Draw...
       
   433         if (iRotatedImage != VG_INVALID_HANDLE)
       
   434             {
       
   435             vgDrawImage(iRotatedImage);
       
   436             }
       
   437         
       
   438         // ..and restore default VG states
       
   439         vgSeti(VG_SCISSORING, VG_TRUE);
       
   440         vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
       
   441         vgLoadMatrix(oldMatrix);
       
   442 
       
   443         // ...finally unbind image and we should have the content correctly.
       
   444         UnBind();
       
   445         }
       
   446     else
       
   447         {
       
   448         // Much easier if no rotation !
       
   449         vgGetPixels(iImage, 0, 0, renderBufferLocation.iTl.iX, displayHeight - renderBufferLocation.iTl.iY - rotatedSize.iHeight, rotatedSize.iWidth, rotatedSize.iHeight);
       
   450         }
       
   451     }
       
   452