diff -r dc7c549001d5 -r 85266cc22c7f javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/library/graphics/qt/windowsurfaceimpl_symbian.cpp --- /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 +#include +#include +#include +#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(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