File indexing completed on 2025-09-14 05:23:17

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #pragma once
0010 
0011 #include <QHash>
0012 #include <QMap>
0013 #include <QPointer>
0014 #include <QRegion>
0015 #include <chrono>
0016 #include <optional>
0017 
0018 #include "core/outputlayer.h"
0019 #include "drm_plane.h"
0020 #include "opengl/gltexture.h"
0021 #include "utils/damagejournal.h"
0022 #include "utils/filedescriptor.h"
0023 
0024 struct gbm_bo;
0025 
0026 namespace KWin
0027 {
0028 
0029 class DrmFramebuffer;
0030 class EglSwapchain;
0031 class EglSwapchainSlot;
0032 class QPainterSwapchain;
0033 class ShadowBuffer;
0034 class EglContext;
0035 class EglGbmBackend;
0036 class GraphicsBuffer;
0037 class SurfaceItem;
0038 class GLTexture;
0039 class GLRenderTimeQuery;
0040 class ColorTransformation;
0041 class GlLookUpTable;
0042 class IccProfile;
0043 class IccShader;
0044 
0045 class EglGbmLayerSurface : public QObject
0046 {
0047     Q_OBJECT
0048 public:
0049     enum class BufferTarget {
0050         Normal,
0051         Linear,
0052         Dumb
0053     };
0054     enum class FormatOption {
0055         PreferAlpha,
0056         RequireAlpha
0057     };
0058     EglGbmLayerSurface(DrmGpu *gpu, EglGbmBackend *eglBackend, BufferTarget target = BufferTarget::Normal, FormatOption formatOption = FormatOption::PreferAlpha);
0059     ~EglGbmLayerSurface();
0060 
0061     std::optional<OutputLayerBeginFrameInfo> startRendering(const QSize &bufferSize, OutputTransform transformation, const QMap<uint32_t, QList<uint64_t>> &formats, const ColorDescription &colorDescription, const QVector3D &channelFactors, const std::shared_ptr<IccProfile> &iccProfile, bool enableColormanagement);
0062     bool endRendering(const QRegion &damagedRegion);
0063     std::chrono::nanoseconds queryRenderTime() const;
0064 
0065     bool doesSurfaceFit(const QSize &size, const QMap<uint32_t, QList<uint64_t>> &formats) const;
0066     std::shared_ptr<GLTexture> texture() const;
0067     void destroyResources();
0068     EglGbmBackend *eglBackend() const;
0069     std::shared_ptr<DrmFramebuffer> renderTestBuffer(const QSize &bufferSize, const QMap<uint32_t, QList<uint64_t>> &formats);
0070     void forgetDamage();
0071 
0072     std::shared_ptr<DrmFramebuffer> currentBuffer() const;
0073     const ColorDescription &colorDescription() const;
0074 
0075 private:
0076     enum class MultiGpuImportMode {
0077         None,
0078         Dmabuf,
0079         LinearDmabuf,
0080         Egl,
0081         DumbBuffer
0082     };
0083     struct Surface
0084     {
0085         ~Surface();
0086 
0087         std::shared_ptr<EglContext> context;
0088         std::shared_ptr<EglSwapchain> gbmSwapchain;
0089         std::shared_ptr<EglSwapchainSlot> currentSlot;
0090         DamageJournal damageJournal;
0091         std::unique_ptr<QPainterSwapchain> importDumbSwapchain;
0092         std::shared_ptr<EglContext> importContext;
0093         std::shared_ptr<EglSwapchain> importGbmSwapchain;
0094         QHash<GraphicsBuffer *, std::shared_ptr<GLTexture>> importedTextureCache;
0095         QImage cpuCopyCache;
0096         MultiGpuImportMode importMode;
0097         std::shared_ptr<DrmFramebuffer> currentFramebuffer;
0098         BufferTarget bufferTarget;
0099 
0100         // for color management
0101         bool colormanagementEnabled = false;
0102         std::shared_ptr<GLTexture> shadowTexture;
0103         std::unique_ptr<GLFramebuffer> shadowBuffer;
0104         ColorDescription targetColorDescription = ColorDescription::sRGB;
0105         ColorDescription intermediaryColorDescription = ColorDescription::sRGB;
0106         QVector3D channelFactors = {1, 1, 1};
0107         std::unique_ptr<IccShader> iccShader;
0108         std::shared_ptr<IccProfile> iccProfile;
0109 
0110         // for render timing
0111         std::unique_ptr<GLRenderTimeQuery> timeQuery;
0112         std::unique_ptr<GLRenderTimeQuery> importTimeQuery;
0113         std::chrono::steady_clock::time_point renderStart;
0114         std::chrono::steady_clock::time_point renderEnd;
0115     };
0116     bool checkSurface(const QSize &size, const QMap<uint32_t, QList<uint64_t>> &formats);
0117     bool doesSurfaceFit(Surface *surface, const QSize &size, const QMap<uint32_t, QList<uint64_t>> &formats) const;
0118     std::unique_ptr<Surface> createSurface(const QSize &size, const QMap<uint32_t, QList<uint64_t>> &formats) const;
0119     std::unique_ptr<Surface> createSurface(const QSize &size, uint32_t format, const QList<uint64_t> &modifiers, MultiGpuImportMode importMode, BufferTarget bufferTarget) const;
0120     std::shared_ptr<EglSwapchain> createGbmSwapchain(DrmGpu *gpu, EglContext *context, const QSize &size, uint32_t format, const QList<uint64_t> &modifiers, MultiGpuImportMode importMode, BufferTarget bufferTarget) const;
0121 
0122     std::shared_ptr<DrmFramebuffer> doRenderTestBuffer(Surface *surface) const;
0123     std::shared_ptr<DrmFramebuffer> importBuffer(Surface *surface, EglSwapchainSlot *source, const FileDescriptor &readFence) const;
0124     std::shared_ptr<DrmFramebuffer> importWithEgl(Surface *surface, GraphicsBuffer *sourceBuffer, const FileDescriptor &readFence) const;
0125     std::shared_ptr<DrmFramebuffer> importWithCpu(Surface *surface, EglSwapchainSlot *source) const;
0126 
0127     std::unique_ptr<Surface> m_surface;
0128     std::unique_ptr<Surface> m_oldSurface;
0129 
0130     DrmGpu *const m_gpu;
0131     EglGbmBackend *const m_eglBackend;
0132     const BufferTarget m_requestedBufferTarget;
0133     const FormatOption m_formatOption;
0134 };
0135 
0136 }