File indexing completed on 2024-11-10 04:57:05

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2015 Martin Flöser <mgraesslin@kde.org>
0006     SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "eglhelpers.h"
0012 #include "opengl/egldisplay.h"
0013 
0014 #include <logging.h>
0015 
0016 #include <QOpenGLContext>
0017 
0018 namespace KWin
0019 {
0020 namespace QPA
0021 {
0022 
0023 bool isOpenGLES()
0024 {
0025     if (qstrcmp(qgetenv("KWIN_COMPOSE"), "O2ES") == 0) {
0026         return true;
0027     }
0028 
0029     return QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES;
0030 }
0031 
0032 EGLConfig configFromFormat(EglDisplay *display, const QSurfaceFormat &surfaceFormat, EGLint surfaceType)
0033 {
0034     // std::max as these values are initialized to -1 by default.
0035     const EGLint redSize = std::max(surfaceFormat.redBufferSize(), 0);
0036     const EGLint greenSize = std::max(surfaceFormat.greenBufferSize(), 0);
0037     const EGLint blueSize = std::max(surfaceFormat.blueBufferSize(), 0);
0038     const EGLint alphaSize = std::max(surfaceFormat.alphaBufferSize(), 0);
0039     const EGLint depthSize = std::max(surfaceFormat.depthBufferSize(), 0);
0040     const EGLint stencilSize = std::max(surfaceFormat.stencilBufferSize(), 0);
0041 
0042     const EGLint renderableType = isOpenGLES() ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT;
0043 
0044     // Not setting samples as QtQuick doesn't need it.
0045     const QList<EGLint> attributes{
0046         EGL_SURFACE_TYPE, surfaceType,
0047         EGL_RED_SIZE, redSize,
0048         EGL_GREEN_SIZE, greenSize,
0049         EGL_BLUE_SIZE, blueSize,
0050         EGL_ALPHA_SIZE, alphaSize,
0051         EGL_DEPTH_SIZE, depthSize,
0052         EGL_STENCIL_SIZE, stencilSize,
0053         EGL_RENDERABLE_TYPE, renderableType,
0054         EGL_NONE};
0055 
0056     EGLint configCount;
0057     if (!eglChooseConfig(display->handle(), attributes.data(), nullptr, 0, &configCount)) {
0058         qCWarning(KWIN_QPA, "eglChooseConfig failed: %x", eglGetError());
0059         return EGL_NO_CONFIG_KHR;
0060     }
0061     if (configCount == 0) {
0062         qCWarning(KWIN_QPA, "eglChooseConfig did not return any configs");
0063         return EGL_NO_CONFIG_KHR;
0064     }
0065 
0066     QList<EGLConfig> configs(configCount);
0067     if (!eglChooseConfig(display->handle(), attributes.data(), configs.data(), configCount, &configCount)) {
0068         qCWarning(KWIN_QPA, "eglChooseConfig failed: %x", eglGetError());
0069         return EGL_NO_CONFIG_KHR;
0070     }
0071     if (configCount != configs.size()) {
0072         qCWarning(KWIN_QPA, "eglChooseConfig did not return requested configs");
0073         return EGL_NO_CONFIG_KHR;
0074     }
0075 
0076     for (const EGLConfig &config : std::as_const(configs)) {
0077         EGLint redConfig, greenConfig, blueConfig, alphaConfig;
0078         eglGetConfigAttrib(display->handle(), config, EGL_RED_SIZE, &redConfig);
0079         eglGetConfigAttrib(display->handle(), config, EGL_GREEN_SIZE, &greenConfig);
0080         eglGetConfigAttrib(display->handle(), config, EGL_BLUE_SIZE, &blueConfig);
0081         eglGetConfigAttrib(display->handle(), config, EGL_ALPHA_SIZE, &alphaConfig);
0082 
0083         if ((redSize == 0 || redSize == redConfig) && (greenSize == 0 || greenSize == greenConfig) && (blueSize == 0 || blueSize == blueConfig) && (alphaSize == 0 || alphaSize == alphaConfig)) {
0084             return config;
0085         }
0086     }
0087 
0088     // Return first config as a fallback.
0089     return configs[0];
0090 }
0091 
0092 QSurfaceFormat formatFromConfig(EglDisplay *display, EGLConfig config)
0093 {
0094     int redSize = 0;
0095     int blueSize = 0;
0096     int greenSize = 0;
0097     int alphaSize = 0;
0098     int stencilSize = 0;
0099     int depthSize = 0;
0100     int sampleCount = 0;
0101 
0102     eglGetConfigAttrib(display->handle(), config, EGL_RED_SIZE, &redSize);
0103     eglGetConfigAttrib(display->handle(), config, EGL_GREEN_SIZE, &greenSize);
0104     eglGetConfigAttrib(display->handle(), config, EGL_BLUE_SIZE, &blueSize);
0105     eglGetConfigAttrib(display->handle(), config, EGL_ALPHA_SIZE, &alphaSize);
0106     eglGetConfigAttrib(display->handle(), config, EGL_STENCIL_SIZE, &stencilSize);
0107     eglGetConfigAttrib(display->handle(), config, EGL_DEPTH_SIZE, &depthSize);
0108     eglGetConfigAttrib(display->handle(), config, EGL_SAMPLES, &sampleCount);
0109 
0110     QSurfaceFormat format;
0111     format.setRedBufferSize(redSize);
0112     format.setGreenBufferSize(greenSize);
0113     format.setBlueBufferSize(blueSize);
0114     format.setAlphaBufferSize(alphaSize);
0115     format.setStencilBufferSize(stencilSize);
0116     format.setDepthBufferSize(depthSize);
0117     format.setSamples(sampleCount);
0118     format.setRenderableType(isOpenGLES() ? QSurfaceFormat::OpenGLES : QSurfaceFormat::OpenGL);
0119     format.setStereo(false);
0120 
0121     return format;
0122 }
0123 
0124 } // namespace QPA
0125 } // namespace KWin