diff options
author | Laszlo Agocs <laszlo.agocs@digia.com> | 2014-01-27 14:45:11 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-14 10:51:44 +0100 |
commit | 97c187da3c1381bc55dd16976bf9fb3c773d0047 (patch) | |
tree | a101467c838879b025bdfb4b5f7b18a6ad8b3033 /src/opengl | |
parent | f25aca5c658b018e3b510990d82e7195d0c3b7c0 (diff) |
Dynamic GL switch on Windows
The patch introduces a new build configuration on Windows which
can be requested by passing -opengl dynamic to configure.
Platforms other than Windows (including WinRT) are not affected.
The existing Angle and desktop configurations are not affected.
These continue to function as before and Angle remains the default.
In the future, when all modules have added support for the dynamic
path, as described below, the default configuration could be changed
to be the dynamic one. This would allow providing a single set of
binaries in the official builds instead of the current two.
When requesting dynamic GL, Angle is built but QT_OPENGL_ES[_2] are
never defined. Instead, the code path that has traditionally been
desktop GL only becomes the dynamic path that has to do runtime
checks. Qt modules and applications are not linked to opengl32.dll or
libegl/glesv2.dll in this case. Instead, QtGui exports all necessary
egl/egl/gl functions which will, under the hood, forward all requests
to a dynamically loaded EGL/WGL/GL implementation.
Porting guide (better said, changes needed to prepare your code to
work with dynamic GL builds when the fallback to Angle is utilized):
1. In !QT_OPENGL_ES[_2] code branches use QOpenGLFunctions::isES() to
differentiate between desktop and ES where needed. Keep in mind that
it is the desktop GL header (plus qopenglext.h) that is included,
not the GLES one.
QtGui's proxy will handle some differences, for example calling
glClearDepth will route to glClearDepthf when needed. The built-in
eglGetProcAddress is able to retrieve pointers for standard GLES2
functions too so code resolving OpenGL 2 functions will function
in any case.
2. QT_CONFIG will contain "opengl" and "dynamicgl" in dynamic builds,
but never "angle" or "opengles2".
3. The preprocessor define QT_OPENGL_DYNAMIC is also available in
dynamic builds. The usage of this is strongly discouraged and should
not be needed anywhere except for QtGui and the platform plugin.
4. Code in need of the library handle can use
QOpenGLFunctions::platformGLHandle().
The decision on which library to load is currently based on a simple
test that creates a dummy window/context and tries to resolve an
OpenGL 2 function. If this fails, it goes for Angle. This seems to work
well on Win7 PCs for example that do not have proper graphics drivers
providing OpenGL installed but are D3D9 capable using the default drivers.
Setting QT_OPENGL to desktop or angle skips the test and forces
usage of the given GL. There are also two new application attributes
that could be used for the same purpose.
If Angle is requested but the libraries are not present, desktop is
tried. If desktop is requested, or if angle is requested but nothing
works, the EGL/WGL functions will still be callable but will return 0.
This conveniently means that eglInitialize() and such will report a failure.
Debug messages can be enabled by setting QT_OPENGLPROXY_DEBUG. This will
tell which implementation is chosen.
The textures example application is ported to OpenGL 2, the GL 1
code path is removed.
[ChangeLog][QtGui] Qt builds on Windows can now be configured for
dynamic loading of the OpenGL implementation. This can be requested
by passing -opengl dynamic to configure. In this mode no modules will
link to opengl32.dll or Angle's libegl/libglesv2. Instead, QtGui will
dynamically choose between desktop and Angle during the first GL/EGL/WGL
call. This allows deploying applications with a single set of Qt libraries
with the ability of transparently falling back to Angle in case the
opengl32.dll is not suitable, due to missing graphics drivers for example.
Task-number: QTBUG-36483
Change-Id: I716fdebbf60b355b7d9ef57d1e069eef366b4ab9
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/gl2paintengineex/qglengineshadermanager.cpp | 5 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qglengineshadersource_p.h | 8 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 88 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp | 21 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 466 | ||||
-rw-r--r-- | src/opengl/qgl_qpa.cpp | 26 | ||||
-rw-r--r-- | src/opengl/qglbuffer.cpp | 16 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject.cpp | 83 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject.h | 12 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject_p.h | 12 | ||||
-rw-r--r-- | src/opengl/qglfunctions.cpp | 174 | ||||
-rw-r--r-- | src/opengl/qglfunctions.h | 1 | ||||
-rw-r--r-- | src/opengl/qglpixelbuffer.cpp | 9 | ||||
-rw-r--r-- | src/opengl/qglshaderprogram.cpp | 33 |
14 files changed, 518 insertions, 436 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index a89d37bc5d..394eb99307 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -163,7 +163,10 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader; code[CustomImageSrcFragmentShader] = qglslCustomSrcFragmentShader; // Calls "customShader", which must be appended code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader; - code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader; + if (!QOpenGLFunctions::isES()) + code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader_desktop; + else + code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader_ES; code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader; code[PatternBrushSrcFragmentShader] = qglslPatternBrushSrcFragmentShader; code[LinearGradientBrushSrcFragmentShader] = qglslLinearGradientBrushSrcFragmentShader; diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index 05d923ca17..90bd7edf54 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -305,25 +305,23 @@ static const char* const qglslPositionWithTextureBrushVertexShader = "\n\ static const char* const qglslAffinePositionWithTextureBrushVertexShader = qglslPositionWithTextureBrushVertexShader; -#if defined(QT_OPENGL_ES_2) // OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead, // we emulate GL_REPEAT by only taking the fractional part of the texture coords. // TODO: Special case POT textures which don't need this emulation -static const char* const qglslTextureBrushSrcFragmentShader = "\n\ +static const char* const qglslTextureBrushSrcFragmentShader_ES = "\n\ varying highp vec2 brushTextureCoords; \n\ uniform sampler2D brushTexture; \n\ lowp vec4 srcPixel() { \n\ return texture2D(brushTexture, fract(brushTextureCoords)); \n\ }\n"; -#else -static const char* const qglslTextureBrushSrcFragmentShader = "\n\ + +static const char* const qglslTextureBrushSrcFragmentShader_desktop = "\n\ varying highp vec2 brushTextureCoords; \n\ uniform sampler2D brushTexture; \n\ lowp vec4 srcPixel() \n\ { \n\ return texture2D(brushTexture, brushTextureCoords); \n\ }\n"; -#endif static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\n\ varying highp vec2 brushTextureCoords; \n\ diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 3b29923586..32dd7be7ba 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -539,33 +539,35 @@ void QGL2PaintEngineEx::beginNativePainting() d->funcs.glDisableVertexAttribArray(i); #ifndef QT_OPENGL_ES_2 - const QGLContext *ctx = d->ctx; - const QGLFormat &fmt = d->device->format(); - if (fmt.majorVersion() < 3 || (fmt.majorVersion() == 3 && fmt.minorVersion() < 1) - || (fmt.majorVersion() == 3 && fmt.minorVersion() == 1 && ctx->contextHandle()->hasExtension(QByteArrayLiteral("GL_ARB_compatibility"))) - || fmt.profile() == QGLFormat::CompatibilityProfile) - { - // be nice to people who mix OpenGL 1.x code with QPainter commands - // by setting modelview and projection matrices to mirror the GL 1 - // paint engine - const QTransform& mtx = state()->matrix; - - float mv_matrix[4][4] = + if (!QOpenGLFunctions::isES()) { + const QGLContext *ctx = d->ctx; + const QGLFormat &fmt = d->device->format(); + if (fmt.majorVersion() < 3 || (fmt.majorVersion() == 3 && fmt.minorVersion() < 1) + || (fmt.majorVersion() == 3 && fmt.minorVersion() == 1 && ctx->contextHandle()->hasExtension(QByteArrayLiteral("GL_ARB_compatibility"))) + || fmt.profile() == QGLFormat::CompatibilityProfile) { - { float(mtx.m11()), float(mtx.m12()), 0, float(mtx.m13()) }, - { float(mtx.m21()), float(mtx.m22()), 0, float(mtx.m23()) }, - { 0, 0, 1, 0 }, - { float(mtx.dx()), float(mtx.dy()), 0, float(mtx.m33()) } - }; - - const QSize sz = d->device->size(); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999); - - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(&mv_matrix[0][0]); + // be nice to people who mix OpenGL 1.x code with QPainter commands + // by setting modelview and projection matrices to mirror the GL 1 + // paint engine + const QTransform& mtx = state()->matrix; + + float mv_matrix[4][4] = + { + { float(mtx.m11()), float(mtx.m12()), 0, float(mtx.m13()) }, + { float(mtx.m21()), float(mtx.m22()), 0, float(mtx.m23()) }, + { 0, 0, 1, 0 }, + { float(mtx.dx()), float(mtx.dy()), 0, float(mtx.m33()) } + }; + + const QSize sz = d->device->size(); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(&mv_matrix[0][0]); + } } #endif @@ -595,9 +597,11 @@ void QGL2PaintEngineExPrivate::resetGLState() ctx->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, false); ctx->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false); #ifndef QT_OPENGL_ES_2 - // gl_Color, corresponding to vertex attribute 3, may have been changed - float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; - funcs.glVertexAttrib4fv(3, color); + if (!QOpenGLFunctions::isES()) { + // gl_Color, corresponding to vertex attribute 3, may have been changed + float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + funcs.glVertexAttrib4fv(3, color); + } #endif } @@ -1352,11 +1356,13 @@ void QGL2PaintEngineEx::renderHintsChanged() state()->renderHintsChanged = true; #if !defined(QT_OPENGL_ES_2) - if ((state()->renderHints & QPainter::Antialiasing) - || (state()->renderHints & QPainter::HighQualityAntialiasing)) - glEnable(GL_MULTISAMPLE); - else - glDisable(GL_MULTISAMPLE); + if (!QOpenGLFunctions::isES()) { + if ((state()->renderHints & QPainter::Antialiasing) + || (state()->renderHints & QPainter::HighQualityAntialiasing)) + glEnable(GL_MULTISAMPLE); + else + glDisable(GL_MULTISAMPLE); + } #endif Q_D(QGL2PaintEngineEx); @@ -2027,21 +2033,23 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) glDisable(GL_SCISSOR_TEST); #if !defined(QT_OPENGL_ES_2) - glDisable(GL_MULTISAMPLE); + if (!QOpenGLFunctions::isES()) + glDisable(GL_MULTISAMPLE); #endif d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; #if !defined(QT_OPENGL_ES_2) + if (!QOpenGLFunctions::isES()) { d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask; -#endif - -#if defined(QT_OPENGL_ES_2) + d->multisamplingAlwaysEnabled = false; + } else { + d->multisamplingAlwaysEnabled = d->device->format().sampleBuffers(); + } +#else // OpenGL ES can't switch MSAA off, so if the gl paint device is // multisampled, it's always multisampled. d->multisamplingAlwaysEnabled = d->device->format().sampleBuffers(); -#else - d->multisamplingAlwaysEnabled = false; #endif return true; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index d96ab36e2b..d506b7e4b9 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -319,23 +319,24 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub uchar g = src[x] >> 8; uchar b = src[x]; quint32 avg = (quint32(r) + quint32(g) + quint32(b) + 1) / 3; // "+1" for rounding. -#if defined(QT_OPENGL_ES_2) - // swizzle the bits to accommodate for the GL_RGBA upload. - src[x] = (avg << 24) | (quint32(r) << 0) | (quint32(g) << 8) | (quint32(b) << 16); -#else - src[x] = (src[x] & 0x00ffffff) | (avg << 24); -#endif + if (QOpenGLFunctions::isES()) { + // swizzle the bits to accommodate for the GL_RGBA upload. + src[x] = (avg << 24) | (quint32(r) << 0) | (quint32(g) << 8) | (quint32(b) << 16); + } else { + src[x] = (src[x] & 0x00ffffff) | (avg << 24); + } } } } glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); if (mask.format() == QImage::Format_RGB32) { -#if defined(QT_OPENGL_ES_2) - glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_RGBA, GL_UNSIGNED_BYTE, mask.bits()); -#else - glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits()); + GLenum format = GL_RGBA; +#if !defined(QT_OPENGL_ES_2) + if (!QOpenGLFunctions::isES()) + format = GL_BGRA; #endif + glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, format, GL_UNSIGNED_BYTE, mask.bits()); } else { // glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is // not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 40a8b1921c..e027de02e0 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1699,10 +1699,12 @@ QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alp return QImage(); int w = size.width(); int h = size.height(); -#if !defined(QT_OPENGL_ES_2) - //### glGetTexImage not in GL ES 2.0, need to do something else here! - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); -#endif +#ifndef QT_OPENGL_ES + if (!QOpenGLFunctions::isES()) { + //### glGetTexImage not in GL ES 2.0, need to do something else here! + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); + } +#endif // QT_OPENGL_ES convertFromGLImage(img, w, h, alpha_format, include_alpha); return img; } @@ -2282,17 +2284,20 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G glBindTexture(target, tx_id); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filtering); -#if defined(QT_OPENGL_ES_2) - bool genMipmap = false; -#endif + bool genMipmap = !QOpenGLFunctions::isES(); if (glFormat.directRendering() && (qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::GenerateMipmap)) && target == GL_TEXTURE_2D && (options & QGLContext::MipmapBindOption)) { #if !defined(QT_OPENGL_ES_2) - glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); - glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + if (genMipmap) { + glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); + glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + } else { + glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); + genMipmap = true; + } #else glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); genMipmap = true; @@ -2421,11 +2426,11 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G printf(" - did byte swapping (%d ms)\n", time.elapsed()); #endif } -#ifdef QT_OPENGL_ES - // OpenGL/ES requires that the internal and external formats be - // identical. - internalFormat = externalFormat; -#endif + if (QOpenGLFunctions::isES()) { + // OpenGL/ES requires that the internal and external formats be + // identical. + internalFormat = externalFormat; + } #ifdef QGL_BIND_TEXTURE_DEBUG printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n", img.format(), externalFormat, internalFormat, pixel_type); @@ -2434,10 +2439,8 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G const QImage &constRef = img; // to avoid detach in bits()... glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat, pixel_type, constRef.bits()); -#if defined(QT_OPENGL_ES_2) - if (genMipmap) - glGenerateMipmap(target); -#endif + if (genMipmap && QOpenGLFunctions::isES()) + functions->glGenerateMipmap(target); #ifndef QT_NO_DEBUG GLenum error = glGetError(); if (error != GL_NO_ERROR) { @@ -2518,31 +2521,32 @@ int QGLContextPrivate::maxTextureSize() glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); -#if defined(QT_OPENGL_ES) - return max_texture_size; -#else - GLenum proxy = GL_PROXY_TEXTURE_2D; - - GLint size; - GLint next = 64; - glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size); - if (size == 0) { - return max_texture_size; - } - do { - size = next; - next = size * 2; +#ifndef QT_OPENGL_ES + if (!QOpenGLFunctions::isES()) { + GLenum proxy = GL_PROXY_TEXTURE_2D; - if (next > max_texture_size) - break; + GLint size; + GLint next = 64; glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next); - } while (next > size); + glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size); + if (size == 0) { + return max_texture_size; + } + do { + size = next; + next = size * 2; - max_texture_size = size; - return max_texture_size; + if (next > max_texture_size) + break; + glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next); + } while (next > size); + + max_texture_size = size; + } #endif + + return max_texture_size; } /*! @@ -2696,7 +2700,7 @@ static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint tex Q_UNUSED(textureHeight); Q_UNUSED(textureTarget); #else - if (textureTarget != GL_TEXTURE_2D) { + if (textureTarget != GL_TEXTURE_2D && !QOpenGLFunctions::isES()) { if (textureWidth == -1 || textureHeight == -1) { glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth); glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight); @@ -2763,35 +2767,38 @@ void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum text #endif #ifndef QT_OPENGL_ES_2 + if (!QOpenGLFunctions::isES()) { #ifdef QT_OPENGL_ES - if (textureTarget != GL_TEXTURE_2D) { - qWarning("QGLContext::drawTexture(): texture target must be GL_TEXTURE_2D on OpenGL ES"); - return; - } + if (textureTarget != GL_TEXTURE_2D) { + qWarning("QGLContext::drawTexture(): texture target must be GL_TEXTURE_2D on OpenGL ES"); + return; + } #else - const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D); - GLint oldTexture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture); + const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D); + GLint oldTexture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture); #endif - glEnable(textureTarget); - glBindTexture(textureTarget, textureId); + glEnable(textureTarget); + glBindTexture(textureTarget, textureId); - qDrawTextureRect(target, -1, -1, textureTarget); + qDrawTextureRect(target, -1, -1, textureTarget); #ifdef QT_OPENGL_ES - glDisable(textureTarget); -#else - if (!wasEnabled) glDisable(textureTarget); - glBindTexture(textureTarget, oldTexture); +#else + if (!wasEnabled) + glDisable(textureTarget); + glBindTexture(textureTarget, oldTexture); #endif + return; + } #else Q_UNUSED(target); Q_UNUSED(textureId); Q_UNUSED(textureTarget); - qWarning("drawTexture() with OpenGL ES 2.0 requires an active OpenGL2 paint engine"); #endif + qWarning("drawTexture() with OpenGL ES 2.0 requires an active OpenGL2 paint engine"); } /*! @@ -2821,40 +2828,42 @@ void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum text Q_UNUSED(point); Q_UNUSED(textureId); Q_UNUSED(textureTarget); - qWarning("drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES, use rect version instead"); #else - - const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D); - GLint oldTexture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture); - - glEnable(textureTarget); - glBindTexture(textureTarget, textureId); - - GLint textureWidth; - GLint textureHeight; - - glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth); - glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight); - - if (d_ptr->active_engine && - d_ptr->active_engine->type() == QPaintEngine::OpenGL2) { - QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine); - if (!eng->isNativePaintingActive()) { - QRectF dest(point, QSizeF(textureWidth, textureHeight)); - QRectF src(0, 0, textureWidth, textureHeight); - QSize size(textureWidth, textureHeight); - if (eng->drawTexture(dest, textureId, size, src)) - return; + if (!QOpenGLFunctions::isES()) { + const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D); + GLint oldTexture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture); + + glEnable(textureTarget); + glBindTexture(textureTarget, textureId); + + GLint textureWidth; + GLint textureHeight; + + glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth); + glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight); + + if (d_ptr->active_engine && + d_ptr->active_engine->type() == QPaintEngine::OpenGL2) { + QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine); + if (!eng->isNativePaintingActive()) { + QRectF dest(point, QSizeF(textureWidth, textureHeight)); + QRectF src(0, 0, textureWidth, textureHeight); + QSize size(textureWidth, textureHeight); + if (eng->drawTexture(dest, textureId, size, src)) + return; + } } - } - qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget); + qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget); - if (!wasEnabled) - glDisable(textureTarget); - glBindTexture(textureTarget, oldTexture); + if (!wasEnabled) + glDisable(textureTarget); + glBindTexture(textureTarget, oldTexture); + return; + } #endif + qWarning("drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES, use rect version instead"); } /*! @@ -4163,7 +4172,7 @@ void QGLWidget::glDraw() return; makeCurrent(); #ifndef QT_OPENGL_ES - if (d->glcx->deviceIsPixmap()) + if (d->glcx->deviceIsPixmap() && !QOpenGLFunctions::isES()) glDrawBuffer(GL_FRONT); #endif QSize readback_target_size = d->glcx->d_ptr->readback_target_size; @@ -4206,18 +4215,20 @@ void QGLWidget::qglColor(const QColor& c) const #ifdef QT_OPENGL_ES glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); #else - Q_D(const QGLWidget); - const QGLContext *ctx = QGLContext::currentContext(); - if (ctx) { - if (ctx->format().rgba()) - glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); - else if (!d->cmap.isEmpty()) { // QGLColormap in use? - int i = d->cmap.find(c.rgb()); - if (i < 0) - i = d->cmap.findNearest(c.rgb()); - glIndexi(i); - } else - glIndexi(ctx->colorIndex(c)); + if (!QOpenGLFunctions::isES()) { + Q_D(const QGLWidget); + const QGLContext *ctx = QGLContext::currentContext(); + if (ctx) { + if (ctx->format().rgba()) + glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + else if (!d->cmap.isEmpty()) { // QGLColormap in use? + int i = d->cmap.find(c.rgb()); + if (i < 0) + i = d->cmap.findNearest(c.rgb()); + glIndexi(i); + } else + glIndexi(ctx->colorIndex(c)); + } } #endif //QT_OPENGL_ES #else @@ -4238,18 +4249,23 @@ void QGLWidget::qglClearColor(const QColor& c) const #ifdef QT_OPENGL_ES glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); #else - Q_D(const QGLWidget); - const QGLContext *ctx = QGLContext::currentContext(); - if (ctx) { - if (ctx->format().rgba()) - glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); - else if (!d->cmap.isEmpty()) { // QGLColormap in use? - int i = d->cmap.find(c.rgb()); - if (i < 0) - i = d->cmap.findNearest(c.rgb()); - glClearIndex(i); - } else - glClearIndex(ctx->colorIndex(c)); + if (!QOpenGLFunctions::isES()) { + Q_D(const QGLWidget); + const QGLContext *ctx = QGLContext::currentContext(); + if (ctx) { + if (ctx->format().rgba()) + glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + else if (!d->cmap.isEmpty()) { // QGLColormap in use? + int i = d->cmap.find(c.rgb()); + if (i < 0) + i = d->cmap.findNearest(c.rgb()); + glClearIndex(i); + } else { + glClearIndex(ctx->colorIndex(c)); + } + } + } else { + glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); } #endif } @@ -4411,72 +4427,75 @@ static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str, void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font) { #ifndef QT_OPENGL_ES - Q_D(QGLWidget); - if (str.isEmpty() || !isValid()) - return; - - GLint view[4]; - bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); - if (!use_scissor_testing) - glGetIntegerv(GL_VIEWPORT, &view[0]); - int width = d->glcx->device()->width(); - int height = d->glcx->device()->height(); - bool auto_swap = autoBufferSwap(); - - QPaintEngine *engine = paintEngine(); - - qt_save_gl_state(); - - QPainter *p; - bool reuse_painter = false; - if (engine->isActive()) { - reuse_painter = true; - p = engine->painter(); + if (!QOpenGLFunctions::isES()) { + Q_D(QGLWidget); + if (str.isEmpty() || !isValid()) + return; + + GLint view[4]; + bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); + if (!use_scissor_testing) + glGetIntegerv(GL_VIEWPORT, &view[0]); + int width = d->glcx->device()->width(); + int height = d->glcx->device()->height(); + bool auto_swap = autoBufferSwap(); + + QPaintEngine *engine = paintEngine(); + + qt_save_gl_state(); + + QPainter *p; + bool reuse_painter = false; + if (engine->isActive()) { + reuse_painter = true; + p = engine->painter(); + + glDisable(GL_DEPTH_TEST); + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, height, 0, 0, 1); + glMatrixMode(GL_MODELVIEW); + + glLoadIdentity(); + } else { + setAutoBufferSwap(false); + // disable glClear() as a result of QPainter::begin() + d->disable_clear_on_painter_begin = true; + p = new QPainter(this); + } - glDisable(GL_DEPTH_TEST); - glViewport(0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, height, 0, 0, 1); - glMatrixMode(GL_MODELVIEW); + QRect viewport(view[0], view[1], view[2], view[3]); + if (!use_scissor_testing && viewport != rect()) { + // if the user hasn't set a scissor box, we set one that + // covers the current viewport + glScissor(view[0], view[1], view[2], view[3]); + glEnable(GL_SCISSOR_TEST); + } else if (use_scissor_testing) { + // use the scissor box set by the user + glEnable(GL_SCISSOR_TEST); + } - glLoadIdentity(); - } else { - setAutoBufferSwap(false); - // disable glClear() as a result of QPainter::begin() - d->disable_clear_on_painter_begin = true; - p = new QPainter(this); - } + qt_gl_draw_text(p, x, y, str, font); - QRect viewport(view[0], view[1], view[2], view[3]); - if (!use_scissor_testing && viewport != rect()) { - // if the user hasn't set a scissor box, we set one that - // covers the current viewport - glScissor(view[0], view[1], view[2], view[3]); - glEnable(GL_SCISSOR_TEST); - } else if (use_scissor_testing) { - // use the scissor box set by the user - glEnable(GL_SCISSOR_TEST); - } + if (!reuse_painter) { + p->end(); + delete p; + setAutoBufferSwap(auto_swap); + d->disable_clear_on_painter_begin = false; + } - qt_gl_draw_text(p, x, y, str, font); + qt_restore_gl_state(); - if (!reuse_painter) { - p->end(); - delete p; - setAutoBufferSwap(auto_swap); - d->disable_clear_on_painter_begin = false; + return; } - - qt_restore_gl_state(); - #else // QT_OPENGL_ES Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(str); Q_UNUSED(font); - qWarning("QGLWidget::renderText is not supported under OpenGL/ES"); #endif + qWarning("QGLWidget::renderText is not supported under OpenGL/ES"); } /*! \overload @@ -4503,80 +4522,83 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font) void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font) { #ifndef QT_OPENGL_ES - Q_D(QGLWidget); - if (str.isEmpty() || !isValid()) - return; + if (!QOpenGLFunctions::isES()) { + Q_D(QGLWidget); + if (str.isEmpty() || !isValid()) + return; + + bool auto_swap = autoBufferSwap(); + + int width = d->glcx->device()->width(); + int height = d->glcx->device()->height(); + GLdouble model[4 * 4], proj[4 * 4]; + GLint view[4]; + glGetDoublev(GL_MODELVIEW_MATRIX, &model[0]); + glGetDoublev(GL_PROJECTION_MATRIX, &proj[0]); + glGetIntegerv(GL_VIEWPORT, &view[0]); + GLdouble win_x = 0, win_y = 0, win_z = 0; + qgluProject(x, y, z, &model[0], &proj[0], &view[0], + &win_x, &win_y, &win_z); + win_y = height - win_y; // y is inverted - bool auto_swap = autoBufferSwap(); + QPaintEngine *engine = paintEngine(); - int width = d->glcx->device()->width(); - int height = d->glcx->device()->height(); - GLdouble model[4 * 4], proj[4 * 4]; - GLint view[4]; - glGetDoublev(GL_MODELVIEW_MATRIX, &model[0]); - glGetDoublev(GL_PROJECTION_MATRIX, &proj[0]); - glGetIntegerv(GL_VIEWPORT, &view[0]); - GLdouble win_x = 0, win_y = 0, win_z = 0; - qgluProject(x, y, z, &model[0], &proj[0], &view[0], - &win_x, &win_y, &win_z); - win_y = height - win_y; // y is inverted + QPainter *p; + bool reuse_painter = false; + bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST); + bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); - QPaintEngine *engine = paintEngine(); + qt_save_gl_state(); - QPainter *p; - bool reuse_painter = false; - bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST); - bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); + if (engine->isActive()) { + reuse_painter = true; + p = engine->painter(); + } else { + setAutoBufferSwap(false); + // disable glClear() as a result of QPainter::begin() + d->disable_clear_on_painter_begin = true; + p = new QPainter(this); + } - qt_save_gl_state(); + QRect viewport(view[0], view[1], view[2], view[3]); + if (!use_scissor_testing && viewport != rect()) { + glScissor(view[0], view[1], view[2], view[3]); + glEnable(GL_SCISSOR_TEST); + } else if (use_scissor_testing) { + glEnable(GL_SCISSOR_TEST); + } + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glViewport(0, 0, width, height); + glOrtho(0, width, height, 0, 0, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glAlphaFunc(GL_GREATER, 0.0); + glEnable(GL_ALPHA_TEST); + if (use_depth_testing) + glEnable(GL_DEPTH_TEST); + glTranslated(0, 0, -win_z); + qt_gl_draw_text(p, qRound(win_x), qRound(win_y), str, font); + + if (!reuse_painter) { + p->end(); + delete p; + setAutoBufferSwap(auto_swap); + d->disable_clear_on_painter_begin = false; + } - if (engine->isActive()) { - reuse_painter = true; - p = engine->painter(); - } else { - setAutoBufferSwap(false); - // disable glClear() as a result of QPainter::begin() - d->disable_clear_on_painter_begin = true; - p = new QPainter(this); - } + qt_restore_gl_state(); - QRect viewport(view[0], view[1], view[2], view[3]); - if (!use_scissor_testing && viewport != rect()) { - glScissor(view[0], view[1], view[2], view[3]); - glEnable(GL_SCISSOR_TEST); - } else if (use_scissor_testing) { - glEnable(GL_SCISSOR_TEST); - } - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glViewport(0, 0, width, height); - glOrtho(0, width, height, 0, 0, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glAlphaFunc(GL_GREATER, 0.0); - glEnable(GL_ALPHA_TEST); - if (use_depth_testing) - glEnable(GL_DEPTH_TEST); - glTranslated(0, 0, -win_z); - qt_gl_draw_text(p, qRound(win_x), qRound(win_y), str, font); - - if (!reuse_painter) { - p->end(); - delete p; - setAutoBufferSwap(auto_swap); - d->disable_clear_on_painter_begin = false; + return; } - - qt_restore_gl_state(); - #else // QT_OPENGL_ES Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(z); Q_UNUSED(str); Q_UNUSED(font); - qWarning("QGLWidget::renderText is not supported under OpenGL/ES"); #endif + qWarning("QGLWidget::renderText is not supported under OpenGL/ES"); } QGLFormat QGLWidget::format() const diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp index 8b66c891bb..4f4df8d2e4 100644 --- a/src/opengl/qgl_qpa.cpp +++ b/src/opengl/qgl_qpa.cpp @@ -321,21 +321,23 @@ QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) d->context = new QOpenGLContext; #if !defined(QT_OPENGL_ES) - // On desktop, request latest released version - QSurfaceFormat format; + if (!QOpenGLFunctions::isES()) { + // On desktop, request latest released version + QSurfaceFormat format; #if defined(Q_OS_MAC) - // OS X is limited to OpenGL 3.2 Core Profile at present - // so set that here. If we use compatibility profile it - // only reports 2.x contexts. - format.setMajorVersion(3); - format.setMinorVersion(2); - format.setProfile(QSurfaceFormat::CoreProfile); + // OS X is limited to OpenGL 3.2 Core Profile at present + // so set that here. If we use compatibility profile it + // only reports 2.x contexts. + format.setMajorVersion(3); + format.setMinorVersion(2); + format.setProfile(QSurfaceFormat::CoreProfile); #else - format.setMajorVersion(4); - format.setMinorVersion(3); -#endif - d->context->setFormat(format); + format.setMajorVersion(4); + format.setMinorVersion(3); #endif + d->context->setFormat(format); + } +#endif // QT_OPENGL_ES d->context->create(); d->context->makeCurrent(d->window); } diff --git a/src/opengl/qglbuffer.cpp b/src/opengl/qglbuffer.cpp index 1c9545990f..5491bad628 100644 --- a/src/opengl/qglbuffer.cpp +++ b/src/opengl/qglbuffer.cpp @@ -344,18 +344,20 @@ void QGLBuffer::destroy() bool QGLBuffer::read(int offset, void *data, int count) { #if !defined(QT_OPENGL_ES) - Q_D(QGLBuffer); - if (!d->funcs->hasOpenGLFeature(QOpenGLFunctions::Buffers) || !d->guard->id()) - return false; - while (glGetError() != GL_NO_ERROR) ; // Clear error state. - d->funcs->glGetBufferSubData(d->type, offset, count, data); - return glGetError() == GL_NO_ERROR; + if (QOpenGLFunctions::platformGLType() != QOpenGLFunctions::GLES1) { + Q_D(QGLBuffer); + if (!d->funcs->hasOpenGLFeature(QOpenGLFunctions::Buffers) || !d->guard->id()) + return false; + while (glGetError() != GL_NO_ERROR) ; // Clear error state. + d->funcs->glGetBufferSubData(d->type, offset, count, data); + return glGetError() == GL_NO_ERROR; + } #else Q_UNUSED(offset); Q_UNUSED(data); Q_UNUSED(count); - return false; #endif + return false; } /*! diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 66e1aca9bc..b4821ccf61 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -373,8 +373,11 @@ void QGLFBOGLPaintDevice::setFBO(QGLFramebufferObject* f, GLenum format = f->format().internalTextureFormat(); reqAlpha = (format != GL_RGB -#ifndef QT_OPENGL_ES - && format != GL_RGB5 && format != GL_RGB8 +#ifdef GL_RGB5 + && format != GL_RGB5 +#endif +#ifdef GL_RGB8 + && format != GL_RGB8 #endif ); } @@ -592,8 +595,17 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, GL_DEPTH_COMPONENT16, size.width(), size.height()); } #else - funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, - GL_DEPTH_COMPONENT, size.width(), size.height()); + if (QOpenGLFunctions::isES()) { + if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) + funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, + GL_DEPTH_COMPONENT24, size.width(), size.height()); + else + funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, + GL_DEPTH_COMPONENT16, size.width(), size.height()); + } else { + funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, + GL_DEPTH_COMPONENT, size.width(), size.height()); + } #endif } else { #ifdef QT_OPENGL_ES @@ -605,7 +617,17 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, size.width(), size.height()); } #else - funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.width(), size.height()); + if (QOpenGLFunctions::isES()) { + if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) { + funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, + size.width(), size.height()); + } else { + funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, + size.width(), size.height()); + } + } else { + funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.width(), size.height()); + } #endif } funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, @@ -621,23 +643,18 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, funcs.glGenRenderbuffers(1, &stencil_buffer); funcs.glBindRenderbuffer(GL_RENDERBUFFER, stencil_buffer); Q_ASSERT(funcs.glIsRenderbuffer(stencil_buffer)); - if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) { -#ifdef QT_OPENGL_ES - funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, - GL_STENCIL_INDEX8, size.width(), size.height()); -#else - funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, - GL_STENCIL_INDEX, size.width(), size.height()); -#endif - } else { + #ifdef QT_OPENGL_ES - funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, - size.width(), size.height()); + GLenum storage = GL_STENCIL_INDEX8; #else - funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX, - size.width(), size.height()); + GLenum storage = QOpenGLFunctions::isES() ? GL_STENCIL_INDEX8 : GL_STENCIL_INDEX; #endif - } + + if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) + funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, storage, size.width(), size.height()); + else + funcs.glRenderbufferStorage(GL_RENDERBUFFER, storage, size.width(), size.height()); + funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencil_buffer); valid = checkFramebufferStatus(); @@ -830,7 +847,13 @@ QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target) : d_ptr(new QGLFramebufferObjectPrivate) { Q_D(QGLFramebufferObject); - d->init(this, size, NoAttachment, target, DEFAULT_FORMAT); + d->init(this, size, NoAttachment, target, +#ifndef QT_OPENGL_ES_2 + QOpenGLFunctions::isES() ? GL_RGBA : GL_RGBA8 +#else + GL_RGBA +#endif + ); } /*! \overload @@ -844,7 +867,13 @@ QGLFramebufferObject::QGLFramebufferObject(int width, int height, GLenum target) : d_ptr(new QGLFramebufferObjectPrivate) { Q_D(QGLFramebufferObject); - d->init(this, QSize(width, height), NoAttachment, target, DEFAULT_FORMAT); + d->init(this, QSize(width, height), NoAttachment, target, +#ifndef QT_OPENGL_ES_2 + QOpenGLFunctions::isES() ? GL_RGBA : GL_RGBA8 +#else + GL_RGBA +#endif + ); } /*! \overload @@ -893,6 +922,12 @@ QGLFramebufferObject::QGLFramebufferObject(int width, int height, Attachment att : d_ptr(new QGLFramebufferObjectPrivate) { Q_D(QGLFramebufferObject); + if (!internal_format) +#ifdef QT_OPENGL_ES_2 + internal_format = GL_RGBA; +#else + internal_format = QOpenGLFunctions::isES() ? GL_RGBA : GL_RGBA8; +#endif d->init(this, QSize(width, height), attachment, target, internal_format); } @@ -914,6 +949,12 @@ QGLFramebufferObject::QGLFramebufferObject(const QSize &size, Attachment attachm : d_ptr(new QGLFramebufferObjectPrivate) { Q_D(QGLFramebufferObject); + if (!internal_format) +#ifdef QT_OPENGL_ES_2 + internal_format = GL_RGBA; +#else + internal_format = QOpenGLFunctions::isES() ? GL_RGBA : GL_RGBA8; +#endif d->init(this, size, attachment, target, internal_format); } diff --git a/src/opengl/qglframebufferobject.h b/src/opengl/qglframebufferobject.h index 9312a23822..affa47cac7 100644 --- a/src/opengl/qglframebufferobject.h +++ b/src/opengl/qglframebufferobject.h @@ -63,17 +63,11 @@ public: QGLFramebufferObject(const QSize &size, GLenum target = GL_TEXTURE_2D); QGLFramebufferObject(int width, int height, GLenum target = GL_TEXTURE_2D); -#if !defined(QT_OPENGL_ES) || defined(Q_QDOC) - QGLFramebufferObject(const QSize &size, Attachment attachment, - GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA8); - QGLFramebufferObject(int width, int height, Attachment attachment, - GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA8); -#else + QGLFramebufferObject(const QSize &size, Attachment attachment, - GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA); + GLenum target = GL_TEXTURE_2D, GLenum internal_format = 0); QGLFramebufferObject(int width, int height, Attachment attachment, - GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA); -#endif + GLenum target = GL_TEXTURE_2D, GLenum internal_format = 0); QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format); QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format); diff --git a/src/opengl/qglframebufferobject_p.h b/src/opengl/qglframebufferobject_p.h index 0f1128e8f6..3b36c5c2b6 100644 --- a/src/opengl/qglframebufferobject_p.h +++ b/src/opengl/qglframebufferobject_p.h @@ -60,12 +60,6 @@ QT_BEGIN_NAMESPACE -#ifndef QT_OPENGL_ES -#define DEFAULT_FORMAT GL_RGBA8 -#else -#define DEFAULT_FORMAT GL_RGBA -#endif - class QGLFramebufferObjectFormatPrivate { public: @@ -74,9 +68,13 @@ public: samples(0), attachment(QGLFramebufferObject::NoAttachment), target(GL_TEXTURE_2D), - internal_format(DEFAULT_FORMAT), mipmap(false) { +#ifndef QT_OPENGL_ES_2 + internal_format = QOpenGLFunctions::isES() ? GL_RGBA : GL_RGBA8; +#else + internal_format = GL_RGBA; +#endif } QGLFramebufferObjectFormatPrivate (const QGLFramebufferObjectFormatPrivate *other) diff --git a/src/opengl/qglfunctions.cpp b/src/opengl/qglfunctions.cpp index 2e8caa30f6..e75f9cf915 100644 --- a/src/opengl/qglfunctions.cpp +++ b/src/opengl/qglfunctions.cpp @@ -213,94 +213,94 @@ QGLFunctions::QGLFunctions(const QGLContext *context) static int qt_gl_resolve_features() { -#if defined(QT_OPENGL_ES_2) - int features = QGLFunctions::Multitexture | - QGLFunctions::Shaders | - QGLFunctions::Buffers | - QGLFunctions::Framebuffers | - QGLFunctions::BlendColor | - QGLFunctions::BlendEquation | - QGLFunctions::BlendEquationSeparate | - QGLFunctions::BlendFuncSeparate | - QGLFunctions::BlendSubtract | - QGLFunctions::CompressedTextures | - QGLFunctions::Multisample | - QGLFunctions::StencilSeparate; - QOpenGLExtensionMatcher extensions; - if (extensions.match("GL_OES_texture_npot")) - features |= QGLFunctions::NPOTTextures; - if (extensions.match("GL_IMG_texture_npot")) - features |= QGLFunctions::NPOTTextures; - return features; -#elif defined(QT_OPENGL_ES) - int features = QGLFunctions::Multitexture | - QGLFunctions::Buffers | - QGLFunctions::CompressedTextures | - QGLFunctions::Multisample; - QOpenGLExtensionMatcher extensions; - if (extensions.match("GL_OES_framebuffer_object")) - features |= QGLFunctions::Framebuffers; - if (extensions.match("GL_OES_blend_equation_separate")) - features |= QGLFunctions::BlendEquationSeparate; - if (extensions.match("GL_OES_blend_func_separate")) - features |= QGLFunctions::BlendFuncSeparate; - if (extensions.match("GL_OES_blend_subtract")) - features |= QGLFunctions::BlendSubtract; - if (extensions.match("GL_OES_texture_npot")) - features |= QGLFunctions::NPOTTextures; - if (extensions.match("GL_IMG_texture_npot")) - features |= QGLFunctions::NPOTTextures; - return features; -#else - int features = 0; - QGLFormat::OpenGLVersionFlags versions = QGLFormat::openGLVersionFlags(); - QOpenGLExtensionMatcher extensions; - - // Recognize features by extension name. - if (extensions.match("GL_ARB_multitexture")) - features |= QGLFunctions::Multitexture; - if (extensions.match("GL_ARB_shader_objects")) - features |= QGLFunctions::Shaders; - if (extensions.match("GL_EXT_framebuffer_object") || + if (QOpenGLFunctions::platformGLType() == QOpenGLFunctions::GLES2) { + int features = QGLFunctions::Multitexture | + QGLFunctions::Shaders | + QGLFunctions::Buffers | + QGLFunctions::Framebuffers | + QGLFunctions::BlendColor | + QGLFunctions::BlendEquation | + QGLFunctions::BlendEquationSeparate | + QGLFunctions::BlendFuncSeparate | + QGLFunctions::BlendSubtract | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample | + QGLFunctions::StencilSeparate; + QOpenGLExtensionMatcher extensions; + if (extensions.match("GL_OES_texture_npot")) + features |= QGLFunctions::NPOTTextures; + if (extensions.match("GL_IMG_texture_npot")) + features |= QGLFunctions::NPOTTextures; + return features; + } if (QOpenGLFunctions::platformGLType() == QOpenGLFunctions::GLES1) { + int features = QGLFunctions::Multitexture | + QGLFunctions::Buffers | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample; + QOpenGLExtensionMatcher extensions; + if (extensions.match("GL_OES_framebuffer_object")) + features |= QGLFunctions::Framebuffers; + if (extensions.match("GL_OES_blend_equation_separate")) + features |= QGLFunctions::BlendEquationSeparate; + if (extensions.match("GL_OES_blend_func_separate")) + features |= QGLFunctions::BlendFuncSeparate; + if (extensions.match("GL_OES_blend_subtract")) + features |= QGLFunctions::BlendSubtract; + if (extensions.match("GL_OES_texture_npot")) + features |= QGLFunctions::NPOTTextures; + if (extensions.match("GL_IMG_texture_npot")) + features |= QGLFunctions::NPOTTextures; + return features; + } else { + int features = 0; + QGLFormat::OpenGLVersionFlags versions = QGLFormat::openGLVersionFlags(); + QOpenGLExtensionMatcher extensions; + + // Recognize features by extension name. + if (extensions.match("GL_ARB_multitexture")) + features |= QGLFunctions::Multitexture; + if (extensions.match("GL_ARB_shader_objects")) + features |= QGLFunctions::Shaders; + if (extensions.match("GL_EXT_framebuffer_object") || extensions.match("GL_ARB_framebuffer_object")) - features |= QGLFunctions::Framebuffers; - if (extensions.match("GL_EXT_blend_color")) - features |= QGLFunctions::BlendColor; - if (extensions.match("GL_EXT_blend_equation_separate")) - features |= QGLFunctions::BlendEquationSeparate; - if (extensions.match("GL_EXT_blend_func_separate")) - features |= QGLFunctions::BlendFuncSeparate; - if (extensions.match("GL_EXT_blend_subtract")) - features |= QGLFunctions::BlendSubtract; - if (extensions.match("GL_ARB_texture_compression")) - features |= QGLFunctions::CompressedTextures; - if (extensions.match("GL_ARB_multisample")) - features |= QGLFunctions::Multisample; - if (extensions.match("GL_ARB_texture_non_power_of_two")) - features |= QGLFunctions::NPOTTextures; - - // Recognize features by minimum OpenGL version. - if (versions & QGLFormat::OpenGL_Version_1_2) { - features |= QGLFunctions::BlendColor | - QGLFunctions::BlendEquation; - } - if (versions & QGLFormat::OpenGL_Version_1_3) { - features |= QGLFunctions::Multitexture | - QGLFunctions::CompressedTextures | - QGLFunctions::Multisample; - } - if (versions & QGLFormat::OpenGL_Version_1_4) - features |= QGLFunctions::BlendFuncSeparate; - if (versions & QGLFormat::OpenGL_Version_1_5) - features |= QGLFunctions::Buffers; - if (versions & QGLFormat::OpenGL_Version_2_0) { - features |= QGLFunctions::Shaders | - QGLFunctions::StencilSeparate | - QGLFunctions::BlendEquationSeparate | - QGLFunctions::NPOTTextures; - } - return features; -#endif + features |= QGLFunctions::Framebuffers; + if (extensions.match("GL_EXT_blend_color")) + features |= QGLFunctions::BlendColor; + if (extensions.match("GL_EXT_blend_equation_separate")) + features |= QGLFunctions::BlendEquationSeparate; + if (extensions.match("GL_EXT_blend_func_separate")) + features |= QGLFunctions::BlendFuncSeparate; + if (extensions.match("GL_EXT_blend_subtract")) + features |= QGLFunctions::BlendSubtract; + if (extensions.match("GL_ARB_texture_compression")) + features |= QGLFunctions::CompressedTextures; + if (extensions.match("GL_ARB_multisample")) + features |= QGLFunctions::Multisample; + if (extensions.match("GL_ARB_texture_non_power_of_two")) + features |= QGLFunctions::NPOTTextures; + + // Recognize features by minimum OpenGL version. + if (versions & QGLFormat::OpenGL_Version_1_2) { + features |= QGLFunctions::BlendColor | + QGLFunctions::BlendEquation; + } + if (versions & QGLFormat::OpenGL_Version_1_3) { + features |= QGLFunctions::Multitexture | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample; + } + if (versions & QGLFormat::OpenGL_Version_1_4) + features |= QGLFunctions::BlendFuncSeparate; + if (versions & QGLFormat::OpenGL_Version_1_5) + features |= QGLFunctions::Buffers; + if (versions & QGLFormat::OpenGL_Version_2_0) { + features |= QGLFunctions::Shaders | + QGLFunctions::StencilSeparate | + QGLFunctions::BlendEquationSeparate | + QGLFunctions::NPOTTextures; + } + return features; + } } /*! diff --git a/src/opengl/qglfunctions.h b/src/opengl/qglfunctions.h index fd867d7a91..7fc7966a09 100644 --- a/src/opengl/qglfunctions.h +++ b/src/opengl/qglfunctions.h @@ -51,6 +51,7 @@ #include <QtOpenGL/qgl.h> #include <QtGui/qopenglcontext.h> +#include <QtGui/qopenglfunctions.h> QT_BEGIN_NAMESPACE diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index ebc9f296eb..51e7648d72 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -361,7 +361,8 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const glBindTexture(GL_TEXTURE_2D, texture_id); #ifndef QT_OPENGL_ES - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, d->req_size.width(), d->req_size.height(), 0); + GLenum format = QOpenGLFunctions::isES() ? GL_RGBA : GL_RGBA8; + glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, d->req_size.width(), d->req_size.height(), 0); #else glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0); #endif @@ -487,7 +488,8 @@ GLuint QGLPixelBuffer::bindTexture(const QImage &image, GLenum target) { Q_D(QGLPixelBuffer); #ifndef QT_OPENGL_ES - return d->qctx->bindTexture(image, target, GLint(GL_RGBA8)); + GLenum format = QOpenGLFunctions::isES() ? GL_RGBA : GL_RGBA8; + return d->qctx->bindTexture(image, target, GLint(format)); #else return d->qctx->bindTexture(image, target, GL_RGBA); #endif @@ -505,7 +507,8 @@ GLuint QGLPixelBuffer::bindTexture(const QPixmap &pixmap, GLenum target) { Q_D(QGLPixelBuffer); #ifndef QT_OPENGL_ES - return d->qctx->bindTexture(pixmap, target, GLint(GL_RGBA8)); + GLenum format = QOpenGLFunctions::isES() ? GL_RGBA : GL_RGBA8; + return d->qctx->bindTexture(pixmap, target, GLint(format)); #else return d->qctx->bindTexture(pixmap, target, GL_RGBA); #endif diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index 84e4c26ed1..6b8d38ef42 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -47,6 +47,7 @@ #include <QtCore/qfile.h> #include <QtCore/qvarlengtharray.h> #include <QtCore/qvector.h> +#include <QDebug> QT_BEGIN_NAMESPACE @@ -246,7 +247,8 @@ bool QGLShaderPrivate::create() if (shaderType == QGLShader::Vertex) shader = glfuncs->glCreateShader(GL_VERTEX_SHADER); #if !defined(QT_OPENGL_ES_2) - else if (shaderType == QGLShader::Geometry) + else if (shaderType == QGLShader::Geometry + && !QOpenGLFunctions::isES()) shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER_EXT); #endif else @@ -428,11 +430,14 @@ bool QGLShader::compileSourceCode(const char *source) srclen.append(GLint(headerLen)); } #ifdef QGL_DEFINE_QUALIFIERS - src.append(qualifierDefines); - srclen.append(GLint(sizeof(qualifierDefines) - 1)); + if (!QOpenGLFunctions::isES()) { + src.append(qualifierDefines); + srclen.append(GLint(sizeof(qualifierDefines) - 1)); + } #endif #ifdef QGL_REDEFINE_HIGHP - if (d->shaderType == Fragment) { + if (d->shaderType == Fragment + && QOpenGLFunctions::isES()) { src.append(redefineHighp); srclen.append(GLint(sizeof(redefineHighp) - 1)); } @@ -562,13 +567,15 @@ public: void initializeGeometryShaderFunctions() { - QOpenGLContext *context = QOpenGLContext::currentContext(); - glProgramParameteri = (type_glProgramParameteri) - context->getProcAddress("glProgramParameteri"); - - if (!glProgramParameteri) { + if (!QOpenGLFunctions::isES()) { + QOpenGLContext *context = QOpenGLContext::currentContext(); glProgramParameteri = (type_glProgramParameteri) - context->getProcAddress("glProgramParameteriEXT"); + context->getProcAddress("glProgramParameteri"); + + if (!glProgramParameteri) { + glProgramParameteri = (type_glProgramParameteri) + context->getProcAddress("glProgramParameteriEXT"); + } } } @@ -929,7 +936,8 @@ bool QGLShaderProgram::link() #if !defined(QT_OPENGL_ES_2) // Set up the geometry shader parameters - if (d->glfuncs->glProgramParameteri) { + if (!QOpenGLFunctions::isES() + && d->glfuncs->glProgramParameteri) { foreach (QGLShader *shader, d->shaders) { if (shader->shaderType() & QGLShader::Geometry) { d->glfuncs->glProgramParameteri(program, GL_GEOMETRY_INPUT_TYPE_EXT, @@ -3060,7 +3068,8 @@ int QGLShaderProgram::maxGeometryOutputVertices() const { GLint n = 0; #if !defined(QT_OPENGL_ES_2) - glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n); + if (!QOpenGLFunctions::isES()) + glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n); #endif return n; } |