1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef UI_GL_GL_CONTEXT_H_
6 #define UI_GL_GL_CONTEXT_H_
7 
8 #include <map>
9 #include <memory>
10 #include <string>
11 
12 #include "base/atomicops.h"
13 #include "base/cancelable_callback.h"
14 #include "base/macros.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/synchronization/atomic_flag.h"
17 #include "build/build_config.h"
18 #include "ui/gfx/extension_set.h"
19 #include "ui/gl/gl_export.h"
20 #include "ui/gl/gl_implementation_wrapper.h"
21 #include "ui/gl/gl_share_group.h"
22 #include "ui/gl/gl_state_restorer.h"
23 #include "ui/gl/gl_workarounds.h"
24 #include "ui/gl/gpu_preference.h"
25 
26 namespace gfx {
27 class ColorSpace;
28 }  // namespace gfx
29 
30 namespace gl {
31 class YUVToRGBConverter;
32 }  // namespace gl
33 
34 namespace gpu {
35 class GLContextVirtual;
36 }  // namespace gpu
37 
38 namespace gl {
39 
40 struct CurrentGL;
41 class LogGLApi;
42 struct DriverGL;
43 class GLApi;
44 class GLFence;
45 class GLSurface;
46 class GPUTiming;
47 class GPUTimingClient;
48 struct GLVersionInfo;
49 class RealGLApi;
50 class TraceGLApi;
51 
52 // Where available, choose a GL context priority for devices that support it.
53 // Currently this requires the EGL_IMG_context_priority extension that is
54 // present on Daydream ready Android devices. Default is Medium, and the
55 // attribute is ignored if the extension is missing.
56 //
57 // "High" priority must only be used for special cases with strong realtime
58 // requirements, it is incompatible with other critical system GL work such as
59 // the GVR library's asynchronous reprojection for VR viewing. Please avoid
60 // using it for any GL contexts that may be used during VR presentation,
61 // see crbug.com/727800.
62 //
63 // Instead, consider using "Low" priority for possibly-slow GL work such as
64 // user WebGL content.
65 enum ContextPriority {
66   ContextPriorityLow,
67   ContextPriorityMedium,
68   ContextPriorityHigh
69 };
70 
71 struct GL_EXPORT GLContextAttribs {
72   GLContextAttribs();
73   GLContextAttribs(const GLContextAttribs& other);
74   GLContextAttribs(GLContextAttribs&& other);
75   ~GLContextAttribs();
76 
77   GLContextAttribs& operator=(const GLContextAttribs& other);
78   GLContextAttribs& operator=(GLContextAttribs&& other);
79 
80   GpuPreference gpu_preference = GpuPreference::kLowPower;
81   bool bind_generates_resource = true;
82   bool webgl_compatibility_context = false;
83   bool global_texture_share_group = false;
84   bool robust_resource_initialization = false;
85   bool robust_buffer_access = false;
86   int client_major_es_version = 3;
87   int client_minor_es_version = 0;
88   bool can_skip_validation = false;
89   ContextPriority context_priority = ContextPriorityMedium;
90 };
91 
92 // Encapsulates an OpenGL context, hiding platform specific management.
93 class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
94  public:
95   explicit GLContext(GLShareGroup* share_group);
96 
97   static int32_t TotalGLContexts();
98 
99   static bool SwitchableGPUsSupported();
100   // This should be called at most once at GPU process startup time.
101   // By default, GPU switching is not supported unless this is called.
102   static void SetSwitchableGPUsSupported();
103 
104   // This should be called at most once at GPU process startup time.
105   static void SetForcedGpuPreference(GpuPreference gpu_preference);
106   // If a gpu preference is forced (by GPU driver bug workaround, etc), return
107   // it. Otherwise, return the original input preference.
108   static GpuPreference AdjustGpuPreference(GpuPreference gpu_preference);
109 
110   // Initializes the GL context to be compatible with the given surface. The GL
111   // context can be made with other surface's of the same type. The compatible
112   // surface is only needed for certain platforms like WGL and GLX. It
113   // should be specific for all platforms though.
114   virtual bool Initialize(GLSurface* compatible_surface,
115                           const GLContextAttribs& attribs) = 0;
116 
117   // Makes the GL context and a surface current on the current thread.
118   virtual bool MakeCurrent(GLSurface* surface) = 0;
119 
120   // Releases this GL context and surface as current on the current thread.
121   virtual void ReleaseCurrent(GLSurface* surface) = 0;
122 
123   // Returns true if this context and surface is current. Pass a null surface
124   // if the current surface is not important.
125   virtual bool IsCurrent(GLSurface* surface) = 0;
126 
127   // Get the underlying platform specific GL context "handle".
128   virtual void* GetHandle() = 0;
129 
130   // Creates a GPUTimingClient class which abstracts various GPU Timing exts.
131   virtual scoped_refptr<GPUTimingClient> CreateGPUTimingClient() = 0;
132 
133   // Set the GL workarounds.
134   void SetGLWorkarounds(const GLWorkarounds& workarounds);
135 
136   void SetDisabledGLExtensions(const std::string& disabled_gl_extensions);
137 
138   // Gets the GLStateRestorer for the context.
139   GLStateRestorer* GetGLStateRestorer();
140 
141   // Sets the GLStateRestorer for the context (takes ownership).
142   void SetGLStateRestorer(GLStateRestorer* state_restorer);
143 
144   // Returns set of extensions. The context must be current.
145   virtual const gfx::ExtensionSet& GetExtensions() = 0;
146 
147   // Indicate that it is safe to force this context to switch GPUs, since
148   // transitioning can cause corruption and hangs (OS X only).
149   virtual void SetSafeToForceGpuSwitch();
150 
151   // Attempt to force the context to move to the GPU of its sharegroup. Return
152   // false only in the event of an unexpected error on the context.
153   virtual bool ForceGpuSwitchIfNeeded();
154 
155   // Indicate that the real context switches should unbind the FBO first
156   // (For an Android work-around only).
157   virtual void SetUnbindFboOnMakeCurrent();
158 
159   // Indicate that the context has become visible/invisible. This can be due to
160   // tab-switching, window minimization, etc.
SetVisibility(bool visibility)161   virtual void SetVisibility(bool visibility) {}
162 
163   // Returns whether the current context supports the named extension. The
164   // context must be current.
165   bool HasExtension(const char* name);
166 
167   // Returns version info of the underlying GL context. The context must be
168   // current.
169   const GLVersionInfo* GetVersionInfo();
170 
171   GLShareGroup* share_group();
172 
173   static bool LosesAllContextsOnContextLost();
174 
175   // Returns the last GLContext made current, virtual or real.
176   static GLContext* GetCurrent();
177 
178   // Returns the 'sticky' value of glGetGraphicsResetStatus, if available.
179   // 'sticky' implies that if glGetGraphicsResetStatus ever returns a value
180   // other than GL_NO_ERROR, that value is returned until the context is
181   // destroyed.
182   // The context must be current.
183   virtual unsigned int CheckStickyGraphicsResetStatus();
184 
185   // Make this context current when used for context virtualization.
186   bool MakeVirtuallyCurrent(GLContext* virtual_context, GLSurface* surface);
187 
188   // Notify this context that |virtual_context|, that was using us, is
189   // being released or destroyed.
190   void OnReleaseVirtuallyCurrent(GLContext* virtual_context);
191 
192   // Returns the GL version string. The context must be current.
193   virtual std::string GetGLVersion();
194 
195   // Returns the GL renderer string. The context must be current.
196   virtual std::string GetGLRenderer();
197 
198   // Returns a helper structure to convert the YUV color space |color_space|
199   // to its associated full-range RGB color space.
200   virtual YUVToRGBConverter* GetYUVToRGBConverter(
201       const gfx::ColorSpace& color_space);
202 
203   // Get the CurrentGL object for this context containing the driver, version
204   // and API.
205   CurrentGL* GetCurrentGL();
206 
207   // Reinitialize the dynamic bindings of this context.  Needed when the driver
208   // may be exposing different extensions compared to when it was initialized.
209   // TODO(geofflang): Try to make this call uncessessary by pre-loading all
210   // extension entry points.
211   void ReinitializeDynamicBindings();
212 
213   // Forces this context, which must be a virtual context, to be no
214   // longer considered virtually current. The real context remains
215   // current.
216   virtual void ForceReleaseVirtuallyCurrent();
217 
218   // Indicates that some GL state was modified that was not tracked by virtual
219   // contexts. Forces full reset from unknown state the next time a virtual
220   // context is made current.
221   void DirtyVirtualContextState();
222 
223 #if defined(OS_MACOSX)
224   // Create a fence for all work submitted to this context so far, and return a
225   // monotonically increasing handle to it. This returned handle never needs to
226   // be freed. This method is used to create backpressure to throttle GL work
227   // on macOS, so that we do not starve CoreAnimation.
228   virtual uint64_t BackpressureFenceCreate();
229   // Perform a client-side wait on a previously-created fence.
230   virtual void BackpressureFenceWait(uint64_t fence);
231   // Flush the underlying context to avoid crashes due to driver bugs on macOS.
232   // https://crbug.com/863817
233   virtual void FlushForDriverCrashWorkaround();
234 #endif
235 
236  protected:
237   virtual ~GLContext();
238 
239   // Create the GLApi for this context using the provided driver. Creates a
240   // RealGLApi by default.
241   virtual GLApi* CreateGLApi(DriverGL* driver);
242 
243   // Will release the current context when going out of scope, unless canceled.
244   class ScopedReleaseCurrent {
245    public:
246     ScopedReleaseCurrent();
247     ~ScopedReleaseCurrent();
248 
249     void Cancel();
250 
251    private:
252     bool canceled_;
253   };
254 
255   // Sets the GL api to the real hardware API (vs the VirtualAPI)
256   void BindGLApi();
257   virtual void SetCurrent(GLSurface* surface);
258 
259   // Initialize function pointers to functions where the bound version depends
260   // on GL version or supported extensions. Should be called immediately after
261   // this context is made current.
262   void InitializeDynamicBindings();
263 
264   // Returns the last real (non-virtual) GLContext made current.
265   static GLContext* GetRealCurrent();
266 
267   virtual void ResetExtensions() = 0;
268 
gl_api()269   GLApi* gl_api() { return gl_api_wrapper_->api(); }
270 
271 #if defined(OS_MACOSX)
272   // Child classes are responsible for calling DestroyBackpressureFences during
273   // their destruction while a context is current.
274   bool HasBackpressureFences() const;
275   void DestroyBackpressureFences();
276 #endif
277 
278  private:
279   friend class base::RefCounted<GLContext>;
280 
281   // For GetRealCurrent.
282   friend class gpu::GLContextVirtual;
283 
284   std::unique_ptr<GLVersionInfo> GenerateGLVersionInfo();
285 
286   static base::subtle::Atomic32 total_gl_contexts_;
287 
288   static bool switchable_gpus_supported_;
289 
290   static GpuPreference forced_gpu_preference_;
291 
292   GLWorkarounds gl_workarounds_;
293   std::string disabled_gl_extensions_;
294 
295   bool static_bindings_initialized_ = false;
296   bool dynamic_bindings_initialized_ = false;
297   std::unique_ptr<DriverGL> driver_gl_;
298 
299   std::unique_ptr<GL_IMPL_WRAPPER_TYPE(GL)> gl_api_wrapper_;
300   std::unique_ptr<CurrentGL> current_gl_;
301 
302   // Copy of the real API (if one was created) for dynamic initialization
303   RealGLApi* real_gl_api_ = nullptr;
304 
305   scoped_refptr<GLShareGroup> share_group_;
306   GLContext* current_virtual_context_ = nullptr;
307   bool state_dirtied_externally_ = false;
308   std::unique_ptr<GLStateRestorer> state_restorer_;
309   std::unique_ptr<GLVersionInfo> version_info_;
310 
311 #if defined(OS_MACOSX)
312   std::map<uint64_t, std::unique_ptr<GLFence>> backpressure_fences_;
313   uint64_t next_backpressure_fence_ = 0;
314 #endif
315 
316   DISALLOW_COPY_AND_ASSIGN(GLContext);
317 };
318 
319 class GL_EXPORT GLContextReal : public GLContext {
320  public:
321   explicit GLContextReal(GLShareGroup* share_group);
322   scoped_refptr<GPUTimingClient> CreateGPUTimingClient() override;
323   const gfx::ExtensionSet& GetExtensions() override;
324 
325  protected:
326   ~GLContextReal() override;
327 
328   void ResetExtensions() override;
329 
330   void SetCurrent(GLSurface* surface) override;
331   void SetExtensionsFromString(std::string extensions);
extension_string()332   const std::string& extension_string() { return extensions_string_; }
333 
334  private:
335   std::unique_ptr<GPUTiming> gpu_timing_;
336   std::string extensions_string_;
337   gfx::ExtensionSet extensions_;
338   bool extensions_initialized_ = false;
339   DISALLOW_COPY_AND_ASSIGN(GLContextReal);
340 };
341 
342 // Wraps GLContext in scoped_refptr and tries to initializes it. Returns a
343 // scoped_refptr containing the initialized GLContext or nullptr if
344 // initialization fails.
345 GL_EXPORT scoped_refptr<GLContext> InitializeGLContext(
346     scoped_refptr<GLContext> context,
347     GLSurface* compatible_surface,
348     const GLContextAttribs& attribs);
349 
350 }  // namespace gl
351 
352 #endif  // UI_GL_GL_CONTEXT_H_
353