Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / ui / gl / gl_gl_api_implementation.cc
blob303ae1d1f8aa4f82aba7497f8d72c62c616aef1f
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.
5 #include "ui/gl/gl_gl_api_implementation.h"
7 #include <algorithm>
8 #include <vector>
10 #include "base/command_line.h"
11 #include "base/string_util.h"
12 #include "ui/gl/gl_context.h"
13 #include "ui/gl/gl_state_restorer.h"
14 #include "ui/gl/gl_surface.h"
15 #include "ui/gl/gl_switches.h"
17 namespace gfx {
19 // The GL Api being used. This could be g_real_gl or gl_trace_gl
20 static GLApi* g_gl;
21 // A GL Api that calls directly into the driver.
22 static RealGLApi* g_real_gl;
23 // A GL Api that calls TRACE and then calls another GL api.
24 static TraceGLApi* g_trace_gl;
26 void InitializeGLBindingsGL() {
27 g_driver_gl.InitializeBindings();
28 if (!g_real_gl) {
29 g_real_gl = new RealGLApi();
30 g_trace_gl = new TraceGLApi(g_real_gl);
32 g_real_gl->Initialize(&g_driver_gl);
33 g_gl = g_real_gl;
34 if (CommandLine::ForCurrentProcess()->HasSwitch(
35 switches::kEnableGPUServiceTracing)) {
36 g_gl = g_trace_gl;
38 SetGLToRealGLApi();
41 GLApi* GetCurrentGLApi() {
42 return g_current_gl_context;
45 void SetGLApi(GLApi* api) {
46 g_current_gl_context = api;
49 void SetGLToRealGLApi() {
50 SetGLApi(g_gl);
53 void InitializeGLExtensionBindingsGL(GLContext* context) {
54 g_driver_gl.InitializeExtensionBindings(context);
57 void InitializeDebugGLBindingsGL() {
58 g_driver_gl.InitializeDebugBindings();
61 void ClearGLBindingsGL() {
62 if (g_real_gl) {
63 delete g_real_gl;
64 g_real_gl = NULL;
66 if (g_trace_gl) {
67 delete g_trace_gl;
68 g_trace_gl = NULL;
70 g_gl = NULL;
71 g_current_gl_context = NULL;
72 g_driver_gl.ClearBindings();
75 GLApi::GLApi() {
78 GLApi::~GLApi() {
81 GLApiBase::GLApiBase()
82 : driver_(NULL) {
85 GLApiBase::~GLApiBase() {
88 void GLApiBase::InitializeBase(DriverGL* driver) {
89 driver_ = driver;
92 RealGLApi::RealGLApi() {
95 RealGLApi::~RealGLApi() {
98 void RealGLApi::Initialize(DriverGL* driver) {
99 InitializeBase(driver);
102 TraceGLApi::~TraceGLApi() {
105 VirtualGLApi::VirtualGLApi()
106 : real_context_(NULL),
107 current_context_(NULL) {
110 VirtualGLApi::~VirtualGLApi() {
113 void VirtualGLApi::Initialize(DriverGL* driver, GLContext* real_context) {
114 InitializeBase(driver);
115 real_context_ = real_context;
117 DCHECK(real_context->IsCurrent(NULL));
118 std::string ext_string(
119 reinterpret_cast<const char*>(driver_->fn.glGetStringFn(GL_EXTENSIONS)));
120 std::vector<std::string> ext;
121 Tokenize(ext_string, " ", &ext);
123 std::vector<std::string>::iterator it;
124 // We can't support GL_EXT_occlusion_query_boolean which is
125 // based on GL_ARB_occlusion_query without a lot of work virtualizing
126 // queries.
127 it = std::find(ext.begin(), ext.end(), "GL_EXT_occlusion_query_boolean");
128 if (it != ext.end())
129 ext.erase(it);
131 extensions_ = JoinString(ext, " ");
134 bool VirtualGLApi::MakeCurrent(GLContext* virtual_context, GLSurface* surface) {
135 bool switched_contexts = g_current_gl_context != this;
136 GLSurface* current_surface = GLSurface::GetCurrent();
137 if (switched_contexts || surface != current_surface) {
138 if (!switched_contexts && current_surface &&
139 virtual_context->IsCurrent(surface)) {
140 // MakeCurrent 'lite' path that avoids potentially expensive MakeCurrent()
141 // calls if the GLSurface uses the same underlying surface or renders to
142 // an FBO.
143 if (!surface->OnMakeCurrent(real_context_)) {
144 LOG(ERROR) << "Could not make GLSurface current.";
145 return false;
147 } else if (!real_context_->MakeCurrent(surface)) {
148 return false;
152 DCHECK(GLSurface::GetCurrent());
153 DCHECK(real_context_->IsCurrent(GLSurface::GetCurrent()));
154 DCHECK(virtual_context->IsCurrent(surface));
156 if (switched_contexts || virtual_context != current_context_) {
157 // There should be no errors from the previous context leaking into the
158 // new context.
159 DCHECK_EQ(glGetErrorFn(), static_cast<GLenum>(GL_NO_ERROR));
161 current_context_ = virtual_context;
162 // Set all state that is different from the real state
163 // NOTE: !!! This is a temporary implementation that just restores all
164 // state to let us test that it works.
165 // TODO: ASAP, change this to something that only restores the state
166 // needed for individual GL calls.
167 GLApi* temp = GetCurrentGLApi();
168 SetGLToRealGLApi();
169 virtual_context->GetGLStateRestorer()->RestoreState();
170 SetGLApi(temp);
172 SetGLApi(this);
173 return true;
176 void VirtualGLApi::OnDestroyVirtualContext(GLContext* virtual_context) {
177 if (current_context_ == virtual_context)
178 current_context_ = NULL;
181 const GLubyte* VirtualGLApi::glGetStringFn(GLenum name) {
182 switch (name) {
183 case GL_EXTENSIONS:
184 return reinterpret_cast<const GLubyte*>(extensions_.c_str());
185 default:
186 return driver_->fn.glGetStringFn(name);
190 } // namespace gfx