Move "pack" button in the top toolbar to an action in the list of unpacked items.
[chromium-blink-merge.git] / ui / gl / gl_gl_api_implementation.cc
blob802d250a37b65856943ec6cfad9a5465ea6986ad
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/strings/string_util.h"
12 #include "ui/gl/gl_context.h"
13 #include "ui/gl/gl_implementation.h"
14 #include "ui/gl/gl_state_restorer.h"
15 #include "ui/gl/gl_surface.h"
16 #include "ui/gl/gl_switches.h"
18 namespace gfx {
20 // The GL Api being used. This could be g_real_gl or gl_trace_gl
21 static GLApi* g_gl;
22 // A GL Api that calls directly into the driver.
23 static RealGLApi* g_real_gl;
24 // A GL Api that calls TRACE and then calls another GL api.
25 static TraceGLApi* g_trace_gl;
27 namespace {
29 static inline GLenum GetTexInternalFormat(GLenum internal_format) {
30 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
31 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
32 return GL_RGBA8;
34 return internal_format;
37 // TODO(epenner): Could the above function be merged into this and removed?
38 static inline GLenum GetTexInternalFormat(GLenum internal_format,
39 GLenum format,
40 GLenum type) {
41 GLenum gl_internal_format = GetTexInternalFormat(internal_format);
43 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
44 return gl_internal_format;
46 if (type == GL_FLOAT) {
47 switch (format) {
48 case GL_RGBA:
49 gl_internal_format = GL_RGBA32F_ARB;
50 break;
51 case GL_RGB:
52 gl_internal_format = GL_RGB32F_ARB;
53 break;
54 case GL_LUMINANCE_ALPHA:
55 gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB;
56 break;
57 case GL_LUMINANCE:
58 gl_internal_format = GL_LUMINANCE32F_ARB;
59 break;
60 case GL_ALPHA:
61 gl_internal_format = GL_ALPHA32F_ARB;
62 break;
63 default:
64 NOTREACHED();
65 break;
67 } else if (type == GL_HALF_FLOAT_OES) {
68 switch (format) {
69 case GL_RGBA:
70 gl_internal_format = GL_RGBA16F_ARB;
71 break;
72 case GL_RGB:
73 gl_internal_format = GL_RGB16F_ARB;
74 break;
75 case GL_LUMINANCE_ALPHA:
76 gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB;
77 break;
78 case GL_LUMINANCE:
79 gl_internal_format = GL_LUMINANCE16F_ARB;
80 break;
81 case GL_ALPHA:
82 gl_internal_format = GL_ALPHA16F_ARB;
83 break;
84 default:
85 NOTREACHED();
86 break;
89 return gl_internal_format;
92 static inline GLenum GetTexType(GLenum type) {
93 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
94 if (type == GL_HALF_FLOAT_OES)
95 return GL_HALF_FLOAT_ARB;
97 return type;
100 static void GL_BINDING_CALL CustomTexImage2D(
101 GLenum target, GLint level, GLint internalformat,
102 GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type,
103 const void* pixels) {
104 GLenum gl_internal_format = GetTexInternalFormat(
105 internalformat, format, type);
106 GLenum gl_type = GetTexType(type);
107 return g_driver_gl.orig_fn.glTexImage2DFn(
108 target, level, gl_internal_format, width, height, border, format, gl_type,
109 pixels);
112 static void GL_BINDING_CALL CustomTexSubImage2D(
113 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
114 GLsizei height, GLenum format, GLenum type, const void* pixels) {
115 GLenum gl_type = GetTexType(type);
116 return g_driver_gl.orig_fn.glTexSubImage2DFn(
117 target, level, xoffset, yoffset, width, height, format, gl_type, pixels);
120 static void GL_BINDING_CALL CustomTexStorage2DEXT(
121 GLenum target, GLsizei levels, GLenum internalformat, GLsizei width,
122 GLsizei height) {
123 GLenum gl_internal_format = GetTexInternalFormat(internalformat);
124 return g_driver_gl.orig_fn.glTexStorage2DEXTFn(
125 target, levels, gl_internal_format, width, height);
128 } // anonymous namespace
130 void DriverGL::Initialize() {
131 InitializeBindings();
134 void DriverGL::InitializeExtensions(GLContext* context) {
135 InitializeExtensionBindings(context);
136 orig_fn = fn;
137 fn.glTexImage2DFn =
138 reinterpret_cast<glTexImage2DProc>(CustomTexImage2D);
139 fn.glTexSubImage2DFn =
140 reinterpret_cast<glTexSubImage2DProc>(CustomTexSubImage2D);
141 fn.glTexStorage2DEXTFn =
142 reinterpret_cast<glTexStorage2DEXTProc>(CustomTexStorage2DEXT);
145 void InitializeGLBindingsGL() {
146 g_driver_gl.Initialize();
147 if (!g_real_gl) {
148 g_real_gl = new RealGLApi();
149 g_trace_gl = new TraceGLApi(g_real_gl);
151 g_real_gl->Initialize(&g_driver_gl);
152 g_gl = g_real_gl;
153 if (CommandLine::ForCurrentProcess()->HasSwitch(
154 switches::kEnableGPUServiceTracing)) {
155 g_gl = g_trace_gl;
157 SetGLToRealGLApi();
160 GLApi* GetCurrentGLApi() {
161 return g_current_gl_context;
164 void SetGLApi(GLApi* api) {
165 g_current_gl_context = api;
168 void SetGLToRealGLApi() {
169 SetGLApi(g_gl);
172 void InitializeGLExtensionBindingsGL(GLContext* context) {
173 g_driver_gl.InitializeExtensions(context);
176 void InitializeDebugGLBindingsGL() {
177 g_driver_gl.InitializeDebugBindings();
180 void ClearGLBindingsGL() {
181 if (g_real_gl) {
182 delete g_real_gl;
183 g_real_gl = NULL;
185 if (g_trace_gl) {
186 delete g_trace_gl;
187 g_trace_gl = NULL;
189 g_gl = NULL;
190 g_current_gl_context = NULL;
191 g_driver_gl.ClearBindings();
194 GLApi::GLApi() {
197 GLApi::~GLApi() {
198 if (GetCurrentGLApi() == this)
199 SetGLApi(NULL);
202 GLApiBase::GLApiBase()
203 : driver_(NULL) {
206 GLApiBase::~GLApiBase() {
209 void GLApiBase::InitializeBase(DriverGL* driver) {
210 driver_ = driver;
213 RealGLApi::RealGLApi() {
216 RealGLApi::~RealGLApi() {
219 void RealGLApi::Initialize(DriverGL* driver) {
220 InitializeBase(driver);
223 TraceGLApi::~TraceGLApi() {
226 VirtualGLApi::VirtualGLApi()
227 : real_context_(NULL),
228 current_context_(NULL) {
231 VirtualGLApi::~VirtualGLApi() {
234 void VirtualGLApi::Initialize(DriverGL* driver, GLContext* real_context) {
235 InitializeBase(driver);
236 real_context_ = real_context;
238 DCHECK(real_context->IsCurrent(NULL));
239 std::string ext_string(
240 reinterpret_cast<const char*>(driver_->fn.glGetStringFn(GL_EXTENSIONS)));
241 std::vector<std::string> ext;
242 Tokenize(ext_string, " ", &ext);
244 std::vector<std::string>::iterator it;
245 // We can't support GL_EXT_occlusion_query_boolean which is
246 // based on GL_ARB_occlusion_query without a lot of work virtualizing
247 // queries.
248 it = std::find(ext.begin(), ext.end(), "GL_EXT_occlusion_query_boolean");
249 if (it != ext.end())
250 ext.erase(it);
252 extensions_ = JoinString(ext, " ");
255 bool VirtualGLApi::MakeCurrent(GLContext* virtual_context, GLSurface* surface) {
256 bool switched_contexts = g_current_gl_context != this;
257 GLSurface* current_surface = GLSurface::GetCurrent();
258 if (switched_contexts || surface != current_surface) {
259 // MakeCurrent 'lite' path that avoids potentially expensive MakeCurrent()
260 // calls if the GLSurface uses the same underlying surface or renders to
261 // an FBO.
262 if (switched_contexts || !current_surface ||
263 !virtual_context->IsCurrent(surface)) {
264 if (!real_context_->MakeCurrent(surface)) {
265 return false;
270 DCHECK_EQ(real_context_, GLContext::GetRealCurrent());
271 DCHECK(real_context_->IsCurrent(NULL));
272 DCHECK(virtual_context->IsCurrent(surface));
274 if (switched_contexts || virtual_context != current_context_) {
275 // There should be no errors from the previous context leaking into the
276 // new context.
277 DCHECK_EQ(glGetErrorFn(), static_cast<GLenum>(GL_NO_ERROR));
279 current_context_ = virtual_context;
280 // Set all state that is different from the real state
281 // NOTE: !!! This is a temporary implementation that just restores all
282 // state to let us test that it works.
283 // TODO: ASAP, change this to something that only restores the state
284 // needed for individual GL calls.
285 GLApi* temp = GetCurrentGLApi();
286 SetGLToRealGLApi();
287 if (virtual_context->GetGLStateRestorer()->IsInitialized())
288 virtual_context->GetGLStateRestorer()->RestoreState();
289 SetGLApi(temp);
291 SetGLApi(this);
293 virtual_context->SetCurrent(surface);
294 if (!surface->OnMakeCurrent(virtual_context)) {
295 LOG(ERROR) << "Could not make GLSurface current.";
296 return false;
298 return true;
301 void VirtualGLApi::OnReleaseVirtuallyCurrent(GLContext* virtual_context) {
302 if (current_context_ == virtual_context)
303 current_context_ = NULL;
306 const GLubyte* VirtualGLApi::glGetStringFn(GLenum name) {
307 switch (name) {
308 case GL_EXTENSIONS:
309 return reinterpret_cast<const GLubyte*>(extensions_.c_str());
310 default:
311 return driver_->fn.glGetStringFn(name);
315 } // namespace gfx