Add version checking to webview library loads.
[chromium-blink-merge.git] / android_webview / browser / scoped_app_gl_state_restore.cc
blob0f45ca3de0a0844047c048d5ea68e95538bbca51
1 // Copyright 2013 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 "android_webview/browser/scoped_app_gl_state_restore.h"
7 #include <string>
9 #include "base/lazy_instance.h"
10 #include "base/trace_event/trace_event.h"
11 #include "ui/gl/gl_bindings.h"
12 #include "ui/gl/gl_context.h"
13 #include "ui/gl/gl_surface_stub.h"
15 namespace android_webview {
17 namespace {
19 // "App" context is a bit of a stretch. Basically we use this context while
20 // saving and restoring the App GL state.
21 class AppContextSurface {
22 public:
23 AppContextSurface()
24 : surface(new gfx::GLSurfaceStub),
25 context(gfx::GLContext::CreateGLContext(NULL,
26 surface.get(),
27 gfx::PreferDiscreteGpu)) {}
28 void MakeCurrent() { context->MakeCurrent(surface.get()); }
30 private:
31 scoped_refptr<gfx::GLSurfaceStub> surface;
32 scoped_refptr<gfx::GLContext> context;
34 DISALLOW_COPY_AND_ASSIGN(AppContextSurface);
37 base::LazyInstance<AppContextSurface> g_app_context_surface =
38 LAZY_INSTANCE_INITIALIZER;
40 // Make the global g_app_context_surface current so that the gl_binding is not
41 // NULL for making gl* calls. The binding can be null if another GlContext was
42 // destroyed immediately before gl* calls here.
43 void MakeAppContextCurrent() {
44 g_app_context_surface.Get().MakeCurrent();
47 void GLEnableDisable(GLenum cap, bool enable) {
48 if (enable)
49 glEnable(cap);
50 else
51 glDisable(cap);
54 bool ClearGLErrors(bool warn, const char* msg) {
55 bool no_error = true;
56 GLenum error;
57 while ((error = glGetError()) != GL_NO_ERROR) {
58 DLOG_IF(WARNING, warn) << error << " " << msg;
59 no_error = false;
62 return no_error;
65 bool g_globals_initialized = false;
66 GLint g_gl_max_texture_units = 0;
67 bool g_supports_oes_vertex_array_object = false;
69 } // namespace
71 namespace internal {
73 class ScopedAppGLStateRestoreImpl {
74 public:
75 ScopedAppGLStateRestoreImpl(ScopedAppGLStateRestore::CallMode mode);
76 ~ScopedAppGLStateRestoreImpl();
78 bool stencil_enabled() const { return stencil_test_; }
79 GLint framebuffer_binding_ext() const { return framebuffer_binding_ext_; }
81 private:
82 const ScopedAppGLStateRestore::CallMode mode_;
84 GLint pack_alignment_;
85 GLint unpack_alignment_;
87 struct {
88 GLint enabled;
89 GLint size;
90 GLint type;
91 GLint normalized;
92 GLint stride;
93 GLvoid* pointer;
94 GLint vertex_attrib_array_buffer_binding;
95 GLfloat current_vertex_attrib[4];
96 } vertex_attrib_[3];
98 GLint vertex_array_buffer_binding_;
99 GLint index_array_buffer_binding_;
101 GLboolean depth_test_;
102 GLboolean cull_face_;
103 GLint cull_face_mode_;
104 GLboolean color_mask_[4];
105 GLfloat color_clear_[4];
106 GLfloat blend_color_[4];
107 GLfloat depth_clear_;
108 GLint current_program_;
109 GLint depth_func_;
110 GLboolean depth_mask_;
111 GLfloat depth_rage_[2];
112 GLint front_face_;
113 GLint hint_generate_mipmap_;
114 GLfloat line_width_;
115 GLfloat polygon_offset_factor_;
116 GLfloat polygon_offset_units_;
117 GLfloat sample_coverage_value_;
118 GLboolean sample_coverage_invert_;
119 GLint blend_equation_rgb_;
120 GLint blend_equation_alpha_;
122 GLboolean enable_dither_;
123 GLboolean enable_polygon_offset_fill_;
124 GLboolean enable_sample_alpha_to_coverage_;
125 GLboolean enable_sample_coverage_;
127 // Not saved/restored in MODE_DRAW.
128 GLboolean blend_enabled_;
129 GLint blend_src_rgb_;
130 GLint blend_src_alpha_;
131 GLint blend_dest_rgb_;
132 GLint blend_dest_alpha_;
133 GLint active_texture_;
134 GLint viewport_[4];
135 GLboolean scissor_test_;
136 GLint scissor_box_[4];
138 GLboolean stencil_test_;
139 GLint stencil_front_func_;
140 GLint stencil_front_ref_;
141 GLint stencil_front_mask_;
142 GLint stencil_back_func_;
143 GLint stencil_back_ref_;
144 GLint stencil_back_mask_;
145 GLint stencil_clear_;
146 GLint stencil_front_writemask_;
147 GLint stencil_back_writemask_;
148 GLint stencil_front_fail_op_;
149 GLint stencil_front_z_fail_op_;
150 GLint stencil_front_z_pass_op_;
151 GLint stencil_back_fail_op_;
152 GLint stencil_back_z_fail_op_;
153 GLint stencil_back_z_pass_op_;
155 GLint framebuffer_binding_ext_;
157 struct TextureBindings {
158 GLint texture_2d;
159 GLint texture_cube_map;
160 GLint texture_external_oes;
161 // TODO(boliu): TEXTURE_RECTANGLE_ARB
164 std::vector<TextureBindings> texture_bindings_;
166 GLint vertex_array_bindings_oes_;
168 DISALLOW_COPY_AND_ASSIGN(ScopedAppGLStateRestoreImpl);
171 ScopedAppGLStateRestoreImpl::ScopedAppGLStateRestoreImpl(
172 ScopedAppGLStateRestore::CallMode mode)
173 : mode_(mode) {
174 TRACE_EVENT0("android_webview", "AppGLStateSave");
175 MakeAppContextCurrent();
177 ClearGLErrors(true, "Incoming GLError");
179 if (!g_globals_initialized) {
180 g_globals_initialized = true;
182 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &g_gl_max_texture_units);
184 std::string extensions;
185 const char* extensions_c_str =
186 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
187 if (extensions_c_str)
188 extensions = extensions_c_str;
189 g_supports_oes_vertex_array_object =
190 extensions.find("GL_OES_vertex_array_object") != std::string::npos;
193 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vertex_array_buffer_binding_);
194 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &index_array_buffer_binding_);
196 switch(mode_) {
197 case ScopedAppGLStateRestore::MODE_DRAW:
198 DCHECK_EQ(0, vertex_array_buffer_binding_);
199 DCHECK_EQ(0, index_array_buffer_binding_);
200 break;
201 case ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT:
202 glGetBooleanv(GL_BLEND, &blend_enabled_);
203 glGetIntegerv(GL_BLEND_SRC_RGB, &blend_src_rgb_);
204 glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_alpha_);
205 glGetIntegerv(GL_BLEND_DST_RGB, &blend_dest_rgb_);
206 glGetIntegerv(GL_BLEND_DST_ALPHA, &blend_dest_alpha_);
207 glGetIntegerv(GL_VIEWPORT, viewport_);
208 glGetBooleanv(GL_SCISSOR_TEST, &scissor_test_);
209 glGetIntegerv(GL_SCISSOR_BOX, scissor_box_);
210 break;
213 glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment_);
214 glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment_);
216 glGetBooleanv(GL_DEPTH_TEST, &depth_test_);
217 glGetBooleanv(GL_CULL_FACE, &cull_face_);
218 glGetIntegerv(GL_CULL_FACE_MODE, &cull_face_mode_);
219 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask_);
220 glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_);
221 glGetFloatv(GL_COLOR_CLEAR_VALUE, color_clear_);
222 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &depth_clear_);
223 glGetFloatv(GL_BLEND_COLOR, blend_color_);
224 glGetIntegerv(GL_DEPTH_FUNC, &depth_func_);
225 glGetBooleanv(GL_DEPTH_WRITEMASK, &depth_mask_);
226 glGetFloatv(GL_DEPTH_RANGE, depth_rage_);
227 glGetIntegerv(GL_FRONT_FACE, &front_face_);
228 glGetIntegerv(GL_GENERATE_MIPMAP_HINT, &hint_generate_mipmap_);
229 glGetFloatv(GL_LINE_WIDTH, &line_width_);
230 glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &polygon_offset_factor_);
231 glGetFloatv(GL_POLYGON_OFFSET_UNITS, &polygon_offset_units_);
232 glGetFloatv(GL_SAMPLE_COVERAGE_VALUE, &sample_coverage_value_);
233 glGetBooleanv(GL_SAMPLE_COVERAGE_INVERT, &sample_coverage_invert_);
234 glGetIntegerv(GL_BLEND_EQUATION_RGB, &blend_equation_rgb_);
235 glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blend_equation_alpha_);
237 glGetBooleanv(GL_DITHER, &enable_dither_);
238 glGetBooleanv(GL_POLYGON_OFFSET_FILL, &enable_polygon_offset_fill_);
239 glGetBooleanv(GL_SAMPLE_ALPHA_TO_COVERAGE, &enable_sample_alpha_to_coverage_);
240 glGetBooleanv(GL_SAMPLE_COVERAGE, &enable_sample_coverage_);
242 glGetBooleanv(GL_STENCIL_TEST, &stencil_test_);
243 glGetIntegerv(GL_STENCIL_FUNC, &stencil_front_func_);
244 glGetIntegerv(GL_STENCIL_VALUE_MASK, &stencil_front_mask_);
245 glGetIntegerv(GL_STENCIL_REF, &stencil_front_ref_);
246 glGetIntegerv(GL_STENCIL_BACK_FUNC, &stencil_back_func_);
247 glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &stencil_back_mask_);
248 glGetIntegerv(GL_STENCIL_BACK_REF, &stencil_back_ref_);
249 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &stencil_clear_);
250 glGetIntegerv(GL_STENCIL_WRITEMASK, &stencil_front_writemask_);
251 glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &stencil_back_writemask_);
252 glGetIntegerv(GL_STENCIL_FAIL, &stencil_front_fail_op_);
253 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &stencil_front_z_fail_op_);
254 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencil_front_z_pass_op_);
255 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencil_back_fail_op_);
256 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &stencil_back_z_fail_op_);
257 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencil_back_z_pass_op_);
259 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &framebuffer_binding_ext_);
261 glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture_);
263 texture_bindings_.resize(g_gl_max_texture_units);
264 for (int ii = 0; ii < g_gl_max_texture_units; ++ii) {
265 glActiveTexture(GL_TEXTURE0 + ii);
266 TextureBindings& bindings = texture_bindings_[ii];
267 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bindings.texture_2d);
268 glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &bindings.texture_cube_map);
269 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES,
270 &bindings.texture_external_oes);
273 if (g_supports_oes_vertex_array_object) {
274 glGetIntegerv(GL_VERTEX_ARRAY_BINDING_OES, &vertex_array_bindings_oes_);
275 glBindVertexArrayOES(0);
278 for (size_t i = 0; i < arraysize(vertex_attrib_); ++i) {
279 glGetVertexAttribiv(
280 i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &vertex_attrib_[i].enabled);
281 glGetVertexAttribiv(
282 i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &vertex_attrib_[i].size);
283 glGetVertexAttribiv(
284 i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &vertex_attrib_[i].type);
285 glGetVertexAttribiv(
286 i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &vertex_attrib_[i].normalized);
287 glGetVertexAttribiv(
288 i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &vertex_attrib_[i].stride);
289 glGetVertexAttribPointerv(
290 i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &vertex_attrib_[i].pointer);
291 glGetVertexAttribPointerv(
292 i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &vertex_attrib_[i].pointer);
293 glGetVertexAttribiv(i,
294 GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
295 &vertex_attrib_[i].vertex_attrib_array_buffer_binding);
296 glGetVertexAttribfv(
297 i, GL_CURRENT_VERTEX_ATTRIB, vertex_attrib_[i].current_vertex_attrib);
300 if (mode_ == ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT) {
301 // Android 5.0.0 specific qualcomm workaround. See crbug.com/434570.
302 glBindRenderbufferEXT(GL_RENDERBUFFER, 0);
305 DCHECK(ClearGLErrors(false, NULL));
308 ScopedAppGLStateRestoreImpl::~ScopedAppGLStateRestoreImpl() {
309 TRACE_EVENT0("android_webview", "AppGLStateRestore");
310 MakeAppContextCurrent();
312 DCHECK(ClearGLErrors(false, NULL));
314 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_binding_ext_);
315 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_buffer_binding_);
317 if (g_supports_oes_vertex_array_object)
318 glBindVertexArrayOES(0);
320 for (size_t i = 0; i < arraysize(vertex_attrib_); ++i) {
321 glBindBuffer(GL_ARRAY_BUFFER,
322 vertex_attrib_[i].vertex_attrib_array_buffer_binding);
323 glVertexAttribPointer(i,
324 vertex_attrib_[i].size,
325 vertex_attrib_[i].type,
326 vertex_attrib_[i].normalized,
327 vertex_attrib_[i].stride,
328 vertex_attrib_[i].pointer);
330 glVertexAttrib4fv(i, vertex_attrib_[i].current_vertex_attrib);
332 if (vertex_attrib_[i].enabled) {
333 glEnableVertexAttribArray(i);
334 } else {
335 glDisableVertexAttribArray(i);
339 if (g_supports_oes_vertex_array_object && vertex_array_bindings_oes_ != 0)
340 glBindVertexArrayOES(vertex_array_bindings_oes_);
342 glBindBuffer(GL_ARRAY_BUFFER, vertex_array_buffer_binding_);
344 for (int ii = 0; ii < g_gl_max_texture_units; ++ii) {
345 glActiveTexture(GL_TEXTURE0 + ii);
346 TextureBindings& bindings = texture_bindings_[ii];
347 glBindTexture(GL_TEXTURE_2D, bindings.texture_2d);
348 glBindTexture(GL_TEXTURE_CUBE_MAP, bindings.texture_cube_map);
349 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bindings.texture_external_oes);
351 glActiveTexture(active_texture_);
353 glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment_);
354 glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment_);
356 GLEnableDisable(GL_DEPTH_TEST, depth_test_);
358 GLEnableDisable(GL_CULL_FACE, cull_face_);
359 glCullFace(cull_face_mode_);
361 glColorMask(color_mask_[0], color_mask_[1], color_mask_[2], color_mask_[3]);
363 glUseProgram(current_program_);
365 glClearColor(
366 color_clear_[0], color_clear_[1], color_clear_[2], color_clear_[3]);
367 glBlendColor(
368 blend_color_[0], blend_color_[1], blend_color_[2], blend_color_[3]);
369 glClearDepth(depth_clear_);
370 glDepthFunc(depth_func_);
371 glDepthMask(depth_mask_);
372 glDepthRange(depth_rage_[0], depth_rage_[1]);
373 glFrontFace(front_face_);
374 glHint(GL_GENERATE_MIPMAP_HINT, hint_generate_mipmap_);
375 // TODO(boliu): GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES ??
376 glLineWidth(line_width_);
377 glPolygonOffset(polygon_offset_factor_, polygon_offset_units_);
378 glSampleCoverage(sample_coverage_value_, sample_coverage_invert_);
379 glBlendEquationSeparate(blend_equation_rgb_, blend_equation_alpha_);
381 GLEnableDisable(GL_DITHER, enable_dither_);
382 GLEnableDisable(GL_POLYGON_OFFSET_FILL, enable_polygon_offset_fill_);
383 GLEnableDisable(GL_SAMPLE_ALPHA_TO_COVERAGE,
384 enable_sample_alpha_to_coverage_);
385 GLEnableDisable(GL_SAMPLE_COVERAGE, enable_sample_coverage_);
387 switch(mode_) {
388 case ScopedAppGLStateRestore::MODE_DRAW:
389 // No-op.
390 break;
391 case ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT:
392 GLEnableDisable(GL_BLEND, blend_enabled_);
393 glBlendFuncSeparate(
394 blend_src_rgb_, blend_dest_rgb_, blend_src_alpha_, blend_dest_alpha_);
396 glViewport(viewport_[0], viewport_[1], viewport_[2], viewport_[3]);
398 GLEnableDisable(GL_SCISSOR_TEST, scissor_test_);
400 glScissor(
401 scissor_box_[0], scissor_box_[1], scissor_box_[2], scissor_box_[3]);
402 break;
405 GLEnableDisable(GL_STENCIL_TEST, stencil_test_);
406 glStencilFuncSeparate(
407 GL_FRONT, stencil_front_func_, stencil_front_mask_, stencil_front_ref_);
408 glStencilFuncSeparate(
409 GL_BACK, stencil_back_func_, stencil_back_mask_, stencil_back_ref_);
410 glClearStencil(stencil_clear_);
411 glStencilMaskSeparate(GL_FRONT, stencil_front_writemask_);
412 glStencilMaskSeparate(GL_BACK, stencil_back_writemask_);
413 glStencilOpSeparate(GL_FRONT,
414 stencil_front_fail_op_,
415 stencil_front_z_fail_op_,
416 stencil_front_z_pass_op_);
417 glStencilOpSeparate(GL_BACK,
418 stencil_back_fail_op_,
419 stencil_back_z_fail_op_,
420 stencil_back_z_pass_op_);
422 // Do not leak GLError out of chromium.
423 ClearGLErrors(true, "Chromium GLError");
426 } // namespace internal
428 ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode)
429 : impl_(new internal::ScopedAppGLStateRestoreImpl(mode)) {
432 ScopedAppGLStateRestore::~ScopedAppGLStateRestore() {}
434 bool ScopedAppGLStateRestore::stencil_enabled() const {
435 return impl_->stencil_enabled();
437 int ScopedAppGLStateRestore::framebuffer_binding_ext() const {
438 return impl_->framebuffer_binding_ext();
441 } // namespace android_webview