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