src/opengl/qgl_symbian.cpp
changeset 37 758a864f9613
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include "qgl.h"
       
    44 #include <coemain.h>
       
    45 #include <coecntrl.h>
       
    46 #include <w32std.h>
       
    47 #include <private/qpixmap_s60_p.h>
       
    48 #include <private/qimagepixmapcleanuphooks_p.h>
       
    49 #include <private/qgl_p.h>
       
    50 #include <private/qpaintengine_opengl_p.h>
       
    51 #include <private/qwidget_p.h> // to access QWExtra
       
    52 #include "qgl_egl_p.h"
       
    53 #include "qcolormap.h"
       
    54 #include <QDebug>
       
    55 
       
    56 QT_BEGIN_NAMESPACE
       
    57 
       
    58 // Turn off "direct to window" rendering if EGL cannot support it.
       
    59 #if !defined(EGL_RENDER_BUFFER) || !defined(EGL_SINGLE_BUFFER)
       
    60 #if defined(QGL_DIRECT_TO_WINDOW)
       
    61 #undef QGL_DIRECT_TO_WINDOW
       
    62 #endif
       
    63 #endif
       
    64 
       
    65 // Determine if preserved window contents should be used.
       
    66 #if !defined(EGL_SWAP_BEHAVIOR) || !defined(EGL_BUFFER_PRESERVED)
       
    67 #if !defined(QGL_NO_PRESERVED_SWAP)
       
    68 #define QGL_NO_PRESERVED_SWAP 1
       
    69 #endif
       
    70 #endif
       
    71 
       
    72 /*
       
    73     QGLTemporaryContext implementation
       
    74 */
       
    75 
       
    76 
       
    77 class QGLTemporaryContextPrivate
       
    78 {
       
    79 public:
       
    80     bool initialized;
       
    81     RWindow *window;
       
    82     EGLContext context;
       
    83     EGLSurface surface;
       
    84     EGLDisplay display;
       
    85 };
       
    86 
       
    87 QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
       
    88     : d(new QGLTemporaryContextPrivate)
       
    89 {
       
    90     d->initialized = false;
       
    91     d->window = 0;
       
    92     d->context = 0;
       
    93     d->surface = 0;
       
    94 
       
    95     d->display = d->display = QEgl::display();
       
    96 
       
    97     EGLConfig config;
       
    98     int numConfigs = 0;
       
    99     EGLint attribs[] = {
       
   100         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
       
   101 #ifdef QT_OPENGL_ES_2
       
   102         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
       
   103 #endif
       
   104         EGL_NONE
       
   105     };
       
   106 
       
   107     eglChooseConfig(d->display, attribs, &config, 1, &numConfigs);
       
   108     if (!numConfigs) {
       
   109         qWarning("QGLTemporaryContext: No EGL configurations available.");
       
   110         return;
       
   111     }
       
   112 
       
   113     d->window = new RWindow(CCoeEnv::Static()->WsSession());
       
   114     d->window->Construct(CCoeEnv::Static()->RootWin(),(uint)this);
       
   115 
       
   116     d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL);
       
   117 
       
   118     if (d->surface == EGL_NO_SURFACE) {
       
   119         qWarning("QGLTemporaryContext: Error creating EGL surface.");
       
   120         delete d->window;
       
   121         d->window = 0;
       
   122         return;
       
   123     }
       
   124 
       
   125     EGLint contextAttribs[] = {
       
   126 #ifdef QT_OPENGL_ES_2
       
   127         EGL_CONTEXT_CLIENT_VERSION, 2,
       
   128 #endif
       
   129         EGL_NONE
       
   130     };
       
   131     d->context = eglCreateContext(d->display, config, 0, contextAttribs);
       
   132     if (d->context != EGL_NO_CONTEXT
       
   133         && eglMakeCurrent(d->display, d->surface, d->surface, d->context))
       
   134     {
       
   135         d->initialized = true;
       
   136     } else {
       
   137         qWarning("QGLTemporaryContext: Error creating EGL context.");
       
   138         d->window = 0;
       
   139         return;
       
   140     }
       
   141 }
       
   142 
       
   143 QGLTemporaryContext::~QGLTemporaryContext()
       
   144 {
       
   145     if (d->initialized) {
       
   146         eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
       
   147         eglDestroyContext(d->display, d->context);
       
   148         eglDestroySurface(d->display, d->surface);
       
   149         delete d->window;
       
   150     }
       
   151 }
       
   152 
       
   153 bool QGLFormat::hasOpenGLOverlays()
       
   154 {
       
   155     return false;
       
   156 }
       
   157 
       
   158 // Chooses the EGL config and creates the EGL context
       
   159 bool QGLContext::chooseContext(const QGLContext* shareContext) // almost same as in qgl_x11egl.cpp
       
   160 {
       
   161     Q_D(QGLContext);
       
   162 
       
   163     if (!device())
       
   164         return false;
       
   165 
       
   166     int devType = device()->devType();
       
   167 
       
   168     if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
       
   169         qWarning("WARNING: Creating a QGLContext not supported on device type %d", devType);
       
   170         return false;
       
   171     }
       
   172 
       
   173     // Get the display and initialize it.
       
   174     if (d->eglContext == 0) {
       
   175         d->eglContext = new QEglContext();
       
   176         d->ownsEglContext = true;
       
   177         d->eglContext->setApi(QEgl::OpenGL);
       
   178 
       
   179 	    // If the device is a widget with WA_TranslucentBackground set, make sure the glFormat
       
   180         // has the alpha channel option set:
       
   181         if (devType == QInternal::Widget) {
       
   182             QWidget* widget = static_cast<QWidget*>(device());
       
   183             if (widget->testAttribute(Qt::WA_TranslucentBackground))
       
   184                 d->glFormat.setAlpha(true);
       
   185         }
       
   186 
       
   187         // Construct the configuration we need for this surface.
       
   188         QEglProperties configProps;
       
   189         configProps.setDeviceType(devType);
       
   190         configProps.setPaintDeviceFormat(device());
       
   191         configProps.setRenderableType(QEgl::OpenGL);
       
   192         configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_SWAP_BEHAVIOR_PRESERVED_BIT);
       
   193 
       
   194         qt_eglproperties_set_glformat(configProps, d->glFormat);
       
   195 
       
   196         if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
       
   197             delete d->eglContext;
       
   198             d->eglContext = 0;
       
   199             return false;
       
   200         }
       
   201 
       
   202         // Create a new context for the configuration.
       
   203         QEglContext* eglSharedContext = shareContext ? shareContext->d_func()->eglContext : 0;
       
   204         if (!d->eglContext->createContext(eglSharedContext)) {
       
   205             delete d->eglContext;
       
   206             d->eglContext = 0;
       
   207             return false;
       
   208         }
       
   209         d->sharing = d->eglContext->isSharing();
       
   210         if (d->sharing && shareContext)
       
   211             const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
       
   212 	}
       
   213 
       
   214     // Inform the higher layers about the actual format properties
       
   215     qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config());
       
   216 
       
   217     // Do don't create the EGLSurface for everything.
       
   218     //    QWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
       
   219     //    QGLWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
       
   220     //    QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf
       
   221 
       
   222     if (devType == QInternal::Widget) {
       
   223         if (d->eglSurface != EGL_NO_SURFACE)
       
   224             eglDestroySurface(d->eglContext->display(), d->eglSurface);
       
   225 
       
   226         d->eglSurface = QEgl::createSurface(device(), d->eglContext->config());
       
   227 
       
   228 #if !defined(QGL_NO_PRESERVED_SWAP)
       
   229         eglGetError();  // Clear error state first.
       
   230         eglSurfaceAttrib(QEgl::display(), d->eglSurface,
       
   231                 EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
       
   232         if (eglGetError() != EGL_SUCCESS) {
       
   233             qWarning("QGLContext: could not enable preserved swap");
       
   234         }
       
   235 #endif
       
   236 
       
   237         setWindowCreated(true);
       
   238     }
       
   239 
       
   240     return true;
       
   241 }
       
   242 
       
   243 void QGLWidget::resizeEvent(QResizeEvent *)
       
   244 {
       
   245     Q_D(QGLWidget);
       
   246     if (!isValid())
       
   247         return;
       
   248 
       
   249     if (QGLContext::currentContext())
       
   250         doneCurrent();
       
   251 
       
   252     // Symbian needs to recreate the surface on resize.
       
   253     d->recreateEglSurface();
       
   254 
       
   255     makeCurrent();
       
   256     if (!d->glcx->initialized())
       
   257         glInit();
       
   258     resizeGL(width(), height());
       
   259     //handle overlay
       
   260 }
       
   261 
       
   262 const QGLContext* QGLWidget::overlayContext() const
       
   263 {
       
   264     return 0;
       
   265 }
       
   266 
       
   267 void QGLWidget::makeOverlayCurrent()
       
   268 {
       
   269     //handle overlay
       
   270 }
       
   271 
       
   272 void QGLWidget::updateOverlayGL()
       
   273 {
       
   274     //handle overlay
       
   275 }
       
   276 
       
   277 void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
       
   278 {
       
   279     Q_D(QGLWidget);
       
   280     if (context == 0) {
       
   281         qWarning("QGLWidget::setContext: Cannot set null context");
       
   282         return;
       
   283     }
       
   284     if (!context->deviceIsPixmap() && context->device() != this) {
       
   285         qWarning("QGLWidget::setContext: Context must refer to this widget");
       
   286         return;
       
   287     }
       
   288 
       
   289     if (d->glcx)
       
   290         d->glcx->doneCurrent();
       
   291     QGLContext* oldcx = d->glcx;
       
   292     d->glcx = context;
       
   293 
       
   294     bool createFailed = false;
       
   295     if (!d->glcx->isValid()) {
       
   296         // Create the QGLContext here, which in turn chooses the EGL config
       
   297         // and creates the EGL context:
       
   298         if (!d->glcx->create(shareContext ? shareContext : oldcx))
       
   299             createFailed = true;
       
   300     }
       
   301     if (createFailed) {
       
   302         if (deleteOldContext)
       
   303             delete oldcx;
       
   304         return;
       
   305     }
       
   306 
       
   307     d->eglSurfaceWindowId = winId(); // Remember the window id we created the surface for
       
   308 }
       
   309 
       
   310 void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget* shareWidget)
       
   311 {
       
   312     Q_Q(QGLWidget);
       
   313 
       
   314     initContext(context, shareWidget);
       
   315 
       
   316     if(q->isValid() && glcx->format().hasOverlay()) {
       
   317         //no overlay
       
   318         qWarning("QtOpenGL ES doesn't currently support overlays");
       
   319     }
       
   320 }
       
   321 
       
   322 void QGLWidgetPrivate::cleanupColormaps()
       
   323 {
       
   324 }
       
   325 
       
   326 const QGLColormap & QGLWidget::colormap() const
       
   327 {
       
   328     return d_func()->cmap;
       
   329 }
       
   330 
       
   331 void QGLWidget::setColormap(const QGLColormap &)
       
   332 {
       
   333 }
       
   334 
       
   335 void QGLWidgetPrivate::recreateEglSurface()
       
   336 {
       
   337     Q_Q(QGLWidget);
       
   338 
       
   339     WId currentId = q->winId();
       
   340 
       
   341     if (glcx->d_func()->eglSurface != EGL_NO_SURFACE) {
       
   342         eglDestroySurface(glcx->d_func()->eglContext->display(),
       
   343                                                 glcx->d_func()->eglSurface);
       
   344     }
       
   345 
       
   346     glcx->d_func()->eglSurface = QEgl::createSurface(glcx->device(),
       
   347                                        glcx->d_func()->eglContext->config());
       
   348 
       
   349 #if !defined(QGL_NO_PRESERVED_SWAP)
       
   350         eglGetError();  // Clear error state first.
       
   351         eglSurfaceAttrib(QEgl::display(), glcx->d_func()->eglSurface,
       
   352                                     EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
       
   353         if (eglGetError() != EGL_SUCCESS) {
       
   354             qWarning("QGLContext: could not enable preserved swap");
       
   355         }
       
   356 #endif
       
   357 
       
   358     eglSurfaceWindowId = currentId;
       
   359 }
       
   360 
       
   361 QT_END_NAMESPACE
       
   362