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