Changeset 561 for trunk/src/opengl/qgl_x11egl.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/opengl/qgl_x11egl.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtOpenGL module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 42 42 #include "qgl.h" 43 43 #include <private/qt_x11_p.h> 44 #include <private/qpixmap_x11_p.h> 45 #include <private/qimagepixmapcleanuphooks_p.h> 44 46 #include <private/qgl_p.h> 45 47 #include <private/qpaintengine_opengl_p.h> 46 48 #include "qgl_egl_p.h" 47 49 #include "qcolormap.h" 50 #include <QDebug> 48 51 49 52 50 53 QT_BEGIN_NAMESPACE 51 52 53 bool QGLFormat::hasOpenGL()54 {55 return true;56 }57 54 58 55 bool QGLFormat::hasOpenGLOverlays() … … 67 64 } 68 65 66 // Chooses the EGL config and creates the EGL context 69 67 bool QGLContext::chooseContext(const QGLContext* shareContext) 70 68 { … … 77 75 78 76 // Get the display and initialize it. 79 d->eglContext = new QEglContext(); 80 d->eglContext->setApi(QEglContext::OpenGL); 81 if (!d->eglContext->openDisplay(device())) { 82 delete d->eglContext; 83 d->eglContext = 0; 84 return false; 85 } 86 87 // Construct the configuration we need for this surface. 88 QEglProperties configProps; 89 qt_egl_set_format(configProps, devType, d->glFormat); 90 qt_egl_add_platform_config(configProps, device()); 91 configProps.setRenderableType(QEglContext::OpenGL); 92 93 // Search for a matching configuration, reducing the complexity 94 // each time until we get something that matches. 95 if (!d->eglContext->chooseConfig(configProps, QEglContext::BestPixelFormat)) { 96 delete d->eglContext; 97 d->eglContext = 0; 98 return false; 77 if (d->eglContext == 0) { 78 d->eglContext = new QEglContext(); 79 d->eglContext->setApi(QEgl::OpenGL); 80 if (!d->eglContext->openDisplay(device())) { 81 delete d->eglContext; 82 d->eglContext = 0; 83 return false; 84 } 85 86 // Construct the configuration we need for this surface. 87 QEglProperties configProps; 88 qt_egl_set_format(configProps, devType, d->glFormat); 89 qt_egl_add_platform_config(configProps, device()); 90 configProps.setRenderableType(QEgl::OpenGL); 91 92 #if We_have_an_EGL_library_which_bothers_to_check_EGL_BUFFER_SIZE 93 if (device()->depth() == 16 && configProps.value(EGL_ALPHA_SIZE) <= 0) { 94 qDebug("Setting EGL_BUFFER_SIZE to 16"); 95 configProps.setValue(EGL_BUFFER_SIZE, 16); 96 configProps.setValue(EGL_ALPHA_SIZE, 0); 97 } 98 99 if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) { 100 delete d->eglContext; 101 d->eglContext = 0; 102 return false; 103 } 104 #else 105 QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat; 106 if ((device()->depth() == 16) && configProps.value(EGL_ALPHA_SIZE) == 0) { 107 configProps.setValue(EGL_RED_SIZE, 5); 108 configProps.setValue(EGL_GREEN_SIZE, 6); 109 configProps.setValue(EGL_BLUE_SIZE, 5); 110 configProps.setValue(EGL_ALPHA_SIZE, 0); 111 matchType = QEgl::ExactPixelFormat; 112 } 113 114 // Search for a matching configuration, reducing the complexity 115 // each time until we get something that matches. 116 if (!d->eglContext->chooseConfig(configProps, matchType)) { 117 delete d->eglContext; 118 d->eglContext = 0; 119 return false; 120 } 121 #endif 122 123 // qDebug("QGLContext::chooseContext() - using EGL config %d:", d->eglContext->config()); 124 // qDebug() << QEglProperties(d->eglContext->config()).toString(); 125 126 // Create a new context for the configuration. 127 if (!d->eglContext->createContext 128 (shareContext ? shareContext->d_func()->eglContext : 0)) { 129 delete d->eglContext; 130 d->eglContext = 0; 131 return false; 132 } 133 d->sharing = d->eglContext->isSharing(); 134 if (d->sharing && shareContext) 135 const_cast<QGLContext *>(shareContext)->d_func()->sharing = true; 136 137 #if defined(EGL_VERSION_1_1) 138 if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget) 139 eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval()); 140 #endif 99 141 } 100 142 … … 102 144 qt_egl_update_format(*(d->eglContext), d->glFormat); 103 145 104 // Create a new context for the configuration.105 if (!d->eglContext->createContext106 (shareContext ? shareContext->d_func()->eglContext : 0)) {107 delete d->eglContext;108 d->eglContext = 0;109 return false;110 }111 112 #if defined(EGL_VERSION_1_1)113 if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)114 eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());115 #endif116 117 // Create the EGL surface to draw into.118 if (!d->eglContext->createSurface(device())) {119 delete d->eglContext;120 d->eglContext = 0;121 return false;122 }123 124 146 return true; 125 147 } 126 127 128 void QGLContext::reset()129 {130 Q_D(QGLContext);131 if (!d->valid)132 return;133 d->cleanup();134 doneCurrent();135 if (d->eglContext) {136 delete d->eglContext;137 d->eglContext = 0;138 }139 d->crWin = false;140 d->sharing = false;141 d->valid = false;142 d->transpColor = QColor();143 d->initDone = false;144 qgl_share_reg()->removeShare(this);145 }146 147 void QGLContext::makeCurrent()148 {149 Q_D(QGLContext);150 if(!d->valid || !d->eglContext) {151 qWarning("QGLContext::makeCurrent(): Cannot make invalid context current");152 return;153 }154 155 if (d->eglContext->makeCurrent()) {156 if (!qgl_context_storage.hasLocalData() && QThread::currentThread())157 qgl_context_storage.setLocalData(new QGLThreadContext);158 if (qgl_context_storage.hasLocalData())159 qgl_context_storage.localData()->context = this;160 currentCtx = this;161 }162 }163 164 void QGLContext::doneCurrent()165 {166 Q_D(QGLContext);167 if (d->eglContext)168 d->eglContext->doneCurrent();169 170 if (qgl_context_storage.hasLocalData())171 qgl_context_storage.localData()->context = 0;172 currentCtx = 0;173 }174 175 176 void QGLContext::swapBuffers() const177 {178 Q_D(const QGLContext);179 if(!d->valid || !d->eglContext)180 return;181 182 d->eglContext->swapBuffers();183 }184 185 QColor QGLContext::overlayTransparentColor() const186 {187 return QColor(0, 0, 0); // Invalid color188 }189 190 uint QGLContext::colorIndex(const QColor &c) const191 {192 //### color index doesn't work on egl193 Q_UNUSED(c);194 return 0;195 }196 197 void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase)198 {199 Q_UNUSED(fnt);200 Q_UNUSED(listBase);201 }202 203 void *QGLContext::getProcAddress(const QString &proc) const204 {205 return (void*)eglGetProcAddress(reinterpret_cast<const char *>(proc.toLatin1().data()));206 }207 208 void QGLWidget::setMouseTracking(bool enable)209 {210 QWidget::setMouseTracking(enable);211 }212 213 148 214 149 void QGLWidget::resizeEvent(QResizeEvent *) … … 239 174 } 240 175 176 //#define QT_DEBUG_X11_VISUAL_SELECTION 1 177 178 bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config, const QX11Info &x11Info, bool useArgbVisual) 179 { 180 bool foundVisualIsArgb = useArgbVisual; 181 182 #ifdef QT_DEBUG_X11_VISUAL_SELECTION 183 qDebug("qt_egl_setup_x11_visual() - useArgbVisual=%d", useArgbVisual); 184 #endif 185 186 memset(&vi, 0, sizeof(XVisualInfo)); 187 188 EGLint eglConfigColorSize; 189 eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &eglConfigColorSize); 190 191 // Check to see if EGL is suggesting an appropriate visual id: 192 EGLint nativeVisualId; 193 eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisualId); 194 vi.visualid = nativeVisualId; 195 196 if (vi.visualid) { 197 // EGL has suggested a visual id, so get the rest of the visual info for that id: 198 XVisualInfo *chosenVisualInfo; 199 int matchingCount = 0; 200 chosenVisualInfo = XGetVisualInfo(x11Info.display(), VisualIDMask, &vi, &matchingCount); 201 if (chosenVisualInfo) { 202 #if !defined(QT_NO_XRENDER) 203 if (useArgbVisual) { 204 // Check to make sure the visual provided by EGL is ARGB 205 XRenderPictFormat *format; 206 format = XRenderFindVisualFormat(x11Info.display(), chosenVisualInfo->visual); 207 if (format->type == PictTypeDirect && format->direct.alphaMask) { 208 #ifdef QT_DEBUG_X11_VISUAL_SELECTION 209 qDebug("Using ARGB X Visual ID (%d) provided by EGL", (int)vi.visualid); 210 #endif 211 foundVisualIsArgb = true; 212 vi = *chosenVisualInfo; 213 } 214 else { 215 qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this is not ARGB", 216 nativeVisualId, (int)config); 217 vi.visualid = 0; 218 } 219 } else 220 #endif 221 { 222 if (eglConfigColorSize == chosenVisualInfo->depth) { 223 #ifdef QT_DEBUG_X11_VISUAL_SELECTION 224 qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid); 225 #endif 226 vi = *chosenVisualInfo; 227 } else 228 qWarning("Warning: EGL suggested using X visual ID %d (%d bpp) for config %d (%d bpp), but the depths do not match!", 229 nativeVisualId, chosenVisualInfo->depth, (int)config, eglConfigColorSize); 230 } 231 XFree(chosenVisualInfo); 232 } 233 else { 234 qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this seems to be invalid!", 235 nativeVisualId, (int)config); 236 vi.visualid = 0; 237 } 238 } 239 240 // If EGL does not know the visual ID, so try to select an appropriate one ourselves, first 241 // using XRender if we're supposed to have an alpha, then falling back to XGetVisualInfo 242 243 #if !defined(QT_NO_XRENDER) 244 if (vi.visualid == 0 && useArgbVisual) { 245 // Try to use XRender to find an ARGB visual we can use 246 vi.screen = x11Info.screen(); 247 vi.depth = 32; //### We might at some point (soon) get ARGB4444 248 vi.c_class = TrueColor; 249 XVisualInfo *matchingVisuals; 250 int matchingCount = 0; 251 matchingVisuals = XGetVisualInfo(x11Info.display(), 252 VisualScreenMask|VisualDepthMask|VisualClassMask, 253 &vi, &matchingCount); 254 255 for (int i = 0; i < matchingCount; ++i) { 256 XRenderPictFormat *format; 257 format = XRenderFindVisualFormat(x11Info.display(), matchingVisuals[i].visual); 258 if (format->type == PictTypeDirect && format->direct.alphaMask) { 259 vi = matchingVisuals[i]; 260 foundVisualIsArgb = true; 261 #ifdef QT_DEBUG_X11_VISUAL_SELECTION 262 qDebug("Using X Visual ID (%d) for ARGB visual as provided by XRender", (int)vi.visualid); 263 #endif 264 break; 265 } 266 } 267 XFree(matchingVisuals); 268 } 269 #endif 270 271 if (vi.visualid == 0) { 272 EGLint depth; 273 eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &depth); 274 int err; 275 err = XMatchVisualInfo(x11Info.display(), x11Info.screen(), depth, TrueColor, &vi); 276 if (err == 0) { 277 qWarning("Warning: Can't find an X visual which matches the EGL config(%d)'s depth (%d)!", 278 (int)config, depth); 279 depth = x11Info.depth(); 280 err = XMatchVisualInfo(x11Info.display(), x11Info.screen(), depth, TrueColor, &vi); 281 if (err == 0) { 282 qWarning("Error: Couldn't get any matching X visual!"); 283 return false; 284 } else 285 qWarning(" - Falling back to X11 suggested depth (%d)", depth); 286 } 287 #ifdef QT_DEBUG_X11_VISUAL_SELECTION 288 else 289 qDebug("Using X Visual ID (%d) for EGL provided depth (%d)", (int)vi.visualid, depth); 290 #endif 291 292 // Don't try to use ARGB now unless the visual is 32-bit - even then it might stil fail :-( 293 if (useArgbVisual) 294 foundVisualIsArgb = vi.depth == 32; //### We might at some point (soon) get ARGB4444 295 } 296 297 #ifdef QT_DEBUG_X11_VISUAL_SELECTION 298 qDebug("Visual Info:"); 299 qDebug(" bits_per_rgb=%d", vi.bits_per_rgb); 300 qDebug(" red_mask=0x%x", vi.red_mask); 301 qDebug(" green_mask=0x%x", vi.green_mask); 302 qDebug(" blue_mask=0x%x", vi.blue_mask); 303 qDebug(" colormap_size=%d", vi.colormap_size); 304 qDebug(" c_class=%d", vi.c_class); 305 qDebug(" depth=%d", vi.depth); 306 qDebug(" screen=%d", vi.screen); 307 qDebug(" visualid=%d", vi.visualid); 308 #endif 309 return foundVisualIsArgb; 310 } 311 241 312 void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext) 242 313 { … … 263 334 } 264 335 265 bool visible = isVisible(); 266 if (visible) 267 hide(); 268 269 XVisualInfo vi; 270 271 int err = XMatchVisualInfo(x11Info().display(), x11Info().screen(), x11Info().depth(), TrueColor, &vi); 272 if (err == 0) { 273 qWarning("Error: Couldn't get a matching X visual for format"); 274 return; 275 } 276 277 XSetWindowAttributes a; 278 279 Window p = RootWindow(X11->display, vi.screen); 280 if (parentWidget()) 281 p = parentWidget()->winId(); 282 283 QColormap colmap = QColormap::instance(vi.screen); 284 a.background_pixel = colmap.pixel(palette().color(backgroundRole())); 285 a.border_pixel = colmap.pixel(Qt::black); 286 287 Window w = XCreateWindow(X11->display, p, x(), y(), width(), height(), 288 0, vi.depth, InputOutput, vi.visual, 289 CWBackPixel|CWBorderPixel, &a); 290 291 if (deleteOldContext) 292 delete oldcx; 293 oldcx = 0; 294 295 create(w); // Create with the ID of the window we've just created 296 297 d->eglSurfaceWindowId = w; // Remember the window id we created the surface for 298 299 if (visible) 300 show(); 336 // If the application has set WA_TranslucentBackground and not explicitly set 337 // the alpha buffer size to zero, modify the format so it have an alpha channel 338 QGLFormat& fmt = d->glcx->d_func()->glFormat; 339 const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground) || fmt.alpha(); 340 if (tryArgbVisual && fmt.alphaBufferSize() == -1) 341 fmt.setAlphaBufferSize(1); 301 342 302 343 bool createFailed = false; 303 344 if (!d->glcx->isValid()) { 345 // Create the QGLContext here, which in turn chooses the EGL config 346 // and creates the EGL context: 304 347 if (!d->glcx->create(shareContext ? shareContext : oldcx)) 305 348 createFailed = true; … … 317 360 } 318 361 362 bool visible = isVisible(); 363 if (visible) 364 hide(); 365 366 XVisualInfo vi; 367 QEglContext *eglContext = d->glcx->d_func()->eglContext; 368 bool usingArgbVisual = qt_egl_setup_x11_visual(vi, eglContext->display(), eglContext->config(), 369 x11Info(), tryArgbVisual); 370 371 XSetWindowAttributes a; 372 373 Window p = RootWindow(x11Info().display(), x11Info().screen()); 374 if (parentWidget()) 375 p = parentWidget()->winId(); 376 377 QColormap colmap = QColormap::instance(vi.screen); 378 a.background_pixel = colmap.pixel(palette().color(backgroundRole())); 379 a.border_pixel = colmap.pixel(Qt::black); 380 381 unsigned int valueMask = CWBackPixel|CWBorderPixel; 382 if (usingArgbVisual) { 383 a.colormap = XCreateColormap(x11Info().display(), p, vi.visual, AllocNone); 384 valueMask |= CWColormap; 385 } 386 387 Window w = XCreateWindow(x11Info().display(), p, x(), y(), width(), height(), 388 0, vi.depth, InputOutput, vi.visual, valueMask, &a); 389 390 if (deleteOldContext) 391 delete oldcx; 392 oldcx = 0; 393 394 create(w); // Create with the ID of the window we've just created 395 396 397 // Create the EGL surface to draw into. 398 QGLContextPrivate *ctxpriv = d->glcx->d_func(); 399 ctxpriv->eglSurface = ctxpriv->eglContext->createSurface(this); 400 if (ctxpriv->eglSurface == EGL_NO_SURFACE) { 401 delete ctxpriv->eglContext; 402 ctxpriv->eglContext = 0; 403 return; 404 } 405 406 d->eglSurfaceWindowId = w; // Remember the window id we created the surface for 407 408 if (visible) 409 show(); 410 411 XFlush(X11->display); 319 412 d->glcx->setWindowCreated(true); 320 413 } … … 332 425 } 333 426 334 bool QGLWidgetPrivate::renderCxPm(QPixmap*)335 {336 return false;337 }338 339 427 void QGLWidgetPrivate::cleanupColormaps() 340 428 { … … 357 445 return; 358 446 init_done = true; 447 448 // We need a context current to initialize the extensions. 449 QGLWidget tmpWidget; 450 tmpWidget.makeCurrent(); 451 359 452 init_extensions(); 453 454 tmpWidget.doneCurrent(); 360 455 } 361 456 … … 369 464 if ( force || (currentId != eglSurfaceWindowId) ) { 370 465 // The window id has changed so we need to re-create the EGL surface 371 if (!glcx->d_func()->eglContext->recreateSurface(q)) 466 QEglContext *ctx = glcx->d_func()->eglContext; 467 EGLSurface surface = glcx->d_func()->eglSurface; 468 if (surface != EGL_NO_SURFACE) 469 ctx->destroySurface(surface); // Will force doneCurrent() if nec. 470 surface = ctx->createSurface(q); 471 if (surface == EGL_NO_SURFACE) 372 472 qWarning("Error creating EGL window surface: 0x%x", eglGetError()); 473 glcx->d_func()->eglSurface = surface; 373 474 374 475 eglSurfaceWindowId = currentId; … … 376 477 } 377 478 479 // Selects which configs should be used 480 EGLConfig Q_OPENGL_EXPORT qt_chooseEGLConfigForPixmap(bool hasAlpha, bool readOnly) 481 { 482 // Cache the configs we select as they wont change: 483 static EGLConfig roPixmapRGBConfig = 0; 484 static EGLConfig roPixmapRGBAConfig = 0; 485 static EGLConfig rwPixmapRGBConfig = 0; 486 static EGLConfig rwPixmapRGBAConfig = 0; 487 488 EGLConfig* targetConfig; 489 490 if (hasAlpha) { 491 if (readOnly) 492 targetConfig = &roPixmapRGBAConfig; 493 else 494 targetConfig = &rwPixmapRGBAConfig; 495 } 496 else { 497 if (readOnly) 498 targetConfig = &roPixmapRGBConfig; 499 else 500 targetConfig = &rwPixmapRGBConfig; 501 } 502 503 if (*targetConfig == 0) { 504 QEglProperties configAttribs; 505 configAttribs.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT); 506 configAttribs.setRenderableType(QEgl::OpenGL); 507 if (hasAlpha) 508 configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); 509 else 510 configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); 511 512 // If this is going to be a render target, it needs to have a depth, stencil & sample buffer 513 if (!readOnly) { 514 configAttribs.setValue(EGL_DEPTH_SIZE, 1); 515 configAttribs.setValue(EGL_STENCIL_SIZE, 1); 516 configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1); 517 } 518 519 EGLint configCount = 0; 520 do { 521 eglChooseConfig(QEglContext::defaultDisplay(0), configAttribs.properties(), targetConfig, 1, &configCount); 522 if (configCount > 0) { 523 // Got one 524 qDebug() << "Found an" << (hasAlpha ? "ARGB" : "RGB") << (readOnly ? "readonly" : "target" ) 525 << "config (" << int(*targetConfig) << ") to create a pixmap surface:"; 526 527 // QEglProperties configProps(*targetConfig); 528 // qDebug() << configProps.toString(); 529 break; 530 } 531 qWarning("choosePixmapConfig() - No suitible config found, reducing requirements"); 532 } while (configAttribs.reduceConfiguration()); 533 } 534 535 if (*targetConfig == 0) 536 qWarning("choosePixmapConfig() - Couldn't find a suitable config"); 537 538 return *targetConfig; 539 } 540 541 bool Q_OPENGL_EXPORT qt_createEGLSurfaceForPixmap(QPixmapData* pmd, bool readOnly) 542 { 543 Q_ASSERT(pmd->classId() == QPixmapData::X11Class); 544 QX11PixmapData* pixmapData = static_cast<QX11PixmapData*>(pmd); 545 546 bool hasAlpha = pixmapData->hasAlphaChannel(); 547 548 EGLConfig pixmapConfig = qt_chooseEGLConfigForPixmap(hasAlpha, readOnly); 549 550 QEglProperties pixmapAttribs; 551 552 // If the pixmap can't be bound to a texture, it's pretty useless 553 pixmapAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D); 554 if (hasAlpha) 555 pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA); 556 else 557 pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB); 558 559 EGLSurface pixmapSurface; 560 pixmapSurface = eglCreatePixmapSurface(QEglContext::defaultDisplay(0), 561 pixmapConfig, 562 (EGLNativePixmapType) pixmapData->handle(), 563 pixmapAttribs.properties()); 564 // qDebug("qt_createEGLSurfaceForPixmap() created surface 0x%x for pixmap 0x%x", 565 // pixmapSurface, pixmapData->handle()); 566 if (pixmapSurface == EGL_NO_SURFACE) { 567 qWarning() << "Failed to create a pixmap surface using config" << (int)pixmapConfig 568 << ":" << QEglContext::errorString(eglGetError()); 569 return false; 570 } 571 572 static bool doneOnce = false; 573 if (!doneOnce) { 574 // Make sure QGLTextureCache is instanciated so it can install cleanup hooks 575 // which cleanup the EGL surface. 576 QGLTextureCache::instance(); 577 doneOnce = true; 578 } 579 580 Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure! 581 pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface; 582 QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData); // Make sure the cleanup hook gets called 583 584 return true; 585 } 586 587 588 QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, const qint64 key, 589 QGLContext::BindOptions options) 590 { 591 Q_Q(QGLContext); 592 593 // The EGL texture_from_pixmap has no facility to invert the y coordinate 594 if (!(options & QGLContext::CanFlipNativePixmapBindOption)) 595 return 0; 596 597 Q_ASSERT(pd->classId() == QPixmapData::X11Class); 598 599 static bool checkedForTFP = false; 600 static bool haveTFP = false; 601 602 if (!checkedForTFP) { 603 // Check for texture_from_pixmap egl extension 604 checkedForTFP = true; 605 if (eglContext->hasExtension("EGL_NOKIA_texture_from_pixmap") || 606 eglContext->hasExtension("EGL_EXT_texture_from_pixmap")) 607 { 608 qDebug("Found texture_from_pixmap EGL extension!"); 609 haveTFP = true; 610 } 611 } 612 613 if (!haveTFP) 614 return 0; 615 616 QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pd); 617 618 bool hasAlpha = pixmapData->hasAlphaChannel(); 619 620 // Check to see if the surface is still valid 621 if (pixmapData->gl_surface && 622 hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) 623 { 624 // Surface is invalid! 625 destroyGlSurfaceForPixmap(pixmapData); 626 } 627 628 if (pixmapData->gl_surface == 0) { 629 bool success = qt_createEGLSurfaceForPixmap(pixmapData, true); 630 if (!success) { 631 haveTFP = false; 632 return 0; 633 } 634 } 635 636 Q_ASSERT(pixmapData->gl_surface); 637 638 GLuint textureId; 639 glGenTextures(1, &textureId); 640 glBindTexture(GL_TEXTURE_2D, textureId); 641 642 // bind the egl pixmap surface to a texture 643 EGLBoolean success; 644 success = eglBindTexImage(eglContext->display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER); 645 if (success == EGL_FALSE) { 646 qWarning() << "eglBindTexImage() failed:" << eglContext->errorString(eglGetError()); 647 eglDestroySurface(eglContext->display(), (EGLSurface)pixmapData->gl_surface); 648 pixmapData->gl_surface = (Qt::HANDLE)EGL_NO_SURFACE; 649 haveTFP = false; 650 return 0; 651 } 652 653 QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options); 654 pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture; 655 656 // We assume the cost of bound pixmaps is zero 657 QGLTextureCache::instance()->insert(q, key, texture, 0); 658 659 glBindTexture(GL_TEXTURE_2D, textureId); 660 return texture; 661 } 662 663 void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd) 664 { 665 Q_ASSERT(pmd->classId() == QPixmapData::X11Class); 666 QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); 667 if (pixmapData->gl_surface) { 668 EGLBoolean success; 669 success = eglDestroySurface(QEglContext::defaultDisplay(0), (EGLSurface)pixmapData->gl_surface); 670 if (success == EGL_FALSE) { 671 qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: " 672 << QEglContext::errorString(eglGetError()); 673 } 674 pixmapData->gl_surface = 0; 675 } 676 } 677 678 void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd) 679 { 680 Q_ASSERT(pmd->classId() == QPixmapData::X11Class); 681 QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); 682 if (pixmapData->gl_surface) { 683 EGLBoolean success; 684 success = eglReleaseTexImage(QEglContext::defaultDisplay(0), 685 (EGLSurface)pixmapData->gl_surface, 686 EGL_BACK_BUFFER); 687 if (success == EGL_FALSE) { 688 qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: " 689 << QEglContext::errorString(eglGetError()); 690 } 691 } 692 } 693 378 694 QT_END_NAMESPACE
Note:
See TracChangeset
for help on using the changeset viewer.