Changeset 846 for trunk/src/opengl/qgl_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/qgl_egl.cpp
r651 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) … … 41 41 42 42 #include <QtOpenGL/qgl.h> 43 #include <QtOpenGL/qglpixelbuffer.h> 43 44 #include "qgl_p.h" 44 45 #include "qgl_egl_p.h" 46 #include "qglpixelbuffer_p.h" 47 48 #ifdef Q_WS_X11 49 #include <QtGui/private/qpixmap_x11_p.h> 50 #endif 45 51 46 52 QT_BEGIN_NAMESPACE 47 53 48 // Set device configuration attributes from a QGLFormat instance. 49 void qt_egl_set_format(QEglProperties& props, int deviceType, const QGLFormat& f) 50 { 51 if (deviceType == QInternal::Pixmap || deviceType == QInternal::Image) 52 props.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT); 53 else if (deviceType == QInternal::Pbuffer) 54 props.setValue(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT); 55 else 56 props.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT); 57 58 // Set the pixel format to that contained in the QGLFormat 59 // if the system hasn't already chosen a fixed format to 60 // match the pixmap, widget, etc. 61 if (props.value(EGL_RED_SIZE) == 0 || f.redBufferSize() != -1) 62 props.setValue(EGL_RED_SIZE, f.redBufferSize() == -1 ? 1 : f.redBufferSize()); 63 if (props.value(EGL_GREEN_SIZE) == 0 || f.greenBufferSize() != -1) 64 props.setValue(EGL_GREEN_SIZE, f.greenBufferSize() == -1 ? 1 : f.greenBufferSize()); 65 if (props.value(EGL_BLUE_SIZE) == 0 || f.blueBufferSize() != -1) 66 props.setValue(EGL_BLUE_SIZE, f.blueBufferSize() == -1 ? 1 : f.blueBufferSize()); 67 if (f.alpha()) { 68 if (props.value(EGL_ALPHA_SIZE) == 0 || f.alphaBufferSize() != -1) 69 props.setValue(EGL_ALPHA_SIZE, f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize()); 70 } 71 72 if (f.depth()) 73 props.setValue(EGL_DEPTH_SIZE, f.depthBufferSize() == -1 ? 1 : f.depthBufferSize()); 74 if (f.stencil()) 75 props.setValue(EGL_STENCIL_SIZE, f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize()); 76 if (f.sampleBuffers()) { 77 props.setValue(EGL_SAMPLE_BUFFERS, 1); 78 props.setValue(EGL_SAMPLES, f.samples() == -1 ? 1 : f.samples()); 79 } else { 80 props.setValue(EGL_SAMPLE_BUFFERS, 0); 81 } 82 if (deviceType == QInternal::Widget) 83 props.setValue(EGL_LEVEL, f.plane()); 54 void qt_eglproperties_set_glformat(QEglProperties& eglProperties, const QGLFormat& glFormat) 55 { 56 int redSize = glFormat.redBufferSize(); 57 int greenSize = glFormat.greenBufferSize(); 58 int blueSize = glFormat.blueBufferSize(); 59 int alphaSize = glFormat.alphaBufferSize(); 60 int depthSize = glFormat.depthBufferSize(); 61 int stencilSize = glFormat.stencilBufferSize(); 62 int sampleCount = glFormat.samples(); 63 64 // QGLFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that 65 // type has been requested. So we must check QGLFormat's booleans too if size is -1: 66 if (glFormat.alpha() && alphaSize <= 0) 67 alphaSize = 1; 68 if (glFormat.depth() && depthSize <= 0) 69 depthSize = 1; 70 if (glFormat.stencil() && stencilSize <= 0) 71 stencilSize = 1; 72 if (glFormat.sampleBuffers() && sampleCount <= 0) 73 sampleCount = 1; 74 75 // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide 76 // the best performance. The EGL config selection algorithm is a bit stange in this regard: 77 // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard 78 // 32-bit configs completely from the selection. So it then comes to the sorting algorithm. 79 // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort 80 // order is special and described as "by larger _total_ number of color bits.". So EGL will 81 // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on 82 // to say "If the requested number of bits in attrib_list for a particular component is 0, 83 // then the number of bits for that component is not considered". This part of the spec also 84 // seems to imply that setting the red/green/blue bits to zero means none of the components 85 // are considered and EGL disregards the entire sorting rule. It then looks to the next 86 // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being 87 // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are 88 // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit, 89 // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that 90 // if the application sets the red/green/blue size to 5/6/5 on the QGLFormat, they will 91 // probably get a 32-bit config, even when there's an RGB565 config available. Oh well. 92 93 // Now normalize the values so -1 becomes 0 94 redSize = redSize > 0 ? redSize : 0; 95 greenSize = greenSize > 0 ? greenSize : 0; 96 blueSize = blueSize > 0 ? blueSize : 0; 97 alphaSize = alphaSize > 0 ? alphaSize : 0; 98 depthSize = depthSize > 0 ? depthSize : 0; 99 stencilSize = stencilSize > 0 ? stencilSize : 0; 100 sampleCount = sampleCount > 0 ? sampleCount : 0; 101 102 eglProperties.setValue(EGL_RED_SIZE, redSize); 103 eglProperties.setValue(EGL_GREEN_SIZE, greenSize); 104 eglProperties.setValue(EGL_BLUE_SIZE, blueSize); 105 eglProperties.setValue(EGL_ALPHA_SIZE, alphaSize); 106 eglProperties.setValue(EGL_DEPTH_SIZE, depthSize); 107 eglProperties.setValue(EGL_STENCIL_SIZE, stencilSize); 108 eglProperties.setValue(EGL_SAMPLES, sampleCount); 109 eglProperties.setValue(EGL_SAMPLE_BUFFERS, sampleCount ? 1 : 0); 84 110 } 85 111 86 112 // Updates "format" with the parameters of the selected configuration. 87 void qt_egl_update_format(const QEglContext& context, QGLFormat& format) 88 { 89 EGLint value = 0; 90 91 if (context.configAttrib(EGL_RED_SIZE, &value)) 92 format.setRedBufferSize(value); 93 if (context.configAttrib(EGL_GREEN_SIZE, &value)) 94 format.setGreenBufferSize(value); 95 if (context.configAttrib(EGL_BLUE_SIZE, &value)) 96 format.setBlueBufferSize(value); 97 if (context.configAttrib(EGL_ALPHA_SIZE, &value)) { 98 format.setAlpha(value != 0); 99 if (format.alpha()) 100 format.setAlphaBufferSize(value); 101 } 102 103 if (context.configAttrib(EGL_DEPTH_SIZE, &value)) { 104 format.setDepth(value != 0); 105 if (format.depth()) 106 format.setDepthBufferSize(value); 107 } 108 109 if (context.configAttrib(EGL_LEVEL, &value)) 110 format.setPlane(value); 111 112 if (context.configAttrib(EGL_SAMPLE_BUFFERS, &value)) { 113 format.setSampleBuffers(value != 0); 114 if (format.sampleBuffers()) { 115 context.configAttrib(EGL_SAMPLES, &value); 116 format.setSamples(value); 117 } 118 } 119 120 if (context.configAttrib(EGL_STENCIL_SIZE, &value)) { 121 format.setStencil(value != 0); 122 if (format.stencil()) 123 format.setStencilBufferSize(value); 124 } 113 void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config) 114 { 115 EGLint redSize = 0; 116 EGLint greenSize = 0; 117 EGLint blueSize = 0; 118 EGLint alphaSize = 0; 119 EGLint depthSize = 0; 120 EGLint stencilSize = 0; 121 EGLint sampleCount = 0; 122 EGLint level = 0; 123 124 EGLDisplay display = QEgl::display(); 125 eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize); 126 eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize); 127 eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize); 128 eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize); 129 eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize); 130 eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize); 131 eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount); 132 eglGetConfigAttrib(display, config, EGL_LEVEL, &level); 133 134 format.setRedBufferSize(redSize); 135 format.setGreenBufferSize(greenSize); 136 format.setBlueBufferSize(blueSize); 137 format.setAlphaBufferSize(alphaSize); 138 format.setDepthBufferSize(depthSize); 139 format.setStencilBufferSize(stencilSize); 140 format.setSamples(sampleCount); 141 format.setPlane(level); 142 format.setDirectRendering(true); // All EGL contexts are direct-rendered 143 format.setRgba(true); // EGL doesn't support colour index rendering 144 format.setStereo(false); // EGL doesn't support stereo buffers 145 format.setAccumBufferSize(0); // EGL doesn't support accululation buffers 146 format.setDoubleBuffer(true); // We don't support single buffered EGL contexts 125 147 126 148 // Clear the EGL error state because some of the above may 127 149 // have errored out because the attribute is not applicable 128 150 // to the surface type. Such errors don't matter. 129 context.clearError();151 eglGetError(); 130 152 } 131 153 … … 142 164 d->cleanup(); 143 165 doneCurrent(); 144 if (d->eglContext ) {166 if (d->eglContext && d->ownsEglContext) { 145 167 d->destroyEglSurfaceForDevice(); 146 168 delete d->eglContext; 147 169 } 170 d->ownsEglContext = false; 148 171 d->eglContext = 0; 149 172 d->eglSurface = EGL_NO_SURFACE; … … 159 182 { 160 183 Q_D(QGLContext); 161 if (!d->valid || !d->eglContext || d->eglSurface == EGL_NO_SURFACE) {184 if (!d->valid || !d->eglContext || d->eglSurfaceForDevice() == EGL_NO_SURFACE) { 162 185 qWarning("QGLContext::makeCurrent(): Cannot make invalid context current"); 163 186 return; 164 187 } 165 188 166 if (d->eglContext->makeCurrent(d->eglSurface ))189 if (d->eglContext->makeCurrent(d->eglSurfaceForDevice())) { 167 190 QGLContextPrivate::setCurrentContext(this); 191 if (!d->workaroundsCached) { 192 d->workaroundsCached = true; 193 const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER)); 194 if (renderer && (strstr(renderer, "SGX") || strstr(renderer, "MBX"))) { 195 // PowerVR MBX/SGX chips needs to clear all buffers when starting to render 196 // a new frame, otherwise there will be a performance penalty to pay for 197 // each frame. 198 d->workaround_needsFullClearOnEveryFrame = true; 199 200 // Older PowerVR SGX drivers (like the one in the N900) have a 201 // bug which prevents glCopyTexSubImage2D() to work with a POT 202 // or GL_ALPHA texture bound to an FBO. The only way to 203 // identify that driver is to check the EGL version number for it. 204 const char *egl_version = eglQueryString(d->eglContext->display(), EGL_VERSION); 205 if (egl_version && strstr(egl_version, "1.3")) 206 d->workaround_brokenFBOReadBack = true; 207 else if (egl_version && strstr(egl_version, "1.4")) 208 d->workaround_brokenTexSubImage = true; 209 } 210 } 211 } 168 212 } 169 213 … … 184 228 return; 185 229 186 d->eglContext->swapBuffers(d->eglSurface );230 d->eglContext->swapBuffers(d->eglSurfaceForDevice()); 187 231 } 188 232 … … 190 234 { 191 235 if (eglSurface != EGL_NO_SURFACE) { 236 #if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN) 237 // Make sure we don't call eglDestroySurface on a surface which 238 // was created for a different winId. This applies only to QGLWidget 239 // paint device, so make sure this is the one we're operating on 240 // (as opposed to a QGLWindowSurface use case). 241 if (paintDevice && paintDevice->devType() == QInternal::Widget) { 242 QWidget *w = static_cast<QWidget *>(paintDevice); 243 if (QGLWidget *wgl = qobject_cast<QGLWidget *>(w)) { 244 if (wgl->d_func()->eglSurfaceWindowId != wgl->winId()) { 245 qWarning("WARNING: Potential EGL surface leak! Not destroying surface."); 246 eglSurface = EGL_NO_SURFACE; 247 return; 248 } 249 } 250 } 251 #endif 252 eglDestroySurface(eglContext->display(), eglSurface); 253 eglSurface = EGL_NO_SURFACE; 254 } 255 } 256 257 EGLSurface QGLContextPrivate::eglSurfaceForDevice() const 258 { 259 // If a QPixmapData had to create the QGLContext, we don't have a paintDevice 260 if (!paintDevice) 261 return eglSurface; 262 192 263 #ifdef Q_WS_X11 193 // Make sure we don't call eglDestroySurface on a surface which 194 // was created for a different winId: 195 if (paintDevice->devType() == QInternal::Widget) { 196 QGLWidget* w = static_cast<QGLWidget*>(paintDevice); 197 198 if (w->d_func()->eglSurfaceWindowId == w->winId()) 199 eglDestroySurface(eglContext->display(), eglSurface); 200 else 201 qWarning("WARNING: Potential EGL surface leak!"); 202 } else 264 if (paintDevice->devType() == QInternal::Pixmap) { 265 QPixmapData *pmd = static_cast<QPixmap*>(paintDevice)->data_ptr().data(); 266 if (pmd->classId() == QPixmapData::X11Class) { 267 QX11PixmapData* x11PixmapData = static_cast<QX11PixmapData*>(pmd); 268 return (EGLSurface)x11PixmapData->gl_surface; 269 } 270 } 203 271 #endif 204 eglDestroySurface(eglContext->display(), eglSurface); 205 eglSurface = EGL_NO_SURFACE; 206 } 272 273 if (paintDevice->devType() == QInternal::Pbuffer) { 274 QGLPixelBuffer* pbuf = static_cast<QGLPixelBuffer*>(paintDevice); 275 return pbuf->d_func()->pbuf; 276 } 277 278 return eglSurface; 279 } 280 281 void QGLContextPrivate::swapRegion(const QRegion ®ion) 282 { 283 if (!valid || !eglContext) 284 return; 285 286 eglContext->swapBuffersRegion2NOK(eglSurfaceForDevice(), ®ion); 207 287 } 208 288
Note:
See TracChangeset
for help on using the changeset viewer.