#include "ui/gl/gl_context.h"
#include <string>
#include "base/cancelable_callback.h"
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/string_util.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "third_party/abseil-cpp/absl/base/attributes.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_switches.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/gpu_timing.h"
#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#endif
namespace gl {
namespace {
#if BUILDFLAG(IS_ANDROID)
enum class MaximumGLESVersion {
kGLES2_0 = 0,
kGLES3_0 = 1,
kGLES3_1 = 2,
kGLES3_2 = 3,
kMaxValue = kGLES3_2
};
#endif
ABSL_CONST_INIT thread_local GLContext* current_context = …;
ABSL_CONST_INIT thread_local GLContext* current_real_context = …;
}
base::subtle::Atomic32 GLContext::total_gl_contexts_ = …;
bool GLContext::switchable_gpus_supported_ = …;
GLContext::ScopedReleaseCurrent::ScopedReleaseCurrent() : … { … }
GLContext::ScopedReleaseCurrent::~ScopedReleaseCurrent() { … }
void GLContext::ScopedReleaseCurrent::Cancel() { … }
GLContextAttribs::GLContextAttribs() = default;
GLContextAttribs::GLContextAttribs(const GLContextAttribs& other) = default;
GLContextAttribs::GLContextAttribs(GLContextAttribs&& other) = default;
GLContextAttribs::~GLContextAttribs() = default;
GLContextAttribs& GLContextAttribs::operator=(const GLContextAttribs& other) =
default;
GLContextAttribs& GLContextAttribs::operator=(GLContextAttribs&& other) =
default;
GLContext::GLContext(GLShareGroup* share_group) : … { … }
GLContext::~GLContext() { … }
int32_t GLContext::TotalGLContexts() { … }
bool GLContext::SwitchableGPUsSupported() { … }
void GLContext::SetSwitchableGPUsSupported() { … }
bool GLContext::Initialize(GLSurface* compatible_surface,
const GLContextAttribs& attribs) { … }
bool GLContext::MakeCurrent(GLSurface* surface) { … }
bool GLContext::MakeCurrentDefault() { … }
base::WeakPtr<GLContext> GLContext::AsWeakPtr() { … }
void GLContext::AddObserver(GLContextObserver* observer) { … }
void GLContext::RemoveObserver(GLContextObserver* observer) { … }
bool GLContext::CanShareTexturesWithContext(GLContext* other_context) { … }
GLApi* GLContext::CreateGLApi(DriverGL* driver) { … }
void GLContext::SetSafeToForceGpuSwitch() { … }
bool GLContext::ForceGpuSwitchIfNeeded() { … }
void GLContext::SetUnbindFboOnMakeCurrent() { … }
std::string GLContext::GetGLVersion() { … }
std::string GLContext::GetGLRenderer() { … }
CurrentGL* GLContext::GetCurrentGL() { … }
void GLContext::ReinitializeDynamicBindings() { … }
void GLContext::ForceReleaseVirtuallyCurrent() { … }
void GLContext::DirtyVirtualContextState() { … }
GLDisplayEGL* GLContext::GetGLDisplayEGL() { … }
GLContextEGL* GLContext::AsGLContextEGL() { … }
#if BUILDFLAG(IS_APPLE)
constexpr uint64_t kInvalidFenceId = 0;
void GLContext::AddMetalSharedEventsForBackpressure(
std::vector<std::unique_ptr<gpu::BackpressureMetalSharedEvent>> events) {
for (auto& e : events) {
next_backpressure_events_.push_back(std::move(e));
}
}
uint64_t GLContext::BackpressureFenceCreate() {
TRACE_EVENT0("gpu", "GLContext::BackpressureFenceCreate");
std::vector<std::unique_ptr<gpu::BackpressureMetalSharedEvent>>
backpressure_events = std::move(next_backpressure_events_);
if (gl::GetANGLEImplementation() == gl::ANGLEImplementation::kMetal) {
backpressure_fences_[++next_backpressure_fence_] = {
nullptr, std::move(backpressure_events)};
return next_backpressure_fence_;
} else if (gl::GLFence::IsSupported()) {
glFlush();
backpressure_fences_[++next_backpressure_fence_] = {
GLFence::Create(), std::move(backpressure_events)};
return next_backpressure_fence_;
} else {
glFinish();
return kInvalidFenceId;
}
}
void GLContext::BackpressureFenceWait(uint64_t fence_id) {
TRACE_EVENT0("gpu", "GLContext::BackpressureFenceWait");
if (fence_id == kInvalidFenceId) {
return;
}
auto it = backpressure_fences_.find(fence_id);
if (it == backpressure_fences_.end()) {
return;
}
auto [fence, events] = std::move(it->second);
backpressure_fences_.erase(it);
bool events_complete = false;
while (!events_complete) {
events_complete = true;
{
TRACE_EVENT0("gpu", "BackpressureMetalSharedEvent::HasCompleted");
for (const auto& e : events) {
if (!e->HasCompleted()) {
events_complete = false;
break;
}
}
}
if (!events_complete) {
base::PlatformThread::Sleep(base::Milliseconds(1));
}
}
if (fence) {
fence->ClientWait();
fence.reset();
}
while (!backpressure_fences_.empty() &&
backpressure_fences_.begin()->first < fence_id) {
backpressure_fences_.erase(backpressure_fences_.begin());
}
}
bool GLContext::HasBackpressureFences() const {
return !backpressure_fences_.empty();
}
void GLContext::DestroyBackpressureFences() {
backpressure_fences_.clear();
}
#endif
#if BUILDFLAG(IS_MAC)
void GLContext::FlushForDriverCrashWorkaround() {
static const bool needs_flush =
base::mac::GetCPUType() == base::mac::CPUType::kIntel;
if (!needs_flush || !IsCurrent(nullptr))
return;
TRACE_EVENT0("gpu", "GLContext::FlushForDriverCrashWorkaround");
glFlush();
}
#endif
bool GLContext::HasExtension(const char* name) { … }
const GLVersionInfo* GLContext::GetVersionInfo() { … }
GLShareGroup* GLContext::share_group() { … }
bool GLContext::LosesAllContextsOnContextLost() { … }
GLContext* GLContext::GetCurrent() { … }
GLContext* GLContext::GetRealCurrent() { … }
void GLContext::OnContextWillDestroy() { … }
std::unique_ptr<gl::GLVersionInfo> GLContext::GenerateGLVersionInfo() { … }
void GLContext::MarkContextLost() { … }
void GLContext::SetCurrent(GLSurface* surface) { … }
void GLContext::SetDisabledGLExtensions(
const std::string& disabled_extensions) { … }
GLStateRestorer* GLContext::GetGLStateRestorer() { … }
void GLContext::SetGLStateRestorer(GLStateRestorer* state_restorer) { … }
GLenum GLContext::CheckStickyGraphicsResetStatus() { … }
GLenum GLContext::CheckStickyGraphicsResetStatusImpl() { … }
void GLContext::InitializeDynamicBindings() { … }
bool GLContext::MakeVirtuallyCurrent(
GLContext* virtual_context, GLSurface* surface) { … }
void GLContext::OnReleaseVirtuallyCurrent(GLContext* virtual_context) { … }
void GLContext::BindGLApi() { … }
GLContextReal::GLContextReal(GLShareGroup* share_group)
: … { … }
scoped_refptr<GPUTimingClient> GLContextReal::CreateGPUTimingClient() { … }
const gfx::ExtensionSet& GLContextReal::GetExtensions() { … }
GLContextReal::~GLContextReal() { … }
void GLContextReal::SetCurrent(GLSurface* surface) { … }
scoped_refptr<GLContext> InitializeGLContext(scoped_refptr<GLContext> context,
GLSurface* compatible_surface,
const GLContextAttribs& attribs) { … }
void GLContextReal::SetExtensionsFromString(std::string extensions) { … }
void GLContextReal::ResetExtensions() { … }
}