summaryrefslogtreecommitdiffstats
path: root/gfx/layers/SurfacePoolWayland.h
blob: 6a746e732cd7ba7cc05f7b5de5681caff0eae8e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_layers_SurfacePoolWayland_h
#define mozilla_layers_SurfacePoolWayland_h

#include <wayland-egl.h>

#include "GLContext.h"
#include "MozFramebuffer.h"
#include "mozilla/layers/SurfacePool.h"
#include "mozilla/widget/WaylandBuffer.h"

#include <unordered_map>

namespace mozilla::layers {

class SurfacePoolWayland final : public SurfacePool {
 public:
  // Get a handle for a new window. aGL can be nullptr.
  RefPtr<SurfacePoolHandle> GetHandleForGL(gl::GLContext* aGL) override;

  // Destroy all GL resources associated with aGL managed by this pool.
  void DestroyGLResourcesForContext(gl::GLContext* aGL) override;

 private:
  friend class SurfacePoolHandleWayland;
  friend RefPtr<SurfacePool> SurfacePool::Create(size_t aPoolSizeLimit);

  explicit SurfacePoolWayland(size_t aPoolSizeLimit);

  RefPtr<widget::WaylandBuffer> ObtainBufferFromPool(const gfx::IntSize& aSize,
                                                     gl::GLContext* aGL);
  void ReturnBufferToPool(const RefPtr<widget::WaylandBuffer>& aBuffer);
  void EnforcePoolSizeLimit();
  void CollectPendingSurfaces();
  Maybe<GLuint> GetFramebufferForBuffer(
      const RefPtr<widget::WaylandBuffer>& aBuffer, gl::GLContext* aGL,
      bool aNeedsDepthBuffer);

  struct GLResourcesForBuffer final {
    RefPtr<gl::GLContext> mGL;                   // non-null
    UniquePtr<gl::MozFramebuffer> mFramebuffer;  // non-null
  };

  struct SurfacePoolEntry final {
    const gfx::IntSize mSize;
    const RefPtr<widget::WaylandBuffer> mWaylandBuffer;  // non-null
    Maybe<GLResourcesForBuffer> mGLResources;
  };

  bool CanRecycleSurfaceForRequest(const MutexAutoLock& aProofOfLock,
                                   const SurfacePoolEntry& aEntry,
                                   const gfx::IntSize& aSize,
                                   gl::GLContext* aGL);

  RefPtr<gl::DepthAndStencilBuffer> GetDepthBufferForSharing(
      const MutexAutoLock& aProofOfLock, gl::GLContext* aGL,
      const gfx::IntSize& aSize);
  UniquePtr<gl::MozFramebuffer> CreateFramebufferForTexture(
      const MutexAutoLock& aProofOfLock, gl::GLContext* aGL,
      const gfx::IntSize& aSize, GLuint aTexture, bool aNeedsDepthBuffer);

  Mutex mMutex MOZ_UNANNOTATED;

  // Stores the entries for surfaces that are in use by NativeLayerWayland, i.e.
  // an entry is inside mInUseEntries between calls to ObtainSurfaceFromPool()
  // and ReturnSurfaceToPool().
  std::unordered_map<widget::WaylandBuffer*, SurfacePoolEntry> mInUseEntries;

  // Stores entries which are no longer in use by NativeLayerWayland but are
  // still in use by the window server, i.e. for which
  // WaylandBuffer::IsAttached() still returns true.
  // These entries are checked once per frame inside
  // CollectPendingSurfaces(), and returned to mAvailableEntries once the
  // window server is done.
  nsTArray<SurfacePoolEntry> mPendingEntries;

  // Stores entries which are available for recycling. These entries are not
  // in use by a NativeLayerWayland or by the window server.
  nsTArray<SurfacePoolEntry> mAvailableEntries;
  size_t mPoolSizeLimit;

  template <typename F>
  void ForEachEntry(F aFn);

  struct DepthBufferEntry final {
    RefPtr<gl::GLContext> mGL;
    gfx::IntSize mSize;
    WeakPtr<gl::DepthAndStencilBuffer> mBuffer;
  };

  nsTArray<DepthBufferEntry> mDepthBuffers;
};

// A surface pool handle that is stored on NativeLayerWayland and keeps the
// SurfacePool alive.
class SurfacePoolHandleWayland final : public SurfacePoolHandle {
 public:
  SurfacePoolHandleWayland* AsSurfacePoolHandleWayland() override {
    return this;
  }

  RefPtr<widget::WaylandBuffer> ObtainBufferFromPool(const gfx::IntSize& aSize);
  void ReturnBufferToPool(const RefPtr<widget::WaylandBuffer>& aBuffer);
  Maybe<GLuint> GetFramebufferForBuffer(
      const RefPtr<widget::WaylandBuffer>& aBuffer, bool aNeedsDepthBuffer);
  const auto& gl() { return mGL; }

  RefPtr<SurfacePool> Pool() override { return mPool; }
  void OnBeginFrame() override;
  void OnEndFrame() override;

 private:
  friend class SurfacePoolWayland;
  SurfacePoolHandleWayland(RefPtr<SurfacePoolWayland> aPool,
                           gl::GLContext* aGL);

  const RefPtr<SurfacePoolWayland> mPool;
  const RefPtr<gl::GLContext> mGL;
};

}  // namespace mozilla::layers

#endif