summaryrefslogtreecommitdiffstats
path: root/src/opengl/qgl_egl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl/qgl_egl.cpp')
-rw-r--r--src/opengl/qgl_egl.cpp127
1 files changed, 90 insertions, 37 deletions
diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp
index 3addea1..3d146b7 100644
--- a/src/opengl/qgl_egl.cpp
+++ b/src/opengl/qgl_egl.cpp
@@ -40,49 +40,78 @@
****************************************************************************/
#include <QtOpenGL/qgl.h>
+#include <QtOpenGL/qglpixelbuffer.h>
#include "qgl_p.h"
#include "qgl_egl_p.h"
+#include "qglpixelbuffer_p.h"
+
+#ifdef Q_WS_X11
+#include <QtGui/private/qpixmap_x11_p.h>
+#endif
QT_BEGIN_NAMESPACE
-// Set device configuration attributes from a QGLFormat instance.
-void qt_egl_set_format(QEglProperties& props, int deviceType, const QGLFormat& f)
+void qt_eglproperties_set_glformat(QEglProperties& eglProperties, const QGLFormat& glFormat)
{
- if (deviceType == QInternal::Pixmap || deviceType == QInternal::Image)
- props.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
- else if (deviceType == QInternal::Pbuffer)
- props.setValue(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
- else
- props.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
-
- // Set the pixel format to that contained in the QGLFormat
- // if the system hasn't already chosen a fixed format to
- // match the pixmap, widget, etc.
- if (props.value(EGL_RED_SIZE) == 0 || f.redBufferSize() != -1)
- props.setValue(EGL_RED_SIZE, f.redBufferSize() == -1 ? 1 : f.redBufferSize());
- if (props.value(EGL_GREEN_SIZE) == 0 || f.greenBufferSize() != -1)
- props.setValue(EGL_GREEN_SIZE, f.greenBufferSize() == -1 ? 1 : f.greenBufferSize());
- if (props.value(EGL_BLUE_SIZE) == 0 || f.blueBufferSize() != -1)
- props.setValue(EGL_BLUE_SIZE, f.blueBufferSize() == -1 ? 1 : f.blueBufferSize());
- if (f.alpha()) {
- if (props.value(EGL_ALPHA_SIZE) == 0 || f.alphaBufferSize() != -1)
- props.setValue(EGL_ALPHA_SIZE, f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize());
- }
+ int redSize = glFormat.redBufferSize();
+ int greenSize = glFormat.greenBufferSize();
+ int blueSize = glFormat.blueBufferSize();
+ int alphaSize = glFormat.alphaBufferSize();
+ int depthSize = glFormat.depthBufferSize();
+ int stencilSize = glFormat.stencilBufferSize();
+ int sampleCount = glFormat.samples();
- if (f.depth())
- props.setValue(EGL_DEPTH_SIZE, f.depthBufferSize() == -1 ? 1 : f.depthBufferSize());
- if (f.stencil())
- props.setValue(EGL_STENCIL_SIZE, f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize());
- if (f.sampleBuffers()) {
- props.setValue(EGL_SAMPLE_BUFFERS, 1);
- props.setValue(EGL_SAMPLES, f.samples() == -1 ? 1 : f.samples());
- } else {
- props.setValue(EGL_SAMPLE_BUFFERS, 0);
+ // QGLFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that
+ // type has been requested. So we must check QGLFormat's booleans too if size is -1:
+ if (glFormat.alpha() && alphaSize <= 0) {
+ qDebug("QGLFormat::alpha() returned true");
+ alphaSize = 1;
}
- if (deviceType == QInternal::Widget)
- props.setValue(EGL_LEVEL, f.plane());
+ if (glFormat.depth() && depthSize <= 0)
+ depthSize = 1;
+ if (glFormat.stencil() && stencilSize <= 0)
+ stencilSize = 1;
+ if (glFormat.sampleBuffers() && sampleCount <= 0)
+ sampleCount = 1;
+
+ // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide
+ // the best performance. The EGL config selection algorithm is a bit stange in this regard:
+ // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard
+ // 32-bit configs completely from the selection. So it then comes to the sorting algorithm.
+ // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort
+ // order is special and described as "by larger _total_ number of color bits.". So EGL will
+ // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on
+ // to say "If the requested number of bits in attrib_list for a particular component is 0,
+ // then the number of bits for that component is not considered". This part of the spec also
+ // seems to imply that setting the red/green/blue bits to zero means none of the components
+ // are considered and EGL disregards the entire sorting rule. It then looks to the next
+ // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being
+ // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are
+ // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit,
+ // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that
+ // if the application sets the red/green/blue size to 5/6/5 on the QGLFormat, they will
+ // probably get a 32-bit config, even when there's an RGB565 config avaliable. Oh well.
+
+ // Now normalize the values so -1 becomes 0
+ redSize = redSize > 0 ? redSize : 0;
+ greenSize = greenSize > 0 ? greenSize : 0;
+ blueSize = blueSize > 0 ? blueSize : 0;
+ alphaSize = alphaSize > 0 ? alphaSize : 0;
+ depthSize = depthSize > 0 ? depthSize : 0;
+ stencilSize = stencilSize > 0 ? stencilSize : 0;
+ sampleCount = sampleCount > 0 ? sampleCount : 0;
+
+ eglProperties.setValue(EGL_RED_SIZE, redSize);
+ eglProperties.setValue(EGL_GREEN_SIZE, greenSize);
+ eglProperties.setValue(EGL_BLUE_SIZE, blueSize);
+ eglProperties.setValue(EGL_ALPHA_SIZE, alphaSize);
+ eglProperties.setValue(EGL_DEPTH_SIZE, depthSize);
+ eglProperties.setValue(EGL_STENCIL_SIZE, stencilSize);
+ eglProperties.setValue(EGL_SAMPLES, sampleCount);
+ eglProperties.setValue(EGL_SAMPLE_BUFFERS, sampleCount ? 1 : 0);
}
+
// Updates "format" with the parameters of the selected configuration.
void qt_egl_update_format(const QEglContext& context, QGLFormat& format)
{
@@ -126,7 +155,7 @@ void qt_egl_update_format(const QEglContext& context, QGLFormat& format)
// Clear the EGL error state because some of the above may
// have errored out because the attribute is not applicable
// to the surface type. Such errors don't matter.
- context.clearError();
+ QEgl::clearError();
}
bool QGLFormat::hasOpenGL()
@@ -158,12 +187,12 @@ void QGLContext::reset()
void QGLContext::makeCurrent()
{
Q_D(QGLContext);
- if (!d->valid || !d->eglContext || d->eglSurface == EGL_NO_SURFACE) {
+ if (!d->valid || !d->eglContext || d->eglSurfaceForDevice() == EGL_NO_SURFACE) {
qWarning("QGLContext::makeCurrent(): Cannot make invalid context current");
return;
}
- if (d->eglContext->makeCurrent(d->eglSurface))
+ if (d->eglContext->makeCurrent(d->eglSurfaceForDevice()))
QGLContextPrivate::setCurrentContext(this);
}
@@ -183,7 +212,7 @@ void QGLContext::swapBuffers() const
if (!d->valid || !d->eglContext)
return;
- d->eglContext->swapBuffers(d->eglSurface);
+ d->eglContext->swapBuffers(d->eglSurfaceForDevice());
}
void QGLContextPrivate::destroyEglSurfaceForDevice()
@@ -206,6 +235,30 @@ void QGLContextPrivate::destroyEglSurfaceForDevice()
}
}
+EGLSurface QGLContextPrivate::eglSurfaceForDevice() const
+{
+ // If a QPixmapData had to create the QGLContext, we don't have a paintDevice
+ if (!paintDevice)
+ return eglSurface;
+
+#ifdef Q_WS_X11
+ if (paintDevice->devType() == QInternal::Pixmap) {
+ QPixmapData *pmd = static_cast<QPixmap*>(paintDevice)->data_ptr().data();
+ if (pmd->classId() == QPixmapData::X11Class) {
+ QX11PixmapData* x11PixmapData = static_cast<QX11PixmapData*>(pmd);
+ return (EGLSurface)x11PixmapData->gl_surface;
+ }
+ }
+#endif
+
+ if (paintDevice->devType() == QInternal::Pbuffer) {
+ QGLPixelBuffer* pbuf = static_cast<QGLPixelBuffer*>(paintDevice);
+ return pbuf->d_func()->pbuf;
+ }
+
+ return eglSurface;
+}
+
void QGLWidget::setMouseTracking(bool enable)
{
QWidget::setMouseTracking(enable);