Changeset 846 for trunk/src/gui/egl/qegl_x11.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/gui/egl/qegl_x11.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 42 42 #include <QtCore/qdebug.h> 43 43 44 #include < private/qt_x11_p.h>44 #include <QtGui/private/qt_x11_p.h> 45 45 #include <QtGui/qx11info_x11.h> 46 #include <private/qpixmapdata_p.h> 47 #include <private/qpixmap_x11_p.h> 46 #include <QtGui/private/qpixmapdata_p.h> 47 #include <QtGui/private/qpixmap_x11_p.h> 48 #include <QtGui/private/qimagepixmapcleanuphooks_p.h> 48 49 49 50 #include <QtGui/qpaintdevice.h> 50 51 #include <QtGui/qpixmap.h> 51 52 #include <QtGui/qwidget.h> 52 #include "qegl_p.h" 53 53 #include <QtGui/qcolormap.h> 54 55 #include "QtGui/private/qegl_p.h" 56 #include "QtGui/private/qeglcontext_p.h" 54 57 55 58 QT_BEGIN_NAMESPACE 56 59 57 EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) 58 { 59 // Create the native drawable for the paint device. 60 int devType = device->devType(); 61 EGLNativePixmapType pixmapDrawable = 0; 62 EGLNativeWindowType windowDrawable = 0; 63 bool ok; 64 if (devType == QInternal::Pixmap) { 65 pixmapDrawable = (EGLNativePixmapType)(static_cast<QPixmap *>(device))->handle(); 66 ok = (pixmapDrawable != 0); 67 } else if (devType == QInternal::Widget) { 68 windowDrawable = (EGLNativeWindowType)(static_cast<QWidget *>(device))->winId(); 69 ok = (windowDrawable != 0); 70 } else { 71 ok = false; 72 } 73 if (!ok) { 74 qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); 75 return EGL_NO_SURFACE; 76 } 77 78 // Create the EGL surface to draw into, based on the native drawable. 79 const int *props; 80 if (properties) 81 props = properties->properties(); 82 else 83 props = 0; 84 EGLSurface surf; 85 if (devType == QInternal::Widget) 86 surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props); 87 else 88 surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props); 89 if (surf == EGL_NO_SURFACE) { 90 qWarning() << "QEglContext::createSurface(): Unable to create EGL surface:" 91 << errorString(eglGetError()); 92 } 93 return surf; 94 } 95 96 EGLNativeDisplayType QEglContext::nativeDisplay() 60 61 EGLNativeDisplayType QEgl::nativeDisplay() 97 62 { 98 63 Display *xdpy = QX11Info::display(); … … 102 67 } 103 68 return EGLNativeDisplayType(xdpy); 69 } 70 71 EGLNativeWindowType QEgl::nativeWindow(QWidget* widget) 72 { 73 return (EGLNativeWindowType)(widget->winId()); 74 } 75 76 EGLNativePixmapType QEgl::nativePixmap(QPixmap* pixmap) 77 { 78 return (EGLNativePixmapType)(pixmap->handle()); 104 79 } 105 80 … … 154 129 } 155 130 131 //#define QT_DEBUG_X11_VISUAL_SELECTION 1 132 133 VisualID QEgl::getCompatibleVisualId(EGLConfig config) 134 { 135 VisualID visualId = 0; 136 EGLint eglValue = 0; 137 138 EGLint configRedSize = 0; 139 eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &configRedSize); 140 141 EGLint configGreenSize = 0; 142 eglGetConfigAttrib(display(), config, EGL_GREEN_SIZE, &configGreenSize); 143 144 EGLint configBlueSize = 0; 145 eglGetConfigAttrib(display(), config, EGL_BLUE_SIZE, &configBlueSize); 146 147 EGLint configAlphaSize = 0; 148 eglGetConfigAttrib(display(), config, EGL_ALPHA_SIZE, &configAlphaSize); 149 150 eglGetConfigAttrib(display(), config, EGL_CONFIG_ID, &eglValue); 151 int configId = eglValue; 152 153 // See if EGL provided a valid VisualID: 154 eglGetConfigAttrib(display(), config, EGL_NATIVE_VISUAL_ID, &eglValue); 155 visualId = (VisualID)eglValue; 156 if (visualId) { 157 // EGL has suggested a visual id, so get the rest of the visual info for that id: 158 XVisualInfo visualInfoTemplate; 159 memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); 160 visualInfoTemplate.visualid = visualId; 161 162 XVisualInfo *chosenVisualInfo; 163 int matchingCount = 0; 164 chosenVisualInfo = XGetVisualInfo(X11->display, VisualIDMask, &visualInfoTemplate, &matchingCount); 165 if (chosenVisualInfo) { 166 // Skip size checks if implementation supports non-matching visual 167 // and config (http://bugreports.qt.nokia.com/browse/QTBUG-9444). 168 if (QEgl::hasExtension("EGL_NV_post_convert_rounding")) { 169 XFree(chosenVisualInfo); 170 return visualId; 171 } 172 173 int visualRedSize = countBits(chosenVisualInfo->red_mask); 174 int visualGreenSize = countBits(chosenVisualInfo->green_mask); 175 int visualBlueSize = countBits(chosenVisualInfo->blue_mask); 176 int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size 177 178 #if !defined(QT_NO_XRENDER) 179 if (X11->use_xrender) { 180 // If we have XRender, actually check the visual supplied by EGL is ARGB 181 XRenderPictFormat *format; 182 format = XRenderFindVisualFormat(X11->display, chosenVisualInfo->visual); 183 if (format && (format->type == PictTypeDirect)) 184 visualAlphaSize = countBits(format->direct.alphaMask); 185 } 186 #endif 187 188 bool visualMatchesConfig = false; 189 if ( visualRedSize == configRedSize && 190 visualGreenSize == configGreenSize && 191 visualBlueSize == configBlueSize ) 192 { 193 // We need XRender to check the alpha channel size of the visual. If we don't have 194 // the alpha size, we don't check it against the EGL config's alpha size. 195 if (visualAlphaSize >= 0) 196 visualMatchesConfig = visualAlphaSize == configAlphaSize; 197 else 198 visualMatchesConfig = true; 199 } 200 201 if (!visualMatchesConfig) { 202 if (visualAlphaSize >= 0) { 203 qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable", 204 (int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize, 205 configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize); 206 } else { 207 qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable", 208 (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, 209 configId, configRedSize, configGreenSize, configBlueSize); 210 } 211 visualId = 0; 212 } 213 } else { 214 qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID", 215 (int)visualId, configId); 216 visualId = 0; 217 } 218 XFree(chosenVisualInfo); 219 } 220 #ifdef QT_DEBUG_X11_VISUAL_SELECTION 221 else 222 qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId); 223 #endif 224 225 if (visualId) { 226 #ifdef QT_DEBUG_X11_VISUAL_SELECTION 227 if (configAlphaSize > 0) 228 qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId); 229 else 230 qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId); 231 #endif 232 return visualId; 233 } 234 235 236 // If EGL didn't give us a valid visual ID, try XRender 237 #if !defined(QT_NO_XRENDER) 238 if (!visualId && X11->use_xrender) { 239 XVisualInfo visualInfoTemplate; 240 memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); 241 242 visualInfoTemplate.c_class = TrueColor; 243 244 XVisualInfo *matchingVisuals; 245 int matchingCount = 0; 246 matchingVisuals = XGetVisualInfo(X11->display, 247 VisualClassMask, 248 &visualInfoTemplate, 249 &matchingCount); 250 251 for (int i = 0; i < matchingCount; ++i) { 252 XRenderPictFormat *format; 253 format = XRenderFindVisualFormat(X11->display, matchingVisuals[i].visual); 254 255 // Check the format for the visual matches the EGL config 256 if ( (countBits(format->direct.redMask) == configRedSize) && 257 (countBits(format->direct.greenMask) == configGreenSize) && 258 (countBits(format->direct.blueMask) == configBlueSize) && 259 (countBits(format->direct.alphaMask) == configAlphaSize) ) 260 { 261 visualId = matchingVisuals[i].visualid; 262 break; 263 } 264 } 265 if (matchingVisuals) 266 XFree(matchingVisuals); 267 268 } 269 if (visualId) { 270 # ifdef QT_DEBUG_X11_VISUAL_SELECTION 271 if (configAlphaSize > 0) 272 qDebug("Using ARGB Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId); 273 else 274 qDebug("Using Opaque Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId); 275 # endif // QT_DEBUG_X11_VISUAL_SELECTION 276 return visualId; 277 } 278 # ifdef QT_DEBUG_X11_VISUAL_SELECTION 279 else 280 qDebug("Failed to find an XVisual which matches EGL config %d using XRender", configId); 281 # endif // QT_DEBUG_X11_VISUAL_SELECTION 282 283 #endif //!defined(QT_NO_XRENDER) 284 285 286 // Finally, if XRender also failed to find a visual (or isn't present), try to 287 // use XGetVisualInfo and only use the bit depths to match on: 288 if (!visualId) { 289 XVisualInfo visualInfoTemplate; 290 memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); 291 XVisualInfo *matchingVisuals; 292 int matchingCount = 0; 293 294 visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize; 295 matchingVisuals = XGetVisualInfo(X11->display, 296 VisualDepthMask, 297 &visualInfoTemplate, 298 &matchingCount); 299 if (!matchingVisuals) { 300 // Try again without taking the alpha channel into account: 301 visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize; 302 matchingVisuals = XGetVisualInfo(X11->display, 303 VisualDepthMask, 304 &visualInfoTemplate, 305 &matchingCount); 306 } 307 308 if (matchingVisuals) { 309 visualId = matchingVisuals[0].visualid; 310 XFree(matchingVisuals); 311 } 312 } 313 314 if (visualId) { 315 #ifdef QT_DEBUG_X11_VISUAL_SELECTION 316 qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId); 317 #endif 318 return visualId; 319 } 320 321 qWarning("Unable to find an X11 visual which matches EGL config %d", configId); 322 return (VisualID)0; 323 } 324 325 void qt_set_winid_on_widget(QWidget* w, Qt::HANDLE id) 326 { 327 w->create(id); 328 } 329 330 331 // NOTE: The X11 version of createSurface will re-create the native drawable if it's visual doesn't 332 // match the one for the passed in EGLConfig 333 EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig config, const QEglProperties *unusedProperties) 334 { 335 Q_UNUSED(unusedProperties); 336 337 int devType = device->devType(); 338 339 if (devType == QInternal::Pbuffer) { 340 // TODO 341 return EGL_NO_SURFACE; 342 } 343 344 QX11PixmapData *x11PixmapData = 0; 345 if (devType == QInternal::Pixmap) { 346 QPixmapData *pmd = static_cast<QPixmap*>(device)->data_ptr().data(); 347 if (pmd->classId() == QPixmapData::X11Class) 348 x11PixmapData = static_cast<QX11PixmapData*>(pmd); 349 else { 350 // TODO: Replace the pixmap's data with a new QX11PixmapData 351 qWarning("WARNING: Creating an EGL surface on a QPixmap is only supported for QX11PixmapData"); 352 return EGL_NO_SURFACE; 353 } 354 } else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) { 355 qWarning("WARNING: Creating an EGLSurface for device type %d isn't supported", devType); 356 return EGL_NO_SURFACE; 357 } 358 359 VisualID visualId = QEgl::getCompatibleVisualId(config); 360 EGLint alphaSize; 361 eglGetConfigAttrib(QEgl::display(), config, EGL_ALPHA_SIZE, &alphaSize); 362 363 if (devType == QInternal::Widget) { 364 QWidget *widget = static_cast<QWidget*>(device); 365 366 VisualID currentVisualId = 0; 367 if (widget->testAttribute(Qt::WA_WState_Created)) 368 currentVisualId = XVisualIDFromVisual((Visual*)widget->x11Info().visual()); 369 370 if (currentVisualId != visualId) { 371 // The window is either not created or has the wrong visual. Either way, we need 372 // to create a window with the correct visual and call create() on the widget: 373 374 bool visible = widget->isVisible(); 375 if (visible) 376 widget->hide(); 377 378 XVisualInfo visualInfo; 379 visualInfo.visualid = visualId; 380 { 381 XVisualInfo *visualInfoPtr; 382 int matchingCount = 0; 383 visualInfoPtr = XGetVisualInfo(widget->x11Info().display(), VisualIDMask, 384 &visualInfo, &matchingCount); 385 Q_ASSERT(visualInfoPtr); // visualId really should be valid! 386 visualInfo = *visualInfoPtr; 387 XFree(visualInfoPtr); 388 } 389 390 Window parentWindow = RootWindow(widget->x11Info().display(), widget->x11Info().screen()); 391 if (widget->parentWidget()) 392 parentWindow = widget->parentWidget()->winId(); 393 394 XSetWindowAttributes windowAttribs; 395 QColormap colmap = QColormap::instance(widget->x11Info().screen()); 396 windowAttribs.background_pixel = colmap.pixel(widget->palette().color(widget->backgroundRole())); 397 windowAttribs.border_pixel = colmap.pixel(Qt::black); 398 399 unsigned int valueMask = CWBackPixel|CWBorderPixel; 400 if (alphaSize > 0) { 401 windowAttribs.colormap = XCreateColormap(widget->x11Info().display(), parentWindow, 402 visualInfo.visual, AllocNone); 403 valueMask |= CWColormap; 404 } 405 406 Window window = XCreateWindow(widget->x11Info().display(), parentWindow, 407 widget->x(), widget->y(), widget->width(), widget->height(), 408 0, visualInfo.depth, InputOutput, visualInfo.visual, 409 valueMask, &windowAttribs); 410 411 // This is a nasty hack to get round the fact that we can't be a friend of QWidget: 412 qt_set_winid_on_widget(widget, window); 413 414 if (visible) 415 widget->show(); 416 } 417 418 // At this point, the widget's window should be created and have the correct visual. Now we 419 // just need to create the EGL surface for it: 420 EGLSurface surf = eglCreateWindowSurface(QEgl::display(), config, (EGLNativeWindowType)widget->winId(), 0); 421 if (surf == EGL_NO_SURFACE) 422 qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); 423 return surf; 424 } 425 426 if (x11PixmapData) { 427 // X11 Pixmaps are only created with a depth, so that's all we need to check 428 EGLint configDepth; 429 eglGetConfigAttrib(QEgl::display(), config, EGL_BUFFER_SIZE , &configDepth); 430 if (x11PixmapData->depth() != configDepth) { 431 // The bit depths are wrong which means the EGLConfig isn't compatable with 432 // this pixmap. So we need to replace the pixmap's existing data with a new 433 // one which is created with the correct depth: 434 435 #ifndef QT_NO_XRENDER 436 if (configDepth == 32) { 437 qWarning("Warning: EGLConfig's depth (32) != pixmap's depth (%d), converting to ARGB32", 438 x11PixmapData->depth()); 439 x11PixmapData->convertToARGB32(true); 440 } else 441 #endif 442 { 443 qWarning("Warning: EGLConfig's depth (%d) != pixmap's depth (%d)", 444 configDepth, x11PixmapData->depth()); 445 } 446 } 447 448 QEglProperties surfaceAttribs; 449 450 // If the pixmap can't be bound to a texture, it's pretty useless 451 surfaceAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D); 452 if (alphaSize > 0) 453 surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA); 454 else 455 surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB); 456 457 EGLSurface surf = eglCreatePixmapSurface(QEgl::display(), config, 458 (EGLNativePixmapType) x11PixmapData->handle(), 459 surfaceAttribs.properties()); 460 x11PixmapData->gl_surface = (void*)surf; 461 QImagePixmapCleanupHooks::enableCleanupHooks(x11PixmapData); 462 return surf; 463 } 464 465 return EGL_NO_SURFACE; 466 } 467 156 468 QT_END_NAMESPACE
Note:
See TracChangeset
for help on using the changeset viewer.