uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiFxVg10OffscreenRenderbuffer.cpp
changeset 0 15bf7259bb7c
child 17 3ac8bf5c5014
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "HuiFxVg10OffscreenRenderbuffer.h"
       
    21 #include "HuiVg10RenderPlugin.h"
       
    22 #include "uiacceltk/HuiEnv.h"
       
    23 #include "uiacceltk/HuiDisplay.h"
       
    24 
       
    25 CHuiFxVg10OffscreenRenderbuffer* CHuiFxVg10OffscreenRenderbuffer::NewL(CHuiVg10RenderPlugin& aPlugin, const TSize& aSize)
       
    26     {
       
    27     CHuiFxVg10OffscreenRenderbuffer* e = new (ELeave) CHuiFxVg10OffscreenRenderbuffer();
       
    28     CleanupStack::PushL(e);
       
    29     e->ConstructL(aPlugin, aSize);
       
    30     CleanupStack::Pop(e);
       
    31     return e;
       
    32     }
       
    33 
       
    34 void CHuiFxVg10OffscreenRenderbuffer::ConstructL(CHuiVg10RenderPlugin& aPlugin, const TSize& aSize)
       
    35     {
       
    36     CHuiFxRenderbuffer::ConstructL(aSize, EBufferTypeOffscreen);
       
    37     iPlugin = &aPlugin;
       
    38 
       
    39     PushEGLContext();
       
    40     
       
    41 #ifndef __WINS__ // Should possibly query the supported mode instead?
       
    42     VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE;
       
    43 #else
       
    44     VGImageFormat imageInternalFormat = VG_sARGB_8888;
       
    45 #endif
       
    46 
       
    47     iImage = vgCreateImage(imageInternalFormat, aSize.iWidth, aSize.iHeight, 
       
    48                            VG_IMAGE_QUALITY_NONANTIALIASED);
       
    49 
       
    50     HUIFX_VG_INVARIANT();
       
    51 
       
    52     const TInt BITS_PER_CHANNEL = 8;
       
    53     
       
    54     // Choose an EGL config
       
    55     const EGLint attrs[] =
       
    56         {
       
    57         EGL_SURFACE_TYPE,       EGL_PBUFFER_BIT,
       
    58         EGL_RENDERABLE_TYPE,    EGL_OPENVG_BIT,
       
    59         EGL_RED_SIZE,           BITS_PER_CHANNEL,
       
    60         EGL_GREEN_SIZE,         BITS_PER_CHANNEL,
       
    61         EGL_BLUE_SIZE,          BITS_PER_CHANNEL,
       
    62         EGL_ALPHA_SIZE,         BITS_PER_CHANNEL,
       
    63         EGL_NONE
       
    64         };
       
    65     TInt configCount = iPlugin->EglChooseConfig(attrs);
       
    66     ASSERT(configCount > 0);
       
    67     EGLConfig config = iPlugin->EglConfig(0);
       
    68     
       
    69     // Create a context
       
    70     iContext = eglCreateContext(iPlugin->EglDisplay(), config,
       
    71             iPlugin->EglSharedContext(), NULL);
       
    72     EGLint err = eglGetError();
       
    73     ASSERT(iContext);
       
    74     
       
    75     // Create a pbuffer surface
       
    76     iSurface = eglCreatePbufferFromClientBuffer(iPlugin->EglDisplay(), EGL_OPENVG_IMAGE,
       
    77                                                 iImage, config, NULL);
       
    78     ASSERT(iSurface);   
       
    79     
       
    80     // Initialize the context
       
    81     iGc = iPlugin->CreateGcL();
       
    82     this->InitGc(aSize);
       
    83 
       
    84     PopEGLContext();
       
    85     }
       
    86 
       
    87 CHuiFxVg10OffscreenRenderbuffer::~CHuiFxVg10OffscreenRenderbuffer()
       
    88     {  
       
    89     delete iGc;
       
    90     
       
    91     if(iPlugin)
       
    92         {
       
    93         eglDestroySurface(iPlugin->EglDisplay(), iSurface);
       
    94         eglDestroyContext(iPlugin->EglDisplay(), iContext); 
       
    95         }
       
    96     
       
    97     if (iRotatedImage != VG_INVALID_HANDLE)
       
    98         {
       
    99         vgDestroyImage(iRotatedImage);
       
   100         HUIFX_VG_INVARIANT();
       
   101         }
       
   102     vgDestroyImage(iImage);
       
   103     HUIFX_VG_INVARIANT();
       
   104     }
       
   105 
       
   106 void CHuiFxVg10OffscreenRenderbuffer::InitGc(const TSize& aSize)
       
   107     {
       
   108     BindAsRenderTarget();
       
   109     iGc->InitState();
       
   110     VGfloat color[] = 
       
   111                 {
       
   112                  .0f, .0f, .0f, .0f
       
   113                 };
       
   114     vgSetfv(VG_CLEAR_COLOR, sizeof(color) / sizeof(VGfloat), color);
       
   115     vgClear(0, 0, aSize.iWidth, aSize.iHeight);
       
   116     UnbindAsRenderTarget();
       
   117     
       
   118     // Let renderer know that we have been fiddlling with OpenVg state directly
       
   119     // "iGc->InitState" confuses scissoring setting, so lets notify it.
       
   120     CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
       
   121     renderer.AddRestoreStateFlags(EHuiVg10GcStateFlagDirtyScissor);    
       
   122     renderer.AddRestoreStateFlags(EHuiVg10GcStateFlagDirtyBlendMode);    
       
   123     }
       
   124 
       
   125 void CHuiFxVg10OffscreenRenderbuffer::PrepareForReuse(const TSize& aReusedSize)
       
   126     {
       
   127     if (iBackgroundEnabled)
       
   128         {
       
   129         ReadBackground();
       
   130         }
       
   131     else
       
   132         {
       
   133         const TInt COLOR_COMPONENTS = 4;
       
   134         VGfloat savedColor[COLOR_COMPONENTS];
       
   135         vgGetfv(VG_CLEAR_COLOR, COLOR_COMPONENTS, savedColor);
       
   136         
       
   137         VGfloat color[COLOR_COMPONENTS] = 
       
   138                     {
       
   139                      .0f, .0f, .0f, .0f
       
   140                     };
       
   141         vgSetfv(VG_CLEAR_COLOR, COLOR_COMPONENTS, color);
       
   142         vgClearImage(Image(), 0, 0, aReusedSize.iWidth, aReusedSize.iHeight);
       
   143         vgSetfv(VG_CLEAR_COLOR, COLOR_COMPONENTS, savedColor);        
       
   144         }
       
   145     
       
   146     HUIFX_VG_INVARIANT();
       
   147     }
       
   148 
       
   149 CHuiGc& CHuiFxVg10OffscreenRenderbuffer::BindAsRenderTarget()
       
   150     {
       
   151     // Save current context and surfaces
       
   152     iSavedContext = eglGetCurrentContext();
       
   153     iSavedDrawSurface = eglGetCurrentSurface(EGL_DRAW);
       
   154     iSavedReadSurface = eglGetCurrentSurface(EGL_READ);
       
   155     ASSERT(iSavedContext != iContext);
       
   156     ASSERT(iSavedDrawSurface != iSurface);
       
   157     ASSERT(iSavedReadSurface != iSurface);
       
   158 
       
   159     // Bind our own surface
       
   160     eglMakeCurrent(iPlugin->EglDisplay(), iSurface, iSurface, iContext);
       
   161     ASSERT(eglGetError() == EGL_SUCCESS);
       
   162 
       
   163     return *iGc;
       
   164     }
       
   165 
       
   166 void CHuiFxVg10OffscreenRenderbuffer::BindAsTexture(THuiFxRenderbufferUsage aUsage)
       
   167     {
       
   168     // Nothing to do
       
   169     }
       
   170 
       
   171 void CHuiFxVg10OffscreenRenderbuffer::UnbindAsTexture()
       
   172     {
       
   173     // Nothing to do
       
   174     }
       
   175 
       
   176 void CHuiFxVg10OffscreenRenderbuffer::UnbindAsRenderTarget()
       
   177     {
       
   178     // Restore original surface & context
       
   179     eglMakeCurrent(iPlugin->EglDisplay(), iSavedDrawSurface, iSavedReadSurface,
       
   180         iSavedContext);
       
   181     ASSERT(eglGetError() == EGL_SUCCESS);
       
   182     }
       
   183 
       
   184 VGImage CHuiFxVg10OffscreenRenderbuffer::Image() const
       
   185     {
       
   186     return iImage;
       
   187     }
       
   188 
       
   189 void CHuiFxVg10OffscreenRenderbuffer::ReadBackground()
       
   190     {
       
   191     if (iBackgroundEnabled)
       
   192         {
       
   193         CHuiDisplay& display = CHuiStatic::Env().PrimaryDisplay();        
       
   194         TBool rotatedDisplay = display.Orientation() == CHuiGc::EOrientationCCW90 || display.Orientation() == CHuiGc::EOrientationCW90;
       
   195         TRect renderBufferLocation = TRect(iPosition, iSize);
       
   196 
       
   197 #ifdef HUIFX_TRACE    
       
   198         RDebug::Print(_L("CHuiFxVg10OffscreenRenderbuffer::PrepareForReuse - renderBufferLocation original: %i,%i, %i,%i "), 
       
   199                 renderBufferLocation.iTl.iX,
       
   200                 renderBufferLocation.iTl.iY,
       
   201                 renderBufferLocation.iBr.iX,
       
   202                 renderBufferLocation.iBr.iY);
       
   203 #endif
       
   204         
       
   205         TRect displayArea = display.VisibleArea();
       
   206         
       
   207         TInt displayHeight = displayArea.Height();
       
   208         TInt displayWidth = displayArea.Width();
       
   209        
       
   210         TSize rotatedSize = iSize;
       
   211         TPoint rotatedPos = iPosition;
       
   212         
       
   213         // Read pixels from surface        
       
   214         if (rotatedDisplay)
       
   215             {
       
   216             if (iRotatedImage == VG_INVALID_HANDLE)
       
   217                 {
       
   218                 PushEGLContext();
       
   219                 
       
   220                 #ifndef __WINS__ // Should possibly query the supported mode instead?
       
   221                     VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE;
       
   222                 #else
       
   223                     VGImageFormat imageInternalFormat = VG_sARGB_8888;
       
   224                 #endif
       
   225 
       
   226                 TSize rotatedImageSize = TSize(iSize.iHeight, iSize.iWidth);
       
   227                 iRotatedImage = vgCreateImage(imageInternalFormat, rotatedImageSize.iWidth, rotatedImageSize.iHeight, 
       
   228                                    VG_IMAGE_QUALITY_NONANTIALIASED);
       
   229 
       
   230                 PopEGLContext();
       
   231                 }
       
   232             
       
   233             
       
   234             // If we have rotation on CHuiGc level, we must manually take that into account when
       
   235             // accessing pixels directly                
       
   236             if(display.Orientation() == CHuiGc::EOrientationCCW90)
       
   237                 {
       
   238                 // Rotate the buffer location relative to real surface coordinates
       
   239                 rotatedSize = TSize(iSize.iHeight, iSize.iWidth);
       
   240                 rotatedPos = TPoint(displayHeight - iPosition.iY - iSize.iHeight, iPosition.iX);                        
       
   241                 renderBufferLocation = TRect(rotatedPos, rotatedSize);            
       
   242                 }
       
   243             else if(display.Orientation() == CHuiGc::EOrientationCW90)
       
   244                 {
       
   245                 // Rotate the buffer location relative to real surface coordinates
       
   246                 rotatedSize = TSize(iSize.iHeight, iSize.iWidth);
       
   247                 rotatedPos = TPoint(iPosition.iY, displayWidth - iPosition.iX - iSize.iWidth);            
       
   248                 renderBufferLocation = TRect(rotatedPos, rotatedSize);
       
   249                 }
       
   250             else
       
   251                 {
       
   252                 // nothing
       
   253                 }        
       
   254 
       
   255             // If screen is rotated but surface is not in native orientation, this gets difficult
       
   256             // because vgGetPixels is not affected by transformations.
       
   257 
       
   258             // Swap h and w so that those are the "real" values from surface point of view.
       
   259             displayHeight = displayWidth;
       
   260 
       
   261             #ifdef HUIFX_TRACE    
       
   262             RDebug::Print(_L("CHuiFxVg10OffscreenRenderbuffer::PrepareForReuse - renderBufferLocation: %i,%i, %i,%i "), 
       
   263                     renderBufferLocation.iTl.iX,
       
   264                     renderBufferLocation.iTl.iY,
       
   265                     renderBufferLocation.iBr.iX,
       
   266                     renderBufferLocation.iBr.iY);
       
   267 
       
   268             TRect vgRect(TPoint(renderBufferLocation.iTl.iX, displayHeight - renderBufferLocation.iTl.iY - rotatedSize.iHeight), rotatedSize);
       
   269 
       
   270             RDebug::Print(_L("CHuiFxVg10OffscreenRenderbuffer::PrepareForReuse - vgRect: %i,%i, %i,%i "), 
       
   271                     vgRect.iTl.iX,
       
   272                     vgRect.iTl.iY,
       
   273                     vgRect.iBr.iX,
       
   274                     vgRect.iBr.iY);
       
   275             #endif
       
   276             
       
   277             // So...first get pixels from surface into rotated image
       
   278             vgGetPixels(iRotatedImage, 0, 0, renderBufferLocation.iTl.iX, displayHeight - renderBufferLocation.iTl.iY - rotatedSize.iHeight, rotatedSize.iWidth, rotatedSize.iHeight);
       
   279             
       
   280             // Draw rotated image into real buffer image, first bind it as render target...
       
   281             BindAsRenderTarget();            
       
   282             
       
   283             // ...store some states...
       
   284             const TInt VG_MATRIX_SIZE = 9;
       
   285             VGfloat oldMatrix[VG_MATRIX_SIZE];
       
   286             vgGetMatrix(oldMatrix);
       
   287 
       
   288             // ...set some vg states...
       
   289             vgLoadIdentity();
       
   290             vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
       
   291             vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
       
   292             vgSeti(VG_SCISSORING, VG_FALSE);
       
   293 
       
   294             TInt w = iSize.iWidth;
       
   295             TInt h = iSize.iHeight;
       
   296             
       
   297             // ...select right rotation...
       
   298             if (display.Orientation() == CHuiGc::EOrientationCW90)
       
   299                 {
       
   300                 // Rotate around origo and move back to displayarea
       
   301                 vgRotate(-90);
       
   302                 vgTranslate(-h, 0);
       
   303                 }
       
   304             else if (display.Orientation() == CHuiGc::EOrientationCCW90)
       
   305                 {
       
   306                 // Rotate around origo and move back to displayarea
       
   307                 vgRotate(90);
       
   308                 vgTranslate(0, -w);
       
   309                 }
       
   310             else if (display.Orientation() == CHuiGc::EOrientation180)
       
   311                 {
       
   312                 // Rotate around origo and move back to displayarea
       
   313                 vgRotate(180);
       
   314                 vgTranslate(-w, -h);            
       
   315                 }
       
   316             else
       
   317                 {
       
   318                 }        
       
   319             
       
   320             // ...Draw...
       
   321             if (iRotatedImage != VG_INVALID_HANDLE)
       
   322                 {
       
   323                 vgDrawImage(iRotatedImage);
       
   324                 }
       
   325             
       
   326             // ..and restore default VG states
       
   327             vgSeti(VG_SCISSORING, VG_TRUE);
       
   328             vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
       
   329             vgLoadMatrix(oldMatrix);
       
   330 
       
   331             // ...finally unbind image and we should have the content correctly.
       
   332             UnbindAsRenderTarget();
       
   333             }
       
   334         else
       
   335             {
       
   336             // Much easier if no rotation !
       
   337             vgGetPixels(iImage, 0, 0, renderBufferLocation.iTl.iX, displayHeight - renderBufferLocation.iTl.iY - rotatedSize.iHeight, rotatedSize.iWidth, rotatedSize.iHeight);
       
   338             }
       
   339         }    
       
   340     }
       
   341 
       
   342 void CHuiFxVg10OffscreenRenderbuffer::PushEGLContext()
       
   343     {
       
   344     iPreviousEGLState.iContext= eglGetCurrentContext(); 
       
   345     TEGLState& state = iPlugin->GetUploadState();
       
   346     if (state.iContext == KErrNotFound)
       
   347         {
       
   348         TEGLState& state = iPlugin->GetUploadState();
       
   349         // the first context used for uploading will be used for all texture uploads
       
   350         state.iContext      = iPreviousEGLState.iContext; 
       
   351         state.iDrawSurface  = eglGetCurrentSurface(EGL_DRAW);
       
   352         state.iReadSurface  = eglGetCurrentSurface(EGL_READ);
       
   353         state.iDisplay      = eglGetCurrentDisplay();
       
   354         }
       
   355     else
       
   356         {
       
   357         // change context only if necessary
       
   358         if (iPreviousEGLState.iContext != state.iContext)
       
   359             {
       
   360             iPreviousEGLState.iDrawSurface  = eglGetCurrentSurface(EGL_DRAW);
       
   361             iPreviousEGLState.iReadSurface  = eglGetCurrentSurface(EGL_READ);
       
   362             iPreviousEGLState.iDisplay      = eglGetCurrentDisplay();
       
   363             eglMakeCurrent(state.iDisplay, state.iDrawSurface, state.iReadSurface, state.iContext);
       
   364             }
       
   365         }
       
   366     }
       
   367 
       
   368 void CHuiFxVg10OffscreenRenderbuffer::PopEGLContext()
       
   369     {
       
   370     if (iPreviousEGLState.iContext != iPlugin->GetUploadState().iContext)
       
   371         {
       
   372         eglMakeCurrent(iPreviousEGLState.iDisplay,  iPreviousEGLState.iDrawSurface, iPreviousEGLState.iReadSurface,iPreviousEGLState.iContext);
       
   373         }
       
   374     }