From a401558a43fd1df11ba44ce81bb09d2467d21e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sat, 29 Sep 2012 13:19:35 +0200 Subject: [PATCH] Provide OpenGL over Egl The Egl backend is decoupled from the OpenGL ES build option which makes it possible to use it as a replacement for glx. To make this possible a new build flag is added when egl is available at compile time and any egl specific code is now ifdefed with this flag instead of the gles flag. In addition at runtime a windowing system enum value is passed to the various detect methods to have egl/glx specific detection for e.g. function pointer resolving. By default egl is used if compiled with OpenGL ES, otherwise glx is used. But in the non-gles case the windowing system can be selected through the new environment variable KWIN_OPENGL_INTERFACE. Setting this variable to "egl" the EglOnXBackend is used. REVIEW: 106632 --- CMakeLists.txt | 14 ++- eglonxbackend.cpp | 45 ++++++-- glxbackend.cpp | 4 +- libkwineffects/CMakeLists.txt | 6 + libkwineffects/kwinconfig.h.cmake | 2 + libkwineffects/kwinglobals.h | 6 + libkwineffects/kwinglplatform.cpp | 39 ++++--- libkwineffects/kwinglplatform.h | 3 +- libkwineffects/kwinglutils.cpp | 6 +- libkwineffects/kwinglutils.h | 2 +- libkwineffects/kwinglutils_funcs.cpp | 157 ++++++++++++++++----------- libkwineffects/kwinglutils_funcs.h | 16 ++- scene_opengl.cpp | 43 +++++++- 13 files changed, 233 insertions(+), 110 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c59b1f6fa1..95fb9c983f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,11 @@ if(OPENGL_FOUND) include_directories(${OPENGL_INCLUDE_DIR}) endif(OPENGL_FOUND) +if(OPENGL_EGL_FOUND) + include_directories(${OPENGLES_EGL_INCLUDE_DIR}) + set(KWIN_HAVE_EGL 1) +endif(OPENGL_EGL_FOUND) + if(OPENGLES_FOUND) include_directories(${OPENGLES_INCLUDE_DIR}) endif(OPENGLES_FOUND) @@ -110,7 +115,6 @@ set(kwin_KDEINIT_SRCS scene.cpp scene_xrender.cpp scene_opengl.cpp - eglonxbackend.cpp glxbackend.cpp thumbnailitem.cpp lanczosfilter.cpp @@ -152,6 +156,10 @@ if(KWIN_BUILD_SCREENEDGES) ) endif(KWIN_BUILD_SCREENEDGES) +if(KWIN_HAVE_EGL) + set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} eglonxbackend.cpp) +endif(KWIN_HAVE_EGL) + qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.KWin.xml dbusinterface.h KWin::DBusInterface ) qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.kwin.Compositing.xml composite.h KWin::Compositor ) qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.kwin.Effects.xml effects.h KWin::EffectsHandlerImpl ) @@ -178,6 +186,10 @@ if(KWIN_BUILD_ACTIVITIES) set(kwinLibs ${kwinLibs} ${KACTIVITIES_LIBRARY}) endif(KWIN_BUILD_ACTIVITIES) +if(OPENGL_EGL_FOUND) + set(kwinLibs ${kwinLibs} ${OPENGLES_EGL_LIBRARY}) +endif(OPENGL_EGL_FOUND) + kde4_add_kdeinit_executable( kwin ${kwin_KDEINIT_SRCS}) target_link_libraries(kdeinit_kwin ${kwinLibs}) diff --git a/eglonxbackend.cpp b/eglonxbackend.cpp index 8797c8aaa2..dc5060b223 100644 --- a/eglonxbackend.cpp +++ b/eglonxbackend.cpp @@ -17,7 +17,6 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ -#ifdef KWIN_HAVE_OPENGLES #include "eglonxbackend.h" // kwin #include "options.h" @@ -67,9 +66,9 @@ void EglOnXBackend::init() return; } GLPlatform *glPlatform = GLPlatform::instance(); - glPlatform->detect(); + glPlatform->detect(EglPlatformInterface); glPlatform->printResults(); - initGL(); + initGL(EglPlatformInterface); if (!hasGLExtension("GL_OES_EGL_image")) { setFailed("Required extension GL_OES_EGL_image not found, disabling compositing"); return; @@ -99,7 +98,14 @@ bool EglOnXBackend::initRenderingContext() EGLint major, minor; if (eglInitialize(dpy, &major, &minor) == EGL_FALSE) return false; +#ifdef KWIN_HAVE_OPENGLES eglBindAPI(EGL_OPENGL_ES_API); +#else + if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) { + kError(1212) << "bind OpenGL API failed"; + return false; + } +#endif initBufferConfigs(); if (!overlayWindow()->create()) { kError(1212) << "Could not get overlay window"; @@ -111,18 +117,27 @@ bool EglOnXBackend::initRenderingContext() eglSurfaceAttrib(dpy, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); - eglQuerySurface(dpy, surface, EGL_POST_SUB_BUFFER_SUPPORTED_NV, &surfaceHasSubPost); + if (eglQuerySurface(dpy, surface, EGL_POST_SUB_BUFFER_SUPPORTED_NV, &surfaceHasSubPost) == EGL_FALSE) { + kError(1212) << "query surface failed"; + return false; + } const EGLint context_attribs[] = { +#ifdef KWIN_HAVE_OPENGLES EGL_CONTEXT_CLIENT_VERSION, 2, +#endif EGL_NONE }; ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, context_attribs); - if (ctx == EGL_NO_CONTEXT) + if (ctx == EGL_NO_CONTEXT) { + kError(1212) << "Create Context failed"; return false; - if (eglMakeCurrent(dpy, surface, surface, ctx) == EGL_FALSE) + } + if (eglMakeCurrent(dpy, surface, surface, ctx) == EGL_FALSE) { + kError(1212) << "Make Context Current failed"; return false; + } kDebug(1212) << "EGL version: " << major << "." << minor; EGLint error = eglGetError(); if (error != EGL_SUCCESS) { @@ -140,21 +155,30 @@ bool EglOnXBackend::initBufferConfigs() EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_ALPHA_SIZE, 0, +#ifdef KWIN_HAVE_OPENGLES EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#else + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, +#endif EGL_CONFIG_CAVEAT, EGL_NONE, EGL_NONE, }; EGLint count; EGLConfig configs[1024]; - eglChooseConfig(dpy, config_attribs, configs, 1024, &count); + if (eglChooseConfig(dpy, config_attribs, configs, 1024, &count) == EGL_FALSE) { + kError(1212) << "choose config failed"; + return false; + } EGLint visualId = XVisualIDFromVisual((Visual*)QX11Info::appVisual()); config = configs[0]; for (int i = 0; i < count; i++) { EGLint val; - eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &val); + if (eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &val) == EGL_FALSE) { + kError(1212) << "egl get config attrib failed"; + } if (visualId == val) { config = configs[i]; break; @@ -189,14 +213,14 @@ SceneOpenGL::TexturePrivate *EglOnXBackend::createBackendTexture(SceneOpenGL::Te return new EglTexture(texture, this); } -void KWin::EglOnXBackend::prepareRenderingFrame() +void EglOnXBackend::prepareRenderingFrame() { if (!lastDamage().isEmpty()) flushBuffer(); startRenderTimer(); } -void KWin::EglOnXBackend::endRenderingFrame(int mask, const QRegion &damage) +void EglOnXBackend::endRenderingFrame(int mask, const QRegion &damage) { setLastDamage(damage); setLastMask(mask); @@ -281,4 +305,3 @@ void KWin::EglTexture::onDamage() } } // namespace -#endif diff --git a/glxbackend.cpp b/glxbackend.cpp index cef88d433a..a9228f73ee 100644 --- a/glxbackend.cpp +++ b/glxbackend.cpp @@ -89,9 +89,9 @@ void GlxBackend::init() } // Initialize OpenGL GLPlatform *glPlatform = GLPlatform::instance(); - glPlatform->detect(); + glPlatform->detect(GlxPlatformInterface); glPlatform->printResults(); - initGL(); + initGL(GlxPlatformInterface); // Check whether certain features are supported if (options->isGlVSync()) { if (glXGetVideoSync && glXSwapInterval && glXIsDirect(display(), ctxbuffer)) { diff --git a/libkwineffects/CMakeLists.txt b/libkwineffects/CMakeLists.txt index 14a2747d6e..4b99d2afed 100644 --- a/libkwineffects/CMakeLists.txt +++ b/libkwineffects/CMakeLists.txt @@ -33,8 +33,14 @@ set(kwin_GLUTILSLIB_SRCS macro( KWIN4_ADD_GLUTILS_BACKEND name glinclude ) include_directories(${glinclude}) + if(OPENGL_EGL_FOUND) + include_directories(OPENGLES_EGL_INCLUDE_DIR) + endif(OPENGL_EGL_FOUND) kde4_add_library(${name} SHARED ${kwin_GLUTILSLIB_SRCS}) target_link_libraries(${name} ${KDE4_KDEUI_LIBS} ${QT_QTGUI_LIBRARY} ${X11_LIBRARIES} kwineffects) + if(OPENGL_EGL_FOUND) + target_link_libraries(${name} ${OPENGLES_EGL_LIBRARY}) + endif(OPENGL_EGL_FOUND) set_target_properties(${name} PROPERTIES VERSION 1.0.0 SOVERSION 1 ) target_link_libraries(${name} ${ARGN}) target_link_libraries(${name} LINK_INTERFACE_LIBRARIES ${ARGN}) diff --git a/libkwineffects/kwinconfig.h.cmake b/libkwineffects/kwinconfig.h.cmake index a8586cc9b6..3e34723aea 100644 --- a/libkwineffects/kwinconfig.h.cmake +++ b/libkwineffects/kwinconfig.h.cmake @@ -19,5 +19,7 @@ /* KWIN_HAVE_XRENDER_COMPOSITING - whether XRender-based compositing support is available */ #cmakedefine KWIN_HAVE_XRENDER_COMPOSITING +#cmakedefine KWIN_HAVE_EGL + #endif diff --git a/libkwineffects/kwinglobals.h b/libkwineffects/kwinglobals.h index 8ea6872c5e..e1507d75bf 100644 --- a/libkwineffects/kwinglobals.h +++ b/libkwineffects/kwinglobals.h @@ -53,6 +53,12 @@ enum CompositingType { OpenGL2Compositing = 1<<3 | OpenGLCompositing }; +enum OpenGLPlatformInterface { + NoOpenGLPlatformInterface = 0, + GlxPlatformInterface, + EglPlatformInterface +}; + enum clientAreaOption { PlacementArea, // geometry where a window will be initially placed after being mapped MovementArea, // ??? window movement snapping area? ignore struts diff --git a/libkwineffects/kwinglplatform.cpp b/libkwineffects/kwinglplatform.cpp index 26341e4d8b..d5d498bf12 100644 --- a/libkwineffects/kwinglplatform.cpp +++ b/libkwineffects/kwinglplatform.cpp @@ -498,7 +498,7 @@ GLPlatform::~GLPlatform() { } -void GLPlatform::detect() +void GLPlatform::detect(OpenGLPlatformInterface platformInterface) { m_vendor = (const char*)glGetString(GL_VENDOR); m_renderer = (const char*)glGetString(GL_RENDERER); @@ -521,21 +521,32 @@ void GLPlatform::detect() m_mesaVersion = parseVersionString(version); } + if (platformInterface == EglPlatformInterface) { + m_directRendering = true; #ifdef KWIN_HAVE_OPENGLES - m_directRendering = true; - m_supportsGLSL = true; - m_textureNPOT = true; + m_supportsGLSL = true; + m_textureNPOT = true; #else - GLXContext ctx = glXGetCurrentContext(); - m_directRendering = glXIsDirect(display(), ctx); + m_supportsGLSL = m_extensions.contains("GL_ARB_shading_language_100") && + m_extensions.contains("GL_ARB_shader_objects") && + m_extensions.contains("GL_ARB_fragment_shader") && + m_extensions.contains("GL_ARB_vertex_shader"); - m_supportsGLSL = m_extensions.contains("GL_ARB_shading_language_100") && - m_extensions.contains("GL_ARB_shader_objects") && - m_extensions.contains("GL_ARB_fragment_shader") && - m_extensions.contains("GL_ARB_vertex_shader"); - - m_textureNPOT = m_extensions.contains("GL_ARB_texture_non_power_of_two"); + m_textureNPOT = m_extensions.contains("GL_ARB_texture_non_power_of_two"); #endif + } else if (platformInterface == GlxPlatformInterface) { +#ifndef KWIN_HAVE_OPENGLES + GLXContext ctx = glXGetCurrentContext(); + m_directRendering = glXIsDirect(display(), ctx); + + m_supportsGLSL = m_extensions.contains("GL_ARB_shading_language_100") && + m_extensions.contains("GL_ARB_shader_objects") && + m_extensions.contains("GL_ARB_fragment_shader") && + m_extensions.contains("GL_ARB_vertex_shader"); + + m_textureNPOT = m_extensions.contains("GL_ARB_texture_non_power_of_two"); +#endif + } m_serverVersion = getXServerVersion(); m_kernelVersion = getKernelVersion(); @@ -728,14 +739,12 @@ void GLPlatform::detect() m_limitedGLSL = m_supportsGLSL && m_chipClass < I965; } -#ifdef KWIN_HAVE_OPENGLES - if (isMesaDriver()) { + if (isMesaDriver() && platformInterface == EglPlatformInterface) { // According to the reference implementation in // mesa/demos/src/egl/opengles1/texture_from_pixmap // the mesa egl implementation does not require a strict binding (so far). m_looseBinding = true; } -#endif // Loose binding is broken with Gallium drivers in Mesa 7.10 if (isGalliumDriver() && mesaVersion() == kVersionNumber(7, 10, 0)) diff --git a/libkwineffects/kwinglplatform.h b/libkwineffects/kwinglplatform.h index 14555a2bd4..cda141d9f9 100644 --- a/libkwineffects/kwinglplatform.h +++ b/libkwineffects/kwinglplatform.h @@ -21,6 +21,7 @@ along with this program. If not, see . #ifndef KWIN_GLPLATFORM_H #define KWIN_GLPLATFORM_H +#include #include #include @@ -139,7 +140,7 @@ public: /** * Runs the detection code using the current OpenGL context. */ - void detect(); + void detect(OpenGLPlatformInterface platformInterface); /** * Prints the results of the detection code. diff --git a/libkwineffects/kwinglutils.cpp b/libkwineffects/kwinglutils.cpp index 5abae528fc..30ac03d78e 100644 --- a/libkwineffects/kwinglutils.cpp +++ b/libkwineffects/kwinglutils.cpp @@ -83,7 +83,7 @@ void initGLX() void initEGL() { -#ifdef KWIN_HAVE_OPENGLES +#ifdef KWIN_HAVE_EGL EGLDisplay dpy = eglGetCurrentDisplay(); int major, minor; eglInitialize(dpy, &major, &minor); @@ -94,7 +94,7 @@ void initEGL() #endif } -void initGL() +void initGL(OpenGLPlatformInterface platformInterface) { // Get OpenGL version QString glversionstring = QString((const char*)glGetString(GL_VERSION)); @@ -108,7 +108,7 @@ void initGL() glExtensions = QString((const char*)glGetString(GL_EXTENSIONS)).split(' '); // handle OpenGL extensions functions - glResolveFunctions(); + glResolveFunctions(platformInterface); GLTexturePrivate::initStatic(); GLRenderTarget::initStatic(); diff --git a/libkwineffects/kwinglutils.h b/libkwineffects/kwinglutils.h index 445ddc7ccc..cbdab15c92 100644 --- a/libkwineffects/kwinglutils.h +++ b/libkwineffects/kwinglutils.h @@ -58,7 +58,7 @@ void KWIN_EXPORT initGLX(); // Initializes OpenGL stuff. This includes resolving function pointers as // well as checking for GL version and extensions // Note that GL context has to be created by the time this function is called -void KWIN_EXPORT initGL(); +void KWIN_EXPORT initGL(OpenGLPlatformInterface platformInterface); // Initializes EGL function pointers void KWIN_EXPORT initEGL(); // Cleans up all resources hold by the GL Context diff --git a/libkwineffects/kwinglutils_funcs.cpp b/libkwineffects/kwinglutils_funcs.cpp index a67c7203b3..5f084d5a1d 100644 --- a/libkwineffects/kwinglutils_funcs.cpp +++ b/libkwineffects/kwinglutils_funcs.cpp @@ -24,19 +24,41 @@ along with this program. If not, see . // Resolves given function, using getProcAddress -#define GL_RESOLVE( function ) function = (function ## _func)getProcAddress( #function ); +#ifdef KWIN_HAVE_EGL +#define GL_RESOLVE( function ) \ + if (platformInterface == GlxPlatformInterface) \ + function = (function ## _func)getProcAddress( #function ); \ + else if (platformInterface == EglPlatformInterface) \ + function = (function ## _func)eglGetProcAddress( #function ); // Same as above but tries to use function "backup" if "function" doesn't exist // Useful when same functionality is also defined in an extension +#define GL_RESOLVE_WITH_EXT( function, backup ) \ + if (platformInterface == GlxPlatformInterface) { \ + function = (function ## _func)getProcAddress( #function ); \ + if ( !function ) \ + function = (function ## _func)getProcAddress( #backup ); \ + } else if (platformInterface == EglPlatformInterface) { \ + function = (function ## _func)eglGetProcAddress( #function ); \ + if ( !function ) \ + function = (function ## _func)eglGetProcAddress( #backup ); \ + } +#else +// same without the switch to egl +#define GL_RESOLVE( function ) function = (function ## _func)getProcAddress( #function ); + #define GL_RESOLVE_WITH_EXT( function, backup ) \ function = (function ## _func)getProcAddress( #function ); \ if ( !function ) \ function = (function ## _func)getProcAddress( #backup ); +#endif + +#define EGL_RESOLVE( function ) function = (function ## _func)eglGetProcAddress( #function ); -#ifndef KWIN_HAVE_OPENGLES namespace KWin { +#ifndef KWIN_HAVE_OPENGLES // Function pointers glXGetProcAddress_func glXGetProcAddress; // GLX 1.3 @@ -175,6 +197,7 @@ void glxResolveFunctions() glXSwapInterval = NULL; } + OpenGLPlatformInterface platformInterface = GlxPlatformInterface; GL_RESOLVE_WITH_EXT(glXGetFBConfigAttrib, glXGetFBConfigAttribSGIX); GL_RESOLVE_WITH_EXT(glXGetVisualFromFBConfig, glXGetVisualFromFBConfigSGIX); GL_RESOLVE(glXGetFBConfigs); @@ -183,9 +206,42 @@ void glxResolveFunctions() GL_RESOLVE(glXCreatePixmap); GL_RESOLVE(glXDestroyPixmap); } +#endif -void glResolveFunctions() + + +#ifdef KWIN_HAVE_EGL + +// EGL +eglCreateImageKHR_func eglCreateImageKHR; +eglDestroyImageKHR_func eglDestroyImageKHR; +eglPostSubBufferNV_func eglPostSubBufferNV; +// GLES +glEGLImageTargetTexture2DOES_func glEGLImageTargetTexture2DOES; + +void eglResolveFunctions() { + if (hasGLExtension("EGL_KHR_image") || + (hasGLExtension("EGL_KHR_image_base") && + hasGLExtension("EGL_KHR_image_pixmap"))) { + eglCreateImageKHR = (eglCreateImageKHR_func)eglGetProcAddress("eglCreateImageKHR"); + eglDestroyImageKHR = (eglDestroyImageKHR_func)eglGetProcAddress("eglDestroyImageKHR"); + } else { + eglCreateImageKHR = NULL; + eglDestroyImageKHR = NULL; + } + + if (hasGLExtension("EGL_NV_post_sub_buffer")) { + eglPostSubBufferNV = (eglPostSubBufferNV_func)eglGetProcAddress("eglPostSubBufferNV"); + } else { + eglPostSubBufferNV = NULL; + } +} +#endif + +void glResolveFunctions(OpenGLPlatformInterface platformInterface) +{ +#ifndef KWIN_HAVE_OPENGLES if (hasGLExtension("GL_ARB_multitexture")) { GL_RESOLVE_WITH_EXT(glActiveTexture, glActiveTextureARB); // Get number of texture units @@ -195,31 +251,31 @@ void glResolveFunctions() glTextureUnitsCount = 0; } if (hasGLExtension("GL_EXT_framebuffer_object")) { - glIsRenderbuffer = (glIsRenderbuffer_func) getProcAddress("glIsRenderbufferEXT"); - glBindRenderbuffer = (glBindRenderbuffer_func) getProcAddress("glBindRenderbufferEXT"); - glDeleteRenderbuffers = (glDeleteRenderbuffers_func) getProcAddress("glDeleteRenderbuffersEXT"); - glGenRenderbuffers = (glGenRenderbuffers_func) getProcAddress("glGenRenderbuffersEXT"); + GL_RESOLVE_WITH_EXT(glIsRenderbuffer, glIsRenderbufferEXT); + GL_RESOLVE_WITH_EXT(glBindRenderbuffer, glBindRenderbufferEXT); + GL_RESOLVE_WITH_EXT(glDeleteRenderbuffers, glDeleteRenderbuffersEXT); + GL_RESOLVE_WITH_EXT(glGenRenderbuffers, glGenRenderbuffersEXT); - glRenderbufferStorage = (glRenderbufferStorage_func) getProcAddress("glRenderbufferStorageEXT"); + GL_RESOLVE_WITH_EXT(glRenderbufferStorage, glRenderbufferStorageEXT); - glGetRenderbufferParameteriv = (glGetRenderbufferParameteriv_func) getProcAddress("glGetRenderbufferParameterivEXT"); + GL_RESOLVE_WITH_EXT(glGetRenderbufferParameteriv, glGetRenderbufferParameterivEXT); - glIsFramebuffer = (glIsFramebuffer_func) getProcAddress("glIsFramebufferEXT"); - glBindFramebuffer = (glBindFramebuffer_func) getProcAddress("glBindFramebufferEXT"); - glDeleteFramebuffers = (glDeleteFramebuffers_func) getProcAddress("glDeleteFramebuffersEXT"); - glGenFramebuffers = (glGenFramebuffers_func) getProcAddress("glGenFramebuffersEXT"); + GL_RESOLVE_WITH_EXT(glIsFramebuffer, glIsFramebufferEXT); + GL_RESOLVE_WITH_EXT(glBindFramebuffer, glBindFramebufferEXT); + GL_RESOLVE_WITH_EXT(glDeleteFramebuffers, glDeleteFramebuffersEXT); + GL_RESOLVE_WITH_EXT(glGenFramebuffers, glGenFramebuffersEXT); - glCheckFramebufferStatus = (glCheckFramebufferStatus_func) getProcAddress("glCheckFramebufferStatusEXT"); + GL_RESOLVE_WITH_EXT(glCheckFramebufferStatus, glCheckFramebufferStatusEXT); - glFramebufferTexture1D = (glFramebufferTexture1D_func) getProcAddress("glFramebufferTexture1DEXT"); - glFramebufferTexture2D = (glFramebufferTexture2D_func) getProcAddress("glFramebufferTexture2DEXT"); - glFramebufferTexture3D = (glFramebufferTexture3D_func) getProcAddress("glFramebufferTexture3DEXT"); + GL_RESOLVE_WITH_EXT(glFramebufferTexture1D, glFramebufferTexture1DEXT); + GL_RESOLVE_WITH_EXT(glFramebufferTexture2D, glFramebufferTexture2DEXT); + GL_RESOLVE_WITH_EXT(glFramebufferTexture3D, glFramebufferTexture3DEXT); - glFramebufferRenderbuffer = (glFramebufferRenderbuffer_func) getProcAddress("glFramebufferRenderbufferEXT"); + GL_RESOLVE_WITH_EXT(glFramebufferRenderbuffer, glFramebufferRenderbufferEXT); - glGetFramebufferAttachmentParameteriv = (glGetFramebufferAttachmentParameteriv_func) getProcAddress("glGetFramebufferAttachmentParameterivEXT"); + GL_RESOLVE_WITH_EXT(glGetFramebufferAttachmentParameteriv, glGetFramebufferAttachmentParameterivEXT); - glGenerateMipmap = (glGenerateMipmap_func) getProcAddress("glGenerateMipmapEXT"); + GL_RESOLVE_WITH_EXT(glGenerateMipmap, glGenerateMipmapEXT); } else { glIsRenderbuffer = NULL; glBindRenderbuffer = NULL; @@ -241,9 +297,9 @@ void glResolveFunctions() } if (hasGLExtension("GL_ARB_framebuffer_object")) { - glBlitFramebuffer = (glBlitFramebuffer_func) getProcAddress("glBlitFramebuffer"); + GL_RESOLVE(glBlitFramebuffer); } else if (hasGLExtension("GL_EXT_framebuffer_blit")) { - glBlitFramebuffer = (glBlitFramebuffer_func) getProcAddress("glBlitFramebufferEXT"); + GL_RESOLVE_WITH_EXT(glBlitFramebuffer, glBlitFramebufferEXT); } else { glBlitFramebuffer = NULL; } @@ -302,48 +358,17 @@ void glResolveFunctions() glBindBuffer = NULL; glBufferData = NULL; } -} - -} // namespace - -#else -namespace KWin -{ - -// EGL -eglCreateImageKHR_func eglCreateImageKHR; -eglDestroyImageKHR_func eglDestroyImageKHR; -eglPostSubBufferNV_func eglPostSubBufferNV; -// GLES -glEGLImageTargetTexture2DOES_func glEGLImageTargetTexture2DOES; - -void eglResolveFunctions() -{ - if (hasGLExtension("EGL_KHR_image") || - (hasGLExtension("EGL_KHR_image_base") && - hasGLExtension("EGL_KHR_image_pixmap"))) { - eglCreateImageKHR = (eglCreateImageKHR_func)eglGetProcAddress("eglCreateImageKHR"); - eglDestroyImageKHR = (eglDestroyImageKHR_func)eglGetProcAddress("eglDestroyImageKHR"); - } else { - eglCreateImageKHR = NULL; - eglDestroyImageKHR = NULL; - } - - if (hasGLExtension("EGL_NV_post_sub_buffer")) { - eglPostSubBufferNV = (eglPostSubBufferNV_func)eglGetProcAddress("eglPostSubBufferNV"); - } else { - eglPostSubBufferNV = NULL; - } -} - -void glResolveFunctions() -{ - if (hasGLExtension("GL_OES_EGL_image")) { - glEGLImageTargetTexture2DOES = (glEGLImageTargetTexture2DOES_func)eglGetProcAddress("glEGLImageTargetTexture2DOES"); - } else { - glEGLImageTargetTexture2DOES = NULL; - } -} - -} // namespace #endif + +#ifdef KWIN_HAVE_EGL + if (platformInterface == EglPlatformInterface) { + if (hasGLExtension("GL_OES_EGL_image")) { + glEGLImageTargetTexture2DOES = (glEGLImageTargetTexture2DOES_func)eglGetProcAddress("glEGLImageTargetTexture2DOES"); + } else { + glEGLImageTargetTexture2DOES = NULL; + } + } +#endif +} + +} // namespace diff --git a/libkwineffects/kwinglutils_funcs.h b/libkwineffects/kwinglutils_funcs.h index 4f8125ab16..b2b7f5ba3f 100644 --- a/libkwineffects/kwinglutils_funcs.h +++ b/libkwineffects/kwinglutils_funcs.h @@ -22,6 +22,8 @@ along with this program. If not, see . #define KWIN_GLUTILS_FUNCS_H #include +#include +#include #define KWIN_EXPORT KDE_EXPORT @@ -352,11 +354,17 @@ extern KWIN_EXPORT glVertexAttribPointer_func glVertexAttribPointer; } // namespace -#else +#endif // not KWIN_HAVE_OPENGLES + +#ifdef KWIN_HAVE_EGL #define EGL_EGLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES + +#ifdef KWIN_HAVE_OPENGLES #include #include +#endif + #include #include #include @@ -369,7 +377,7 @@ namespace KWin { void KWIN_EXPORT eglResolveFunctions(); -void KWIN_EXPORT glResolveFunctions(); +void KWIN_EXPORT glResolveFunctions(OpenGLPlatformInterface platformInterface); // EGL typedef EGLImageKHR(*eglCreateImageKHR_func)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*); typedef EGLBoolean(*eglDestroyImageKHR_func)(EGLDisplay, EGLImageKHR); @@ -384,6 +392,6 @@ extern KWIN_EXPORT glEGLImageTargetTexture2DOES_func glEGLImageTargetTexture2DOE } // namespace -#endif +#endif // KWIN_HAVE_EGL -#endif +#endif // KWIN_GLUTILS_FUNCS_H diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 164d463eae..aa9bd15e1c 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -67,9 +67,10 @@ Sources and other compositing managers: */ #include "scene_opengl.h" -#ifdef KWIN_HAVE_OPENGLES +#ifdef KWIN_HAVE_EGL #include "eglonxbackend.h" -#else +#endif +#ifndef KWIN_HAVE_OPENGLES #include "glxbackend.h" #endif @@ -194,11 +195,41 @@ SceneOpenGL::~SceneOpenGL() SceneOpenGL *SceneOpenGL::createScene() { OpenGLBackend *backend = NULL; -#ifdef KWIN_HAVE_OPENGLES - backend = new EglOnXBackend(); -#else - backend = new GlxBackend(); + OpenGLPlatformInterface platformInterface = NoOpenGLPlatformInterface; + // should we use glx? +#ifndef KWIN_HAVE_OPENGLES + // on OpenGL we default to glx + platformInterface = GlxPlatformInterface; #endif + +#ifdef KWIN_HAVE_EGL +#ifdef KWIN_HAVE_OPENGLES + // for OpenGL ES we need to use the Egl Backend + platformInterface = EglPlatformInterface; +#else + // check environment variable + if (qstrcmp(qgetenv("KWIN_OPENGL_INTERFACE"), "egl") == 0) { + kDebug(1212) << "Forcing EGL native interface through environment variable"; + platformInterface = EglPlatformInterface; + } +#endif +#endif + + switch (platformInterface) { + case GlxPlatformInterface: +#ifndef KWIN_HAVE_OPENGLES + backend = new GlxBackend(); +#endif + break; + case EglPlatformInterface: +#ifdef KWIN_HAVE_EGL + backend = new EglOnXBackend(); +#endif + break; + default: + // no backend available + return NULL; + } if (!backend || backend->isFailed()) { delete backend; return NULL;