javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/library/graphics/qt/windowsurfaceimpl_symbian.cpp
changeset 35 85266cc22c7f
child 48 e0d6e9bd3ca7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/library/graphics/qt/windowsurfaceimpl_symbian.cpp	Fri Jun 11 13:33:44 2010 +0300
@@ -0,0 +1,372 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Nokia Corporation - initial API and implementation
+ *******************************************************************************/
+
+//#include <QtOpenGL>
+#include <QWidget>
+#include <QPainter>
+#include <QPaintEngine>
+#include "windowsurfaceimpl_symbian.h"
+#include "gfxlog.h"
+
+namespace Java { namespace GFX {
+
+WindowSurfaceImpl::WindowSurfaceImpl(QPaintDevice* aSurface, WindowSurfaceType aType)
+: mIsBound(false),
+  mBufferedRendering(false),
+  mAutoRefresh(false),
+  mPaintingStarted(false)
+{
+    GFX_LOG_FUNC_CALL();
+    mMainSurface.device = aSurface;
+    mMainSurface.type = aType;
+}
+
+WindowSurfaceImpl::WindowSurfaceImpl(QWidget* aWidget, bool aAutoRefresh)
+: mIsBound(false),
+  mBufferedRendering(false),
+  mAutoRefresh(false),
+  mPaintingStarted(false)
+{
+    GFX_LOG_FUNC_CALL();
+    if(aWidget == NULL) 
+    {
+        throw GfxException(EGfxErrorIllegalArgument, "Target widget is NULL");
+    }
+    mMainSurface.widget = aWidget;
+    mAutoRefresh = aAutoRefresh;
+    updateSurfaceData();   
+}
+
+
+WindowSurfaceImpl::~WindowSurfaceImpl()
+{
+    GFX_LOG_FUNC_CALL();
+    if(mMainSurface.localSurface != NULL)
+    {
+        delete mMainSurface.localSurface;
+        mMainSurface.localSurface = NULL;
+    }
+}
+
+void WindowSurfaceImpl::beginPaint(int aX, int aY, int aWidth, int aHeight)
+{
+    if(mAutoRefresh && (mMainSurface.widget != NULL)) 
+    {
+        updateSurfaceData();
+    }
+    if(!mMainSurface.localSurfaceInUse)
+    {
+        QRegion region(aX, aY, aWidth, aHeight);
+        mMainSurface.qSurface->beginPaint(region);
+        // In case local surface was used last round
+        // and we now have Qt's window surface again
+        // delete the local surface to save memory
+        if(mMainSurface.localSurface != NULL)
+        {
+            delete mMainSurface.localSurface;
+            mMainSurface.localSurface = NULL;
+        }
+    }
+    mPaintingStarted = true;
+}
+
+void WindowSurfaceImpl::endPaint()
+{
+    if(!mMainSurface.localSurfaceInUse)
+    {
+        mMainSurface.qSurface->endPaint(QRegion());
+    }
+    mPaintingStarted = false;
+}
+
+void WindowSurfaceImpl::flush()
+{
+    if(!mMainSurface.localSurfaceInUse)
+    { 
+        QRegion region(0,0,mMainSurface.device->width(), mMainSurface.device->height());  
+        mMainSurface.qSurface->flush(mMainSurface.widget, region, QPoint());
+    }
+}
+
+void WindowSurfaceImpl::bind(int aCapabilies)
+{
+    GFX_LOG_FUNC_CALL();
+    // Bind is not allowed if beginPaint has not been called
+    if(!mPaintingStarted)
+    {
+        throw GfxException(EGfxErrorIllegalState, "beginPaint() not called before bind()");
+    }
+    
+    switch (mMainSurface.type)
+    {
+        case WsTypeQtImage:
+        {
+            mBufferedRendering = true;
+            break;
+        }
+        
+        case WsTypeEglSurface:
+        {
+            // If caller does not support EGL surface
+            // create temp buffer to be used as target and
+            // copy pixels from window surface to temp buffer
+            if ((aCapabilies & WsTypeEglSurface) == 0) {
+                // TODO copy pixels from EGL surface to 
+                // QImage created here
+                
+            } else {
+                // Caller supports EGL surface, so just 
+                // save EGL state here
+                saveEglState();
+            }
+            break;
+        }
+        case WsTypeSymbianBitmap:
+        {
+            break;
+        }
+        default:
+        {
+            // we should newer get here
+        }
+    }
+    mIsBound = true;
+}
+
+int WindowSurfaceImpl::getType()
+{
+    GFX_LOG_FUNC_CALL();
+    return mMainSurface.type;
+}
+
+QPaintDevice* WindowSurfaceImpl::getDevice()
+{
+    return mMainSurface.device;
+}
+
+
+EGLSurface WindowSurfaceImpl::getEglSurface()
+{
+    return mEgl.drawSurface;
+}
+
+EGLenum WindowSurfaceImpl::getEglApi()
+{
+    return mEgl.api;
+}
+
+CFbsBitmap* WindowSurfaceImpl::getSymbianBitmap()
+{
+    return mMainSurface.symbianBitmap;
+}
+
+QImage* WindowSurfaceImpl::getQtImage()
+{
+    return mMainSurface.localSurface;
+}
+
+void WindowSurfaceImpl::refresh()
+{
+    updateSurfaceData();
+}
+
+void WindowSurfaceImpl::release()
+{
+    GFX_LOG_FUNC_CALL();
+    if (!mIsBound)
+    {
+        return;
+    }
+
+    if (mBufferedRendering)
+    {
+        // TODO draw QImage with painter to actual target
+    }
+    else
+    {
+        if(mMainSurface.type == WsTypeEglSurface)
+        {
+            restoreEglState();
+        }
+        // pixels are already rendered to the target
+        // no post blitter hook needed
+    }
+    mIsBound = false;
+}
+
+void WindowSurfaceImpl::dispose()
+{
+    GFX_LOG_FUNC_CALL();
+    delete this;
+}
+
+void WindowSurfaceImpl::saveEglState()
+{
+    // Some painter needs to be active on the device
+    // in order to get correct data from EGL, so if 
+    // there's no active painter, activate one here
+    if(!mMainSurface.device->paintingActive())
+    {
+        mPainter.begin(mMainSurface.device);
+    }
+    mEgl.drawSurface = eglGetCurrentSurface(EGL_DRAW);
+    mEgl.readSurface = eglGetCurrentSurface(EGL_READ);
+    mEgl.display = eglGetCurrentDisplay();
+    mEgl.context = eglGetCurrentContext();
+    mEgl.api = eglQueryAPI();
+}
+    
+void WindowSurfaceImpl::restoreEglState()
+{
+    eglBindAPI(mEgl.api);
+    eglMakeCurrent(mEgl.display, mEgl.drawSurface, mEgl.readSurface, mEgl.context);
+    
+    // if owned painter was activate to the device 
+    // release it
+    if(mPainter.isActive())
+    {
+        mPainter.end();
+    }
+}
+
+// Private methods
+
+void WindowSurfaceImpl::createLocalSurface(int aWidth, int aHeight)
+{
+    mMainSurface.localSurface = new QImage(aWidth, aHeight, QImage::Format_ARGB32);
+    if(mMainSurface.localSurface->isNull()) 
+    {   
+        throw GfxException(EGfxErrorNoMemory, "Local Surface creation failed");
+    }   
+}
+
+void WindowSurfaceImpl::deleteLocalSurface()
+{
+    if(mMainSurface.localSurface != NULL)
+    {
+        delete mMainSurface.localSurface;
+        mMainSurface.localSurface = NULL;
+    }
+    
+}
+
+bool WindowSurfaceImpl::isLocalSurfaceValid()
+{
+    if(mMainSurface.localSurface == NULL)
+    {
+        return false;
+    }
+    
+    if((mMainSurface.localSurfaceInUse) && 
+       (mMainSurface.localSurface->width() == mMainSurface.widget->width()) && 
+       (mMainSurface.localSurface->height() == mMainSurface.widget->height()))
+    {
+        return true;
+    }
+    return false;
+}
+
+void WindowSurfaceImpl::updateSurfaceData()
+{   
+    // If painting is active, i.e. beginPaint has been called 
+    // surface data is not updated
+    if(mPaintingStarted)
+    {
+        return;
+    }   
+    QWindowSurface* surface = mMainSurface.widget->windowSurface();
+    
+    // If window surface is null it means that the widget has been 
+    // sent to background and widget's window surface has been deleted, 
+    // in such case create own QImage as local surface in order to support 
+    // rendering in background
+    if(surface == NULL || surface == 0)
+    {
+        // check if we already have local surface with valid size
+        if(!isLocalSurfaceValid()) 
+        {
+            // incase we have invalid surface delete the current one
+            // and create new
+            if(mMainSurface.localSurfaceInUse) 
+            {
+                deleteLocalSurface();
+            }
+            createLocalSurface(mMainSurface.widget->width(), mMainSurface.widget->height());
+            // set info
+            mMainSurface.qSurface = NULL;
+            mMainSurface.device = mMainSurface.localSurface;
+            mMainSurface.type = WsTypeQtImage;
+            mMainSurface.localSurfaceInUse = true;
+            return;
+        }
+        else 
+        {
+            // We have valid local surface so just return
+            return;
+        }
+    }
+    else 
+    {
+        // We got Qt's window surface, so in case we had local surface in use
+        // delete it as it's not used anymore
+        if(mMainSurface.localSurfaceInUse)
+        {
+            deleteLocalSurface();
+        }
+    }
+    
+    // We got window surface so extract information
+    QPaintDevice* device = surface->paintDevice();
+    if(device->paintingActive())
+    {
+        throw GfxException(EGfxErrorIllegalState, "Internal error: Device active when refreshing data");  
+    }
+    
+    // Attach painter to device in oder to see which type 
+    // of device it is working on
+    mPainter.begin(device);
+    QPaintEngine* engine = mPainter.paintEngine();
+    
+    // determine the surface type based on the engine used
+    // as Qt does not provide exact info of the surface type
+    switch (engine->type())
+    {
+        case QPaintEngine::OpenVG:
+            // surface is EGL window surface
+            mMainSurface.type = WsTypeEglSurface;
+            break;
+        case QPaintEngine::Raster:
+            mMainSurface.type = WsTypeSymbianBitmap;
+            if(device->devType() == QInternal::Pixmap)
+            {
+                QPixmap* pixmap = static_cast<QPixmap*>(device);
+                mMainSurface.symbianBitmap = pixmap->toSymbianCFbsBitmap();
+            }
+            else 
+            {
+                throw GfxException(EGfxErrorIllegalArgument, "Unsupported device type");
+            }
+            break;
+        default:
+            throw GfxException(EGfxErrorIllegalArgument, "Unsupported widget window surface type");
+            break;
+    }
+    
+    // release painter
+    mPainter.end();
+    mMainSurface.qSurface = surface;
+    mMainSurface.device = device;
+    mMainSurface.localSurfaceInUse = false;
+}
+
+
+} // namespace GFX
+} // namespace Java