File indexing completed on 2024-05-19 16:35:18

0001 /*
0002     SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "drmclientbuffer.h"
0008 #include "clientbuffer_p.h"
0009 #include "display.h"
0010 
0011 #include <EGL/egl.h>
0012 #include <QtGui/qopengl.h>
0013 
0014 #ifndef EGL_WL_bind_wayland_display
0015 #define EGL_WAYLAND_Y_INVERTED_WL 0x31DB
0016 #endif
0017 
0018 namespace KWaylandServer
0019 {
0020 typedef EGLBoolean (*eglQueryWaylandBufferWL_func)(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
0021 static eglQueryWaylandBufferWL_func eglQueryWaylandBufferWL = nullptr;
0022 
0023 class DrmClientBufferPrivate : public ClientBufferPrivate
0024 {
0025 public:
0026     int textureFormat = 0;
0027     int width = 0;
0028     int height = 0;
0029     int yInverted = 0;
0030     bool hasAlphaChannel = false;
0031 };
0032 
0033 DrmClientBuffer::DrmClientBuffer(wl_resource *resource, DrmClientBufferIntegration *integration)
0034     : ClientBuffer(resource, *new DrmClientBufferPrivate)
0035 {
0036     Q_D(DrmClientBuffer);
0037 
0038     EGLDisplay eglDisplay = integration->display()->eglDisplay();
0039     eglQueryWaylandBufferWL(eglDisplay, resource, EGL_TEXTURE_FORMAT, &d->textureFormat);
0040     eglQueryWaylandBufferWL(eglDisplay, resource, EGL_WIDTH, &d->width);
0041     eglQueryWaylandBufferWL(eglDisplay, resource, EGL_HEIGHT, &d->height);
0042 
0043     if (!eglQueryWaylandBufferWL(eglDisplay, resource, EGL_WAYLAND_Y_INVERTED_WL, &d->yInverted)) {
0044         // If EGL_WAYLAND_Y_INVERTED_WL is unsupported, we must assume that the buffer is inverted.
0045         d->yInverted = true;
0046     }
0047 }
0048 
0049 int DrmClientBuffer::textureFormat() const
0050 {
0051     Q_D(const DrmClientBuffer);
0052     return d->textureFormat;
0053 }
0054 
0055 QSize DrmClientBuffer::size() const
0056 {
0057     Q_D(const DrmClientBuffer);
0058     return QSize(d->width, d->height);
0059 }
0060 
0061 bool DrmClientBuffer::hasAlphaChannel() const
0062 {
0063     Q_D(const DrmClientBuffer);
0064     return d->textureFormat == EGL_TEXTURE_RGBA;
0065 }
0066 
0067 ClientBuffer::Origin DrmClientBuffer::origin() const
0068 {
0069     Q_D(const DrmClientBuffer);
0070     return d->yInverted ? Origin::TopLeft : Origin::BottomLeft;
0071 }
0072 
0073 DrmClientBufferIntegration::DrmClientBufferIntegration(Display *display)
0074     : ClientBufferIntegration(display)
0075 {
0076 }
0077 
0078 ClientBuffer *DrmClientBufferIntegration::createBuffer(::wl_resource *resource)
0079 {
0080     EGLDisplay eglDisplay = display()->eglDisplay();
0081     static bool resolved = false;
0082     if (!resolved && eglDisplay != EGL_NO_DISPLAY) {
0083         eglQueryWaylandBufferWL = (eglQueryWaylandBufferWL_func)eglGetProcAddress("eglQueryWaylandBufferWL");
0084         resolved = true;
0085     }
0086 
0087     EGLint format;
0088     if (eglQueryWaylandBufferWL(eglDisplay, resource, EGL_TEXTURE_FORMAT, &format)) {
0089         return new DrmClientBuffer(resource, this);
0090     }
0091     return nullptr;
0092 }
0093 
0094 } // namespace KWaylandServer