Overte C++ Documentation
OpenGLDisplayPlugin.h
1 //
2 // Created by Bradley Austin Davis on 2015/05/29
3 // Copyright 2015 High Fidelity, Inc.
4 //
5 // Distributed under the Apache License, Version 2.0.
6 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
7 //
8 #pragma once
9 
10 #include "DisplayPlugin.h"
11 
12 #include <condition_variable>
13 #include <memory>
14 #include <queue>
15 
16 #include <QtCore/QThread>
17 #include <QtCore/QTimer>
18 #include <QtGui/QImage>
19 
20 #include <GLMHelpers.h>
21 #include <SimpleMovingAverage.h>
22 #include <shared/RateCounter.h>
23 
24 #include <gpu/Batch.h>
25 
26 namespace gpu { namespace gl {
27 class GLBackend;
28 }} // namespace gpu::gl
29 
30 class RefreshRateController;
31 
32 class OpenGLDisplayPlugin : public DisplayPlugin {
33  Q_OBJECT
34  Q_PROPERTY(float hudAlpha MEMBER _hudAlpha)
35  using Parent = DisplayPlugin;
36 
37 protected:
38  using Mutex = std::mutex;
39  using Lock = std::unique_lock<Mutex>;
40  using Condition = std::condition_variable;
41 
42 public:
43  ~OpenGLDisplayPlugin();
44  // These must be final to ensure proper ordering of operations
45  // between the main thread and the presentation thread
46 
47  static std::function<void(int)> getRefreshRateOperator();
48 
49  bool activate() override final;
50  void deactivate() override final;
51  bool startStandBySession() override final;
52  void endSession() override final;
53  bool eventFilter(QObject* receiver, QEvent* event) override;
54  bool isDisplayVisible() const override { return true; }
55  void captureFrame(const std::string& outputName) const override;
56  void submitFrame(const gpu::FramePointer& newFrame) override;
57 
58  glm::uvec2 getRecommendedRenderSize() const override { return getSurfacePixels(); }
59 
60  glm::uvec2 getRecommendedUiSize() const override { return getSurfaceSize(); }
61 
62  virtual bool setDisplayTexture(const QString& name) override;
63  virtual bool onDisplayTextureReset() { return false; };
64 
65  float presentRate() const override;
66 
67  void resetPresentRate() override;
68 
69  float newFramePresentRate() const override;
70 
71  float droppedFrameRate() const override;
72 
73  float renderRate() const override;
74 
75  bool beginFrameRender(uint32_t frameIndex) override;
76 
77  virtual bool wantVsync() const { return true; }
78  void setVsyncEnabled(bool vsyncEnabled) { _vsyncEnabled = vsyncEnabled; }
79  bool isVsyncEnabled() const { return _vsyncEnabled; }
80  // Three threads, one for rendering, one for texture transfers, one reserved for the GL driver
81  // Drop to one reserved for better other-task performance in desktop
82  int getRequiredThreadCount() const override { return 1; }
83 
84  virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator() override;
85  void copyTextureToQuickFramebuffer(NetworkTexturePointer source,
86  QOpenGLFramebufferObject* target,
87  GLsync* fenceSync) override;
88 
89 protected:
90  friend class PresentThread;
91 
92  glm::uvec2 getSurfaceSize() const;
93  glm::uvec2 getSurfacePixels() const;
94  // Some display plugins require us to always execute some present logic,
95  // whether we have a frame or not (Oculus Mobile plugin)
96  // Such plugins must be prepared to do the right thing if the `_currentFrame`
97  // is not populated
98  virtual bool alwaysPresent() const { return false; }
99 
100  void updateCompositeFramebuffer();
101 
102  virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; }
103  virtual void compositeLayers();
104  virtual void setupCompositeScenePipeline(gpu::Batch& batch);
105  virtual void compositeScene();
106  virtual void compositePointer();
107  virtual void compositeExtra(){};
108 
109  // These functions must only be called on the presentation thread
110  virtual void customizeContext();
111  virtual void uncustomizeContext();
112 
113  // Returns true on successful activation
114  virtual bool internalActivate() { return true; }
115  virtual void internalDeactivate() {}
116 
117  // Returns true on successful activation of standby session
118  virtual bool activateStandBySession() { return true; }
119  virtual void deactivateSession() {}
120 
121  // Plugin specific functionality to send the composed scene to the output window or device
122  virtual void internalPresent();
123 
124  void renderFromTexture(gpu::Batch& batch,
125  const gpu::TexturePointer& texture,
126  const glm::ivec4& viewport,
127  const glm::ivec4& scissor,
128  const gpu::FramebufferPointer& fbo);
129  void renderFromTexture(gpu::Batch& batch,
130  const gpu::TexturePointer& texture,
131  const glm::ivec4& viewport,
132  const glm::ivec4& scissor);
133  virtual void updateFrameData();
134  virtual glm::mat4 getViewCorrection() { return glm::mat4(); }
135 
136  void withOtherThreadContext(std::function<void()> f) const;
137 
138  void present(const std::shared_ptr<RefreshRateController>& refreshRateController);
139  virtual void swapBuffers();
140 
141  void render(std::function<void(gpu::Batch& batch)> f);
142 
143  bool _vsyncEnabled{ true };
144  QThread* _presentThread{ nullptr };
145  std::queue<gpu::FramePointer> _newFrameQueue;
146  RateCounter<200> _droppedFrameRate;
147  RateCounter<200> _newFrameRate;
148  RateCounter<200> _presentRate;
149  RateCounter<200> _renderRate;
150 
151  gpu::FramePointer _currentFrame;
152  gpu::Frame* _lastFrame{ nullptr };
153  mat4 _prevRenderView;
154  gpu::FramebufferPointer _compositeFramebuffer;
155  gpu::PipelinePointer _hudPipeline;
156  gpu::PipelinePointer _mirrorHUDPipeline;
157  gpu::ShaderPointer _mirrorHUDPS;
158  gpu::PipelinePointer _drawTexturePipeline;
159  gpu::PipelinePointer _drawTextureSqueezePipeline;
160  gpu::PipelinePointer _linearToSRGBPipeline;
161  gpu::PipelinePointer _SRGBToLinearPipeline;
162  gpu::PipelinePointer _cursorPipeline;
163  gpu::TexturePointer _displayTexture{};
164  float _compositeHUDAlpha{ 1.0f };
165 
166  virtual gpu::PipelinePointer getRenderTexturePipeline();
167 
168  struct CursorData {
169  QImage image;
170  vec2 hotSpot;
171  uvec2 size;
172  gpu::TexturePointer texture;
173  };
174 
175  std::map<uint16_t, CursorData> _cursorsData;
176  bool _lockCurrentTexture{ false };
177 
178  void assertNotPresentThread() const;
179  void assertIsPresentThread() const;
180 
181  template <typename F>
182  void withPresentThreadLock(F f) const {
183  assertIsPresentThread();
184  Lock lock(_presentMutex);
185  f();
186  }
187 
188  template <typename F>
189  void withNonPresentThreadLock(F f) const {
190  assertNotPresentThread();
191  Lock lock(_presentMutex);
192  f();
193  }
194 
195  gpu::gl::GLBackend* getGLBackend();
196 
197  // Any resource shared by the main thread and the presentation thread must
198  // be serialized through this mutex
199  mutable Mutex _presentMutex;
200  float _hudAlpha{ 1.0f };
201 
202  QImage getScreenshot(float aspectRatio);
203  QImage getSecondaryCameraScreenshot();
204 };