Changeset 846 for trunk/src/opengl/qpixmapdata_x11gl_egl.cpp
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/opengl/qpixmapdata_x11gl_egl.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 201 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation ([email protected]) … … 42 42 #include <QDebug> 43 43 44 #include <private/qgl_p.h> 45 #include <private/qegl_p.h> 46 #include <private/qeglproperties_p.h> 47 48 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) 49 #include <private/qpaintengineex_opengl2_p.h> 44 #include <QtGui/private/qt_x11_p.h> 45 #include <QtGui/private/qegl_p.h> 46 #include <QtGui/private/qeglproperties_p.h> 47 #include <QtGui/private/qeglcontext_p.h> 48 49 #if !defined(QT_OPENGL_ES_1) 50 #include <QtOpenGL/private/qpaintengineex_opengl2_p.h> 50 51 #endif 51 52 52 53 #ifndef QT_OPENGL_ES_2 53 #include <private/qpaintengine_opengl_p.h> 54 #endif 54 #include <QtOpenGL/private/qpaintengine_opengl_p.h> 55 #endif 56 57 #include <QtOpenGL/private/qgl_p.h> 58 #include <QtOpenGL/private/qgl_egl_p.h> 55 59 56 60 #include "qpixmapdata_x11gl_p.h" … … 58 62 QT_BEGIN_NAMESPACE 59 63 60 extern EGLConfig qt_chooseEGLConfigForPixmap(bool hasAlpha, bool readOnly); // in qgl_x11egl.cpp 61 extern bool qt_createEGLSurfaceForPixmap(QPixmapData* pmd, bool readOnly); // in qgl_x11egl.cpp 62 63 // On 16bpp systems, RGB & ARGB pixmaps are different bit-depths and therefore need 64 // different contexts: 65 static EGLContext qPixmapARGBSharedEglContext = EGL_NO_CONTEXT; 66 static EGLContext qPixmapRGBSharedEglContext = EGL_NO_CONTEXT; 67 68 bool QX11GLPixmapData::hasX11GLPixmaps() 69 { 70 static bool checkedForX11Pixmaps = false; 71 static bool haveX11Pixmaps = false; 72 73 if (checkedForX11Pixmaps) 74 return haveX11Pixmaps; 75 76 checkedForX11Pixmaps = true; 77 78 QX11PixmapData *argbPixmapData = 0; 79 QX11PixmapData *rgbPixmapData = 0; 80 do { 81 if (qgetenv("QT_USE_X11GL_PIXMAPS").isEmpty()) 82 break; 83 84 // Check we actually have EGL configs which support pixmaps 85 EGLConfig argbConfig = qt_chooseEGLConfigForPixmap(true, false); 86 EGLConfig rgbConfig = qt_chooseEGLConfigForPixmap(false, false); 87 88 if (argbConfig == 0 || rgbConfig == 0) 89 break; 90 91 // Create the shared contexts: 92 eglBindAPI(EGL_OPENGL_ES_API); 93 EGLint contextAttribs[] = { 94 #if defined(QT_OPENGL_ES_2) 95 EGL_CONTEXT_CLIENT_VERSION, 2, 96 #endif 97 EGL_NONE 98 }; 99 qPixmapARGBSharedEglContext = eglCreateContext(QEglContext::display(), 100 argbConfig, 0, contextAttribs); 101 102 if (argbConfig == rgbConfig) { 103 // If the configs are the same, we can re-use the same context. 104 qPixmapRGBSharedEglContext = qPixmapARGBSharedEglContext; 105 } else { 106 qPixmapRGBSharedEglContext = eglCreateContext(QEglContext::display(), 107 rgbConfig, 0, contextAttribs); 108 } 109 110 argbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); 111 argbPixmapData->resize(100, 100); 112 argbPixmapData->fill(Qt::transparent); // Force ARGB 113 114 if (!qt_createEGLSurfaceForPixmap(argbPixmapData, false)) 115 break; 116 117 haveX11Pixmaps = eglMakeCurrent(QEglContext::display(), 118 (EGLSurface)argbPixmapData->gl_surface, 119 (EGLSurface)argbPixmapData->gl_surface, 120 qPixmapARGBSharedEglContext); 121 if (!haveX11Pixmaps) { 122 EGLint err = eglGetError(); 123 qWarning() << "Unable to make pixmap config current:" << err << QEglContext::errorString(err); 124 break; 125 } 126 127 // If the ARGB & RGB configs are the same, we don't need to check RGB too 128 if (haveX11Pixmaps && (argbConfig != rgbConfig)) { 129 rgbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); 130 rgbPixmapData->resize(100, 100); 64 65 class QX11GLSharedContexts 66 { 67 public: 68 QX11GLSharedContexts() 69 : rgbContext(0) 70 , argbContext(0) 71 , sharedQGLContext(0) 72 , sharePixmap(0) 73 { 74 EGLint rgbConfigId; 75 EGLint argbConfigId; 76 77 do { 78 EGLConfig rgbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, QEgl::Renderable); 79 EGLConfig argbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, 80 QEgl::Renderable | QEgl::Translucent); 81 82 eglGetConfigAttrib(QEgl::display(), rgbConfig, EGL_CONFIG_ID, &rgbConfigId); 83 eglGetConfigAttrib(QEgl::display(), argbConfig, EGL_CONFIG_ID, &argbConfigId); 84 85 rgbContext = new QEglContext; 86 rgbContext->setConfig(rgbConfig); 87 rgbContext->createContext(); 88 89 if (!rgbContext->isValid()) 90 break; 91 92 // If the RGB & ARGB configs are the same, use the same egl context for both: 93 if (rgbConfig == argbConfig) 94 argbContext = rgbContext; 95 96 // Otherwise, create a separate context to be used for ARGB pixmaps: 97 if (!argbContext) { 98 argbContext = new QEglContext; 99 argbContext->setConfig(argbConfig); 100 bool success = argbContext->createContext(rgbContext); 101 if (!success) { 102 qWarning("QX11GLPixmapData - RGB & ARGB contexts aren't shared"); 103 success = argbContext->createContext(); 104 if (!success) 105 argbContext = rgbContext; // Might work, worth a shot at least. 106 } 107 } 108 109 if (!argbContext->isValid()) 110 break; 111 112 // Create the pixmap which will be used to create the egl surface for the share QGLContext 113 QX11PixmapData *rgbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); 114 rgbPixmapData->resize(8, 8); 131 115 rgbPixmapData->fill(Qt::red); 132 133 // Try to actually create an EGL pixmap surface 134 if (!qt_createEGLSurfaceForPixmap(rgbPixmapData, false)) 135 break; 136 137 haveX11Pixmaps = eglMakeCurrent(QEglContext::display(), 138 (EGLSurface)rgbPixmapData->gl_surface, 139 (EGLSurface)rgbPixmapData->gl_surface, 140 qPixmapRGBSharedEglContext); 141 if (!haveX11Pixmaps) { 142 EGLint err = eglGetError(); 143 qWarning() << "Unable to make pixmap config current:" << err << QEglContext::errorString(err); 116 sharePixmap = new QPixmap(rgbPixmapData); 117 EGLSurface sharePixmapSurface = QEgl::createSurface(sharePixmap, rgbConfig); 118 rgbPixmapData->gl_surface = (void*)sharePixmapSurface; 119 120 // Create the actual QGLContext which will be used for sharing 121 sharedQGLContext = new QGLContext(QX11GLPixmapData::glFormat()); 122 sharedQGLContext->d_func()->eglContext = rgbContext; 123 sharedQGLContext->d_func()->eglSurface = sharePixmapSurface; 124 sharedQGLContext->d_func()->valid = true; 125 qt_glformat_from_eglconfig(sharedQGLContext->d_func()->glFormat, rgbConfig); 126 127 128 valid = rgbContext->makeCurrent(sharePixmapSurface); 129 130 // If the ARGB & RGB configs are different, check ARGB works too: 131 if (argbConfig != rgbConfig) { 132 QX11PixmapData *argbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); 133 argbPixmapData->resize(8, 8); 134 argbPixmapData->fill(Qt::transparent); // Force ARGB 135 QPixmap argbPixmap(argbPixmapData); // destroys pixmap data when goes out of scope 136 EGLSurface argbPixmapSurface = QEgl::createSurface(&argbPixmap, argbConfig); 137 valid = argbContext->makeCurrent(argbPixmapSurface); 138 argbContext->doneCurrent(); 139 eglDestroySurface(QEgl::display(), argbPixmapSurface); 140 argbPixmapData->gl_surface = 0; 141 } 142 143 if (!valid) { 144 qWarning() << "Unable to make pixmap surface current:" << QEgl::errorString(); 144 145 break; 145 146 } 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 146 168 } 147 } while (0); 148 149 if (qPixmapARGBSharedEglContext || qPixmapRGBSharedEglContext) { 150 eglMakeCurrent(QEglContext::display(), 151 EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 152 } 153 154 if (argbPixmapData) { 155 if (argbPixmapData->gl_surface) 156 QGLContextPrivate::destroyGlSurfaceForPixmap(argbPixmapData); 157 delete argbPixmapData; 158 argbPixmapData = 0; 159 } 160 if (rgbPixmapData) { 161 if (rgbPixmapData->gl_surface) 162 QGLContextPrivate::destroyGlSurfaceForPixmap(rgbPixmapData); 163 delete rgbPixmapData; 164 rgbPixmapData = 0; 165 } 166 167 if (!haveX11Pixmaps) { 168 // Clean up the context(s) if we can't use X11GL pixmaps 169 if (qPixmapARGBSharedEglContext != EGL_NO_CONTEXT) 170 eglDestroyContext(QEglContext::display(), qPixmapARGBSharedEglContext); 171 172 if (qPixmapRGBSharedEglContext != qPixmapARGBSharedEglContext && 173 qPixmapRGBSharedEglContext != EGL_NO_CONTEXT) 174 { 175 eglDestroyContext(QEglContext::display(), qPixmapRGBSharedEglContext); 169 if (argbContext && argbContext != rgbContext) 170 delete argbContext; 171 argbContext = 0; 172 173 if (rgbContext) { 174 delete rgbContext; 175 rgbContext = 0; 176 176 } 177 qPixmapRGBSharedEglContext = EGL_NO_CONTEXT; 178 qPixmapARGBSharedEglContext = EGL_NO_CONTEXT; 179 } 180 181 if (haveX11Pixmaps) 182 qDebug("QX11GLPixmapData is supported"); 183 else 184 qDebug("QX11GLPixmapData is *NOT* being used"); 185 186 return haveX11Pixmaps; 177 178 // Deleting the QPixmap will fire the pixmap destruction cleanup hooks which in turn 179 // will destroy the egl surface: 180 if (sharePixmap) { 181 delete sharePixmap; 182 sharePixmap = 0; 183 } 184 } 185 186 bool isValid() { return valid;} 187 188 // On 16bpp systems, RGB & ARGB pixmaps are different bit-depths and therefore need 189 // different contexts: 190 QEglContext *rgbContext; 191 QEglContext *argbContext; 192 193 // The share context wraps the rgbContext and is used as the master of the context share 194 // group. As all other contexts will have the same egl context (or a shared one if rgb != argb) 195 // all QGLContexts will actually be sharing and can be in the same context group. 196 QGLContext *sharedQGLContext; 197 private: 198 QPixmap *sharePixmap; 199 bool valid; 200 }; 201 202 static void qt_cleanup_x11gl_share_contexts(); 203 204 Q_GLOBAL_STATIC_WITH_INITIALIZER(QX11GLSharedContexts, qt_x11gl_share_contexts, 205 { 206 qAddPostRoutine(qt_cleanup_x11gl_share_contexts); 207 }) 208 209 static void qt_cleanup_x11gl_share_contexts() 210 { 211 qt_x11gl_share_contexts()->cleanup(); 212 } 213 214 215 QX11GLSharedContexts* QX11GLPixmapData::sharedContexts() 216 { 217 return qt_x11gl_share_contexts(); 218 } 219 220 bool QX11GLPixmapData::hasX11GLPixmaps() 221 { 222 static bool checkedForX11GLPixmaps = false; 223 static bool haveX11GLPixmaps = false; 224 225 if (checkedForX11GLPixmaps) 226 return haveX11GLPixmaps; 227 228 haveX11GLPixmaps = qt_x11gl_share_contexts()->isValid(); 229 checkedForX11GLPixmaps = true; 230 231 return haveX11GLPixmaps; 187 232 } 188 233 … … 195 240 QX11GLPixmapData::~QX11GLPixmapData() 196 241 { 197 } 198 199 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) 242 if (ctx) 243 delete ctx; 244 } 245 246 247 void QX11GLPixmapData::fill(const QColor &color) 248 { 249 if (ctx) { 250 ctx->makeCurrent(); 251 glFinish(); 252 eglWaitClient(); 253 } 254 255 QX11PixmapData::fill(color); 256 XSync(X11->display, False); 257 258 if (ctx) { 259 ctx->makeCurrent(); 260 eglWaitNative(EGL_CORE_NATIVE_ENGINE); 261 } 262 } 263 264 void QX11GLPixmapData::copy(const QPixmapData *data, const QRect &rect) 265 { 266 if (ctx) { 267 ctx->makeCurrent(); 268 glFinish(); 269 eglWaitClient(); 270 } 271 272 QX11PixmapData::copy(data, rect); 273 XSync(X11->display, False); 274 275 if (ctx) { 276 ctx->makeCurrent(); 277 eglWaitNative(EGL_CORE_NATIVE_ENGINE); 278 } 279 } 280 281 bool QX11GLPixmapData::scroll(int dx, int dy, const QRect &rect) 282 { 283 if (ctx) { 284 ctx->makeCurrent(); 285 glFinish(); 286 eglWaitClient(); 287 } 288 289 bool success = QX11PixmapData::scroll(dx, dy, rect); 290 XSync(X11->display, False); 291 292 if (ctx) { 293 ctx->makeCurrent(); 294 eglWaitNative(EGL_CORE_NATIVE_ENGINE); 295 } 296 297 return success; 298 } 299 300 #if !defined(QT_OPENGL_ES_1) 200 301 Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_pixmap_2_engine) 201 302 #endif … … 211 312 if (!ctx) { 212 313 ctx = new QGLContext(glFormat()); 213 if (ctx->d_func()->eglContext == 0) 214 ctx->d_func()->eglContext = new QEglContext(); 215 ctx->d_func()->eglContext->setApi(QEgl::OpenGL); 216 ctx->d_func()->eglContext->setContext(hasAlphaChannel() ? qPixmapARGBSharedEglContext 217 : qPixmapRGBSharedEglContext); 314 Q_ASSERT(ctx->d_func()->eglContext == 0); 315 ctx->d_func()->eglContext = hasAlphaChannel() ? sharedContexts()->argbContext : sharedContexts()->rgbContext; 316 317 // While we use a separate QGLContext for each pixmap, the underlying QEglContext is 318 // the same. So we must use a "fake" QGLContext and fool the texture cache into thinking 319 // each pixmap's QGLContext is sharing with this central one. The only place this is 320 // going to fail is where we the underlying EGL RGB and ARGB contexts aren't sharing. 321 ctx->d_func()->sharing = true; 322 QGLContextGroup::addShare(ctx, sharedContexts()->sharedQGLContext); 323 324 // Update the glFormat for the QGLContext: 325 qt_glformat_from_eglconfig(ctx->d_func()->glFormat, ctx->d_func()->eglContext->config()); 218 326 } 219 327 220 328 QPaintEngine* engine; 221 329 222 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)330 #if defined(QT_OPENGL_ES_1) 223 331 engine = qt_gl_pixmap_engine(); 224 332 #elif defined(QT_OPENGL_ES_2) … … 237 345 qWarning("Pixmap paint engine already active"); 238 346 239 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)347 #if defined(QT_OPENGL_ES_1) 240 348 engine = new QOpenGLPaintEngine; 241 349 #elif defined(QT_OPENGL_ES_2) … … 258 366 { 259 367 // qDebug("QX11GLPixmapData::beginPaint()"); 368 260 369 if ((EGLSurface)gl_surface == EGL_NO_SURFACE) { 261 qt_createEGLSurfaceForPixmap(this, false); 262 ctx->d_func()->eglSurface = (EGLSurface)gl_surface; 263 ctx->d_func()->valid = true; // ;-) 370 QPixmap tmpPixmap(this); 371 EGLConfig cfg = ctx->d_func()->eglContext->config(); 372 Q_ASSERT(cfg != QEGL_NO_CONFIG); 373 374 // qDebug("QX11GLPixmapData - using EGL Config ID %d", ctx->d_func()->eglContext->configAttrib(EGL_CONFIG_ID)); 375 EGLSurface surface = QEgl::createSurface(&tmpPixmap, cfg); 376 if (surface == EGL_NO_SURFACE) { 377 qWarning() << "Error creating EGL surface for pixmap:" << QEgl::errorString(); 378 return; 379 } 380 gl_surface = (void*)surface; 381 ctx->d_func()->eglSurface = surface; 382 ctx->d_func()->valid = true; 264 383 } 265 384 QGLPaintDevice::beginPaint(); 266 385 } 267 386 268 void QX11GLPixmapData::endPaint()269 {270 glFinish();271 QGLPaintDevice::endPaint();272 }273 274 387 QGLContext* QX11GLPixmapData::context() const 275 388 {
Note:
See TracChangeset
for help on using the changeset viewer.