javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/library/graphics/qt/windowsurfaceimpl_symbian.cpp
changeset 35 85266cc22c7f
child 48 e0d6e9bd3ca7
equal deleted inserted replaced
26:dc7c549001d5 35:85266cc22c7f
       
     1 /*******************************************************************************
       
     2  * Copyright (c) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3  * All rights reserved. This program and the accompanying materials
       
     4  * are made available under the terms of the Eclipse Public License v1.0
       
     5  * which accompanies this distribution, and is available at
       
     6  * http://www.eclipse.org/legal/epl-v10.html
       
     7  *
       
     8  * Contributors:
       
     9  *     Nokia Corporation - initial API and implementation
       
    10  *******************************************************************************/
       
    11 
       
    12 //#include <QtOpenGL>
       
    13 #include <QWidget>
       
    14 #include <QPainter>
       
    15 #include <QPaintEngine>
       
    16 #include "windowsurfaceimpl_symbian.h"
       
    17 #include "gfxlog.h"
       
    18 
       
    19 namespace Java { namespace GFX {
       
    20 
       
    21 WindowSurfaceImpl::WindowSurfaceImpl(QPaintDevice* aSurface, WindowSurfaceType aType)
       
    22 : mIsBound(false),
       
    23   mBufferedRendering(false),
       
    24   mAutoRefresh(false),
       
    25   mPaintingStarted(false)
       
    26 {
       
    27     GFX_LOG_FUNC_CALL();
       
    28     mMainSurface.device = aSurface;
       
    29     mMainSurface.type = aType;
       
    30 }
       
    31 
       
    32 WindowSurfaceImpl::WindowSurfaceImpl(QWidget* aWidget, bool aAutoRefresh)
       
    33 : mIsBound(false),
       
    34   mBufferedRendering(false),
       
    35   mAutoRefresh(false),
       
    36   mPaintingStarted(false)
       
    37 {
       
    38     GFX_LOG_FUNC_CALL();
       
    39     if(aWidget == NULL) 
       
    40     {
       
    41         throw GfxException(EGfxErrorIllegalArgument, "Target widget is NULL");
       
    42     }
       
    43     mMainSurface.widget = aWidget;
       
    44     mAutoRefresh = aAutoRefresh;
       
    45     updateSurfaceData();   
       
    46 }
       
    47 
       
    48 
       
    49 WindowSurfaceImpl::~WindowSurfaceImpl()
       
    50 {
       
    51     GFX_LOG_FUNC_CALL();
       
    52     if(mMainSurface.localSurface != NULL)
       
    53     {
       
    54         delete mMainSurface.localSurface;
       
    55         mMainSurface.localSurface = NULL;
       
    56     }
       
    57 }
       
    58 
       
    59 void WindowSurfaceImpl::beginPaint(int aX, int aY, int aWidth, int aHeight)
       
    60 {
       
    61     if(mAutoRefresh && (mMainSurface.widget != NULL)) 
       
    62     {
       
    63         updateSurfaceData();
       
    64     }
       
    65     if(!mMainSurface.localSurfaceInUse)
       
    66     {
       
    67         QRegion region(aX, aY, aWidth, aHeight);
       
    68         mMainSurface.qSurface->beginPaint(region);
       
    69         // In case local surface was used last round
       
    70         // and we now have Qt's window surface again
       
    71         // delete the local surface to save memory
       
    72         if(mMainSurface.localSurface != NULL)
       
    73         {
       
    74             delete mMainSurface.localSurface;
       
    75             mMainSurface.localSurface = NULL;
       
    76         }
       
    77     }
       
    78     mPaintingStarted = true;
       
    79 }
       
    80 
       
    81 void WindowSurfaceImpl::endPaint()
       
    82 {
       
    83     if(!mMainSurface.localSurfaceInUse)
       
    84     {
       
    85         mMainSurface.qSurface->endPaint(QRegion());
       
    86     }
       
    87     mPaintingStarted = false;
       
    88 }
       
    89 
       
    90 void WindowSurfaceImpl::flush()
       
    91 {
       
    92     if(!mMainSurface.localSurfaceInUse)
       
    93     { 
       
    94         QRegion region(0,0,mMainSurface.device->width(), mMainSurface.device->height());  
       
    95         mMainSurface.qSurface->flush(mMainSurface.widget, region, QPoint());
       
    96     }
       
    97 }
       
    98 
       
    99 void WindowSurfaceImpl::bind(int aCapabilies)
       
   100 {
       
   101     GFX_LOG_FUNC_CALL();
       
   102     // Bind is not allowed if beginPaint has not been called
       
   103     if(!mPaintingStarted)
       
   104     {
       
   105         throw GfxException(EGfxErrorIllegalState, "beginPaint() not called before bind()");
       
   106     }
       
   107     
       
   108     switch (mMainSurface.type)
       
   109     {
       
   110         case WsTypeQtImage:
       
   111         {
       
   112             mBufferedRendering = true;
       
   113             break;
       
   114         }
       
   115         
       
   116         case WsTypeEglSurface:
       
   117         {
       
   118             // If caller does not support EGL surface
       
   119             // create temp buffer to be used as target and
       
   120             // copy pixels from window surface to temp buffer
       
   121             if ((aCapabilies & WsTypeEglSurface) == 0) {
       
   122                 // TODO copy pixels from EGL surface to 
       
   123                 // QImage created here
       
   124                 
       
   125             } else {
       
   126                 // Caller supports EGL surface, so just 
       
   127                 // save EGL state here
       
   128                 saveEglState();
       
   129             }
       
   130             break;
       
   131         }
       
   132         case WsTypeSymbianBitmap:
       
   133         {
       
   134             break;
       
   135         }
       
   136         default:
       
   137         {
       
   138             // we should newer get here
       
   139         }
       
   140     }
       
   141     mIsBound = true;
       
   142 }
       
   143 
       
   144 int WindowSurfaceImpl::getType()
       
   145 {
       
   146     GFX_LOG_FUNC_CALL();
       
   147     return mMainSurface.type;
       
   148 }
       
   149 
       
   150 QPaintDevice* WindowSurfaceImpl::getDevice()
       
   151 {
       
   152     return mMainSurface.device;
       
   153 }
       
   154 
       
   155 
       
   156 EGLSurface WindowSurfaceImpl::getEglSurface()
       
   157 {
       
   158     return mEgl.drawSurface;
       
   159 }
       
   160 
       
   161 EGLenum WindowSurfaceImpl::getEglApi()
       
   162 {
       
   163     return mEgl.api;
       
   164 }
       
   165 
       
   166 CFbsBitmap* WindowSurfaceImpl::getSymbianBitmap()
       
   167 {
       
   168     return mMainSurface.symbianBitmap;
       
   169 }
       
   170 
       
   171 QImage* WindowSurfaceImpl::getQtImage()
       
   172 {
       
   173     return mMainSurface.localSurface;
       
   174 }
       
   175 
       
   176 void WindowSurfaceImpl::refresh()
       
   177 {
       
   178     updateSurfaceData();
       
   179 }
       
   180 
       
   181 void WindowSurfaceImpl::release()
       
   182 {
       
   183     GFX_LOG_FUNC_CALL();
       
   184     if (!mIsBound)
       
   185     {
       
   186         return;
       
   187     }
       
   188 
       
   189     if (mBufferedRendering)
       
   190     {
       
   191         // TODO draw QImage with painter to actual target
       
   192     }
       
   193     else
       
   194     {
       
   195         if(mMainSurface.type == WsTypeEglSurface)
       
   196         {
       
   197             restoreEglState();
       
   198         }
       
   199         // pixels are already rendered to the target
       
   200         // no post blitter hook needed
       
   201     }
       
   202     mIsBound = false;
       
   203 }
       
   204 
       
   205 void WindowSurfaceImpl::dispose()
       
   206 {
       
   207     GFX_LOG_FUNC_CALL();
       
   208     delete this;
       
   209 }
       
   210 
       
   211 void WindowSurfaceImpl::saveEglState()
       
   212 {
       
   213     // Some painter needs to be active on the device
       
   214     // in order to get correct data from EGL, so if 
       
   215     // there's no active painter, activate one here
       
   216     if(!mMainSurface.device->paintingActive())
       
   217     {
       
   218         mPainter.begin(mMainSurface.device);
       
   219     }
       
   220     mEgl.drawSurface = eglGetCurrentSurface(EGL_DRAW);
       
   221     mEgl.readSurface = eglGetCurrentSurface(EGL_READ);
       
   222     mEgl.display = eglGetCurrentDisplay();
       
   223     mEgl.context = eglGetCurrentContext();
       
   224     mEgl.api = eglQueryAPI();
       
   225 }
       
   226     
       
   227 void WindowSurfaceImpl::restoreEglState()
       
   228 {
       
   229     eglBindAPI(mEgl.api);
       
   230     eglMakeCurrent(mEgl.display, mEgl.drawSurface, mEgl.readSurface, mEgl.context);
       
   231     
       
   232     // if owned painter was activate to the device 
       
   233     // release it
       
   234     if(mPainter.isActive())
       
   235     {
       
   236         mPainter.end();
       
   237     }
       
   238 }
       
   239 
       
   240 // Private methods
       
   241 
       
   242 void WindowSurfaceImpl::createLocalSurface(int aWidth, int aHeight)
       
   243 {
       
   244     mMainSurface.localSurface = new QImage(aWidth, aHeight, QImage::Format_ARGB32);
       
   245     if(mMainSurface.localSurface->isNull()) 
       
   246     {   
       
   247         throw GfxException(EGfxErrorNoMemory, "Local Surface creation failed");
       
   248     }   
       
   249 }
       
   250 
       
   251 void WindowSurfaceImpl::deleteLocalSurface()
       
   252 {
       
   253     if(mMainSurface.localSurface != NULL)
       
   254     {
       
   255         delete mMainSurface.localSurface;
       
   256         mMainSurface.localSurface = NULL;
       
   257     }
       
   258     
       
   259 }
       
   260 
       
   261 bool WindowSurfaceImpl::isLocalSurfaceValid()
       
   262 {
       
   263     if(mMainSurface.localSurface == NULL)
       
   264     {
       
   265         return false;
       
   266     }
       
   267     
       
   268     if((mMainSurface.localSurfaceInUse) && 
       
   269        (mMainSurface.localSurface->width() == mMainSurface.widget->width()) && 
       
   270        (mMainSurface.localSurface->height() == mMainSurface.widget->height()))
       
   271     {
       
   272         return true;
       
   273     }
       
   274     return false;
       
   275 }
       
   276 
       
   277 void WindowSurfaceImpl::updateSurfaceData()
       
   278 {   
       
   279     // If painting is active, i.e. beginPaint has been called 
       
   280     // surface data is not updated
       
   281     if(mPaintingStarted)
       
   282     {
       
   283         return;
       
   284     }   
       
   285     QWindowSurface* surface = mMainSurface.widget->windowSurface();
       
   286     
       
   287     // If window surface is null it means that the widget has been 
       
   288     // sent to background and widget's window surface has been deleted, 
       
   289     // in such case create own QImage as local surface in order to support 
       
   290     // rendering in background
       
   291     if(surface == NULL || surface == 0)
       
   292     {
       
   293         // check if we already have local surface with valid size
       
   294         if(!isLocalSurfaceValid()) 
       
   295         {
       
   296             // incase we have invalid surface delete the current one
       
   297             // and create new
       
   298             if(mMainSurface.localSurfaceInUse) 
       
   299             {
       
   300                 deleteLocalSurface();
       
   301             }
       
   302             createLocalSurface(mMainSurface.widget->width(), mMainSurface.widget->height());
       
   303             // set info
       
   304             mMainSurface.qSurface = NULL;
       
   305             mMainSurface.device = mMainSurface.localSurface;
       
   306             mMainSurface.type = WsTypeQtImage;
       
   307             mMainSurface.localSurfaceInUse = true;
       
   308             return;
       
   309         }
       
   310         else 
       
   311         {
       
   312             // We have valid local surface so just return
       
   313             return;
       
   314         }
       
   315     }
       
   316     else 
       
   317     {
       
   318         // We got Qt's window surface, so in case we had local surface in use
       
   319         // delete it as it's not used anymore
       
   320         if(mMainSurface.localSurfaceInUse)
       
   321         {
       
   322             deleteLocalSurface();
       
   323         }
       
   324     }
       
   325     
       
   326     // We got window surface so extract information
       
   327     QPaintDevice* device = surface->paintDevice();
       
   328     if(device->paintingActive())
       
   329     {
       
   330         throw GfxException(EGfxErrorIllegalState, "Internal error: Device active when refreshing data");  
       
   331     }
       
   332     
       
   333     // Attach painter to device in oder to see which type 
       
   334     // of device it is working on
       
   335     mPainter.begin(device);
       
   336     QPaintEngine* engine = mPainter.paintEngine();
       
   337     
       
   338     // determine the surface type based on the engine used
       
   339     // as Qt does not provide exact info of the surface type
       
   340     switch (engine->type())
       
   341     {
       
   342         case QPaintEngine::OpenVG:
       
   343             // surface is EGL window surface
       
   344             mMainSurface.type = WsTypeEglSurface;
       
   345             break;
       
   346         case QPaintEngine::Raster:
       
   347             mMainSurface.type = WsTypeSymbianBitmap;
       
   348             if(device->devType() == QInternal::Pixmap)
       
   349             {
       
   350                 QPixmap* pixmap = static_cast<QPixmap*>(device);
       
   351                 mMainSurface.symbianBitmap = pixmap->toSymbianCFbsBitmap();
       
   352             }
       
   353             else 
       
   354             {
       
   355                 throw GfxException(EGfxErrorIllegalArgument, "Unsupported device type");
       
   356             }
       
   357             break;
       
   358         default:
       
   359             throw GfxException(EGfxErrorIllegalArgument, "Unsupported widget window surface type");
       
   360             break;
       
   361     }
       
   362     
       
   363     // release painter
       
   364     mPainter.end();
       
   365     mMainSurface.qSurface = surface;
       
   366     mMainSurface.device = device;
       
   367     mMainSurface.localSurfaceInUse = false;
       
   368 }
       
   369 
       
   370 
       
   371 } // namespace GFX
       
   372 } // namespace Java