mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
258 lines
6.7 KiB
C++
258 lines
6.7 KiB
C++
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include <string>
|
|
|
|
#include "base/bind.h"
|
|
#include "base/cancelable_callback.h"
|
|
#include "base/command_line.h"
|
|
#include "base/lazy_instance.h"
|
|
#include "base/logging.h"
|
|
#include "base/threading/thread_local.h"
|
|
#include "ui/gl/gl_bindings.h"
|
|
#include "ui/gl/gl_context.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"
|
|
|
|
namespace gfx {
|
|
|
|
namespace {
|
|
base::LazyInstance<base::ThreadLocalPointer<GLContext> >::Leaky
|
|
current_context_ = LAZY_INSTANCE_INITIALIZER;
|
|
|
|
base::LazyInstance<base::ThreadLocalPointer<GLContext> >::Leaky
|
|
current_real_context_ = LAZY_INSTANCE_INITIALIZER;
|
|
} // namespace
|
|
|
|
GLContext::ScopedReleaseCurrent::ScopedReleaseCurrent() : canceled_(false) {}
|
|
|
|
GLContext::ScopedReleaseCurrent::~ScopedReleaseCurrent() {
|
|
if (!canceled_ && GetCurrent()) {
|
|
GetCurrent()->ReleaseCurrent(NULL);
|
|
}
|
|
}
|
|
|
|
void GLContext::ScopedReleaseCurrent::Cancel() {
|
|
canceled_ = true;
|
|
}
|
|
|
|
GLContext::GLContext(GLShareGroup* share_group) :
|
|
share_group_(share_group),
|
|
state_dirtied_externally_(false),
|
|
swap_interval_(1),
|
|
force_swap_interval_zero_(false),
|
|
state_dirtied_callback_(
|
|
base::Bind(&GLContext::SetStateWasDirtiedExternally,
|
|
// Note that if this is not unretained, it will create a cycle (and
|
|
// will never be freed.
|
|
base::Unretained(this),
|
|
true)) {
|
|
if (!share_group_.get())
|
|
share_group_ = new GLShareGroup;
|
|
|
|
share_group_->AddContext(this);
|
|
}
|
|
|
|
GLContext::~GLContext() {
|
|
share_group_->RemoveContext(this);
|
|
if (GetCurrent() == this) {
|
|
SetCurrent(NULL);
|
|
}
|
|
}
|
|
|
|
bool GLContext::GetTotalGpuMemory(size_t* bytes) {
|
|
DCHECK(bytes);
|
|
*bytes = 0;
|
|
return false;
|
|
}
|
|
|
|
void GLContext::SetSafeToForceGpuSwitch() {
|
|
}
|
|
|
|
bool GLContext::ForceGpuSwitchIfNeeded() {
|
|
return true;
|
|
}
|
|
|
|
void GLContext::SetUnbindFboOnMakeCurrent() {
|
|
NOTIMPLEMENTED();
|
|
}
|
|
|
|
std::string GLContext::GetExtensions() {
|
|
DCHECK(IsCurrent(NULL));
|
|
const char* ext = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
|
return std::string(ext ? ext : "");
|
|
}
|
|
|
|
std::string GLContext::GetGLVersion() {
|
|
DCHECK(IsCurrent(NULL));
|
|
const char *version =
|
|
reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
|
return std::string(version ? version : "");
|
|
}
|
|
|
|
std::string GLContext::GetGLRenderer() {
|
|
DCHECK(IsCurrent(NULL));
|
|
const char *renderer =
|
|
reinterpret_cast<const char*>(glGetString(GL_RENDERER));
|
|
return std::string(renderer ? renderer : "");
|
|
}
|
|
|
|
base::Closure GLContext::GetStateWasDirtiedExternallyCallback() {
|
|
return state_dirtied_callback_.callback();
|
|
}
|
|
|
|
void GLContext::RestoreStateIfDirtiedExternally() {
|
|
NOTREACHED();
|
|
}
|
|
|
|
bool GLContext::GetStateWasDirtiedExternally() const {
|
|
DCHECK(virtual_gl_api_);
|
|
return state_dirtied_externally_;
|
|
}
|
|
|
|
void GLContext::SetStateWasDirtiedExternally(bool dirtied_externally) {
|
|
DCHECK(virtual_gl_api_);
|
|
state_dirtied_externally_ = dirtied_externally;
|
|
}
|
|
|
|
bool GLContext::HasExtension(const char* name) {
|
|
std::string extensions = GetExtensions();
|
|
extensions += " ";
|
|
|
|
std::string delimited_name(name);
|
|
delimited_name += " ";
|
|
|
|
return extensions.find(delimited_name) != std::string::npos;
|
|
}
|
|
|
|
const GLVersionInfo* GLContext::GetVersionInfo() {
|
|
if(!version_info_) {
|
|
std::string version = GetGLVersion();
|
|
std::string renderer = GetGLRenderer();
|
|
version_info_ =
|
|
make_scoped_ptr(new GLVersionInfo(version.c_str(), renderer.c_str()));
|
|
}
|
|
return version_info_.get();
|
|
}
|
|
|
|
GLShareGroup* GLContext::share_group() {
|
|
return share_group_.get();
|
|
}
|
|
|
|
bool GLContext::LosesAllContextsOnContextLost() {
|
|
switch (GetGLImplementation()) {
|
|
case kGLImplementationDesktopGL:
|
|
return false;
|
|
case kGLImplementationEGLGLES2:
|
|
return true;
|
|
case kGLImplementationOSMesaGL:
|
|
case kGLImplementationAppleGL:
|
|
return false;
|
|
case kGLImplementationMockGL:
|
|
return false;
|
|
default:
|
|
NOTREACHED();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
GLContext* GLContext::GetCurrent() {
|
|
return current_context_.Pointer()->Get();
|
|
}
|
|
|
|
GLContext* GLContext::GetRealCurrent() {
|
|
return current_real_context_.Pointer()->Get();
|
|
}
|
|
|
|
void GLContext::SetCurrent(GLSurface* surface) {
|
|
current_context_.Pointer()->Set(surface ? this : NULL);
|
|
GLSurface::SetCurrent(surface);
|
|
// Leave the real GL api current so that unit tests work correctly.
|
|
// TODO(sievers): Remove this, but needs all gpu_unittest classes
|
|
// to create and make current a context.
|
|
if (!surface && GetGLImplementation() != kGLImplementationMockGL) {
|
|
SetGLApiToNoContext();
|
|
}
|
|
}
|
|
|
|
GLStateRestorer* GLContext::GetGLStateRestorer() {
|
|
return state_restorer_.get();
|
|
}
|
|
|
|
void GLContext::SetGLStateRestorer(GLStateRestorer* state_restorer) {
|
|
state_restorer_ = make_scoped_ptr(state_restorer);
|
|
}
|
|
|
|
void GLContext::SetSwapInterval(int interval) {
|
|
swap_interval_ = interval;
|
|
OnSetSwapInterval(force_swap_interval_zero_ ? 0 : swap_interval_);
|
|
}
|
|
|
|
void GLContext::ForceSwapIntervalZero(bool force) {
|
|
force_swap_interval_zero_ = force;
|
|
OnSetSwapInterval(force_swap_interval_zero_ ? 0 : swap_interval_);
|
|
}
|
|
|
|
bool GLContext::WasAllocatedUsingRobustnessExtension() {
|
|
return false;
|
|
}
|
|
|
|
bool GLContext::InitializeDynamicBindings() {
|
|
DCHECK(IsCurrent(NULL));
|
|
static bool initialized = false;
|
|
if (initialized)
|
|
return initialized;
|
|
initialized = InitializeDynamicGLBindings(GetGLImplementation(), this);
|
|
if (!initialized)
|
|
LOG(ERROR) << "Could not initialize dynamic bindings.";
|
|
return initialized;
|
|
}
|
|
|
|
void GLContext::SetupForVirtualization() {
|
|
if (!virtual_gl_api_) {
|
|
virtual_gl_api_.reset(new VirtualGLApi());
|
|
virtual_gl_api_->Initialize(&g_driver_gl, this);
|
|
}
|
|
}
|
|
|
|
bool GLContext::MakeVirtuallyCurrent(
|
|
GLContext* virtual_context, GLSurface* surface) {
|
|
DCHECK(virtual_gl_api_);
|
|
if (!ForceGpuSwitchIfNeeded())
|
|
return false;
|
|
return virtual_gl_api_->MakeCurrent(virtual_context, surface);
|
|
}
|
|
|
|
void GLContext::OnReleaseVirtuallyCurrent(GLContext* virtual_context) {
|
|
if (virtual_gl_api_)
|
|
virtual_gl_api_->OnReleaseVirtuallyCurrent(virtual_context);
|
|
}
|
|
|
|
void GLContext::SetRealGLApi() {
|
|
SetGLToRealGLApi();
|
|
}
|
|
|
|
GLContextReal::GLContextReal(GLShareGroup* share_group)
|
|
: GLContext(share_group) {}
|
|
|
|
scoped_refptr<gfx::GPUTimingClient> GLContextReal::CreateGPUTimingClient() {
|
|
if (!gpu_timing_) {
|
|
gpu_timing_.reset(new gfx::GPUTiming(this));
|
|
}
|
|
return gpu_timing_->CreateGPUTimingClient();
|
|
}
|
|
|
|
GLContextReal::~GLContextReal() {}
|
|
|
|
void GLContextReal::SetCurrent(GLSurface* surface) {
|
|
GLContext::SetCurrent(surface);
|
|
current_real_context_.Pointer()->Set(surface ? this : NULL);
|
|
}
|
|
|
|
} // namespace gfx
|