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 "base/debug/trace_event.h"
8 #include "base/lazy_instance.h"
9 #include "ui/gl/gl_context.h"
10 #include "ui/gl/gl_surface_stub.h"
12 namespace android_webview
{
16 // "App" context is a bit of a stretch. Basically we use this context while
17 // saving and restoring the App GL state.
18 class AppContextSurface
{
21 : surface(new gfx::GLSurfaceStub
),
22 context(gfx::GLContext::CreateGLContext(NULL
,
24 gfx::PreferDiscreteGpu
)) {}
25 void MakeCurrent() { context
->MakeCurrent(surface
.get()); }
28 scoped_refptr
<gfx::GLSurfaceStub
> surface
;
29 scoped_refptr
<gfx::GLContext
> context
;
31 DISALLOW_COPY_AND_ASSIGN(AppContextSurface
);
34 base::LazyInstance
<AppContextSurface
> g_app_context_surface
=
35 LAZY_INSTANCE_INITIALIZER
;
37 // Make the global g_app_context_surface current so that the gl_binding is not
38 // NULL for making gl* calls. The binding can be null if another GlContext was
39 // destroyed immediately before gl* calls here.
40 void MakeAppContextCurrent() {
41 g_app_context_surface
.Get().MakeCurrent();
44 void GLEnableDisable(GLenum cap
, bool enable
) {
51 GLint g_gl_max_texture_units
= 0;
55 ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode
) : mode_(mode
) {
56 TRACE_EVENT0("android_webview", "AppGLStateSave");
57 MakeAppContextCurrent();
59 glGetIntegerv(GL_ARRAY_BUFFER_BINDING
, &vertex_array_buffer_binding_
);
60 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING
, &index_array_buffer_binding_
);
64 DCHECK_EQ(0, vertex_array_buffer_binding_
);
65 DCHECK_EQ(0, index_array_buffer_binding_
);
67 case MODE_RESOURCE_MANAGEMENT
:
68 glGetBooleanv(GL_BLEND
, &blend_enabled_
);
69 glGetIntegerv(GL_BLEND_SRC_RGB
, &blend_src_rgb_
);
70 glGetIntegerv(GL_BLEND_SRC_ALPHA
, &blend_src_alpha_
);
71 glGetIntegerv(GL_BLEND_DST_RGB
, &blend_dest_rgb_
);
72 glGetIntegerv(GL_BLEND_DST_ALPHA
, &blend_dest_alpha_
);
73 glGetIntegerv(GL_VIEWPORT
, viewport_
);
74 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_test_
);
75 glGetIntegerv(GL_SCISSOR_BOX
, scissor_box_
);
79 glGetIntegerv(GL_PACK_ALIGNMENT
, &pack_alignment_
);
80 glGetIntegerv(GL_UNPACK_ALIGNMENT
, &unpack_alignment_
);
82 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(vertex_attrib_
); ++i
) {
84 i
, GL_VERTEX_ATTRIB_ARRAY_ENABLED
, &vertex_attrib_
[i
].enabled
);
86 i
, GL_VERTEX_ATTRIB_ARRAY_SIZE
, &vertex_attrib_
[i
].size
);
88 i
, GL_VERTEX_ATTRIB_ARRAY_TYPE
, &vertex_attrib_
[i
].type
);
90 i
, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
, &vertex_attrib_
[i
].normalized
);
92 i
, GL_VERTEX_ATTRIB_ARRAY_STRIDE
, &vertex_attrib_
[i
].stride
);
93 glGetVertexAttribPointerv(
94 i
, GL_VERTEX_ATTRIB_ARRAY_POINTER
, &vertex_attrib_
[i
].pointer
);
97 glGetBooleanv(GL_DEPTH_TEST
, &depth_test_
);
98 glGetBooleanv(GL_CULL_FACE
, &cull_face_
);
99 glGetIntegerv(GL_CULL_FACE_MODE
, &cull_face_mode_
);
100 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask_
);
101 glGetIntegerv(GL_CURRENT_PROGRAM
, ¤t_program_
);
102 glGetFloatv(GL_COLOR_CLEAR_VALUE
, color_clear_
);
103 glGetFloatv(GL_DEPTH_CLEAR_VALUE
, &depth_clear_
);
104 glGetIntegerv(GL_DEPTH_FUNC
, &depth_func_
);
105 glGetBooleanv(GL_DEPTH_WRITEMASK
, &depth_mask_
);
106 glGetFloatv(GL_DEPTH_RANGE
, depth_rage_
);
107 glGetIntegerv(GL_FRONT_FACE
, &front_face_
);
108 glGetIntegerv(GL_GENERATE_MIPMAP_HINT
, &hint_generate_mipmap_
);
109 glGetFloatv(GL_LINE_WIDTH
, &line_width_
);
110 glGetFloatv(GL_POLYGON_OFFSET_FACTOR
, &polygon_offset_factor_
);
111 glGetFloatv(GL_POLYGON_OFFSET_UNITS
, &polygon_offset_units_
);
112 glGetFloatv(GL_SAMPLE_COVERAGE_VALUE
, &sample_coverage_value_
);
113 glGetBooleanv(GL_SAMPLE_COVERAGE_INVERT
, &sample_coverage_invert_
);
115 glGetBooleanv(GL_DITHER
, &enable_dither_
);
116 glGetBooleanv(GL_POLYGON_OFFSET_FILL
, &enable_polygon_offset_fill_
);
117 glGetBooleanv(GL_SAMPLE_ALPHA_TO_COVERAGE
, &enable_sample_alpha_to_coverage_
);
118 glGetBooleanv(GL_SAMPLE_COVERAGE
, &enable_sample_coverage_
);
120 glGetBooleanv(GL_STENCIL_TEST
, &stencil_test_
);
121 glGetIntegerv(GL_STENCIL_FUNC
, &stencil_func_
);
122 glGetIntegerv(GL_STENCIL_VALUE_MASK
, &stencil_mask_
);
123 glGetIntegerv(GL_STENCIL_REF
, &stencil_ref_
);
125 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &framebuffer_binding_ext_
);
127 if (!g_gl_max_texture_units
) {
128 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
, &g_gl_max_texture_units
);
129 DCHECK_GT(g_gl_max_texture_units
, 0);
132 glGetIntegerv(GL_ACTIVE_TEXTURE
, &active_texture_
);
134 texture_bindings_
.resize(g_gl_max_texture_units
);
135 for (int ii
= 0; ii
< g_gl_max_texture_units
; ++ii
) {
136 glActiveTexture(GL_TEXTURE0
+ ii
);
137 TextureBindings
& bindings
= texture_bindings_
[ii
];
138 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bindings
.texture_2d
);
139 glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP
, &bindings
.texture_cube_map
);
140 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES
,
141 &bindings
.texture_external_oes
);
145 ScopedAppGLStateRestore::~ScopedAppGLStateRestore() {
146 TRACE_EVENT0("android_webview", "AppGLStateRestore");
147 MakeAppContextCurrent();
149 glBindFramebufferEXT(GL_FRAMEBUFFER
, framebuffer_binding_ext_
);
150 glBindBuffer(GL_ARRAY_BUFFER
, vertex_array_buffer_binding_
);
151 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, index_array_buffer_binding_
);
153 for (int ii
= 0; ii
< g_gl_max_texture_units
; ++ii
) {
154 glActiveTexture(GL_TEXTURE0
+ ii
);
155 TextureBindings
& bindings
= texture_bindings_
[ii
];
156 glBindTexture(GL_TEXTURE_2D
, bindings
.texture_2d
);
157 glBindTexture(GL_TEXTURE_CUBE_MAP
, bindings
.texture_cube_map
);
158 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, bindings
.texture_external_oes
);
160 glActiveTexture(active_texture_
);
162 glPixelStorei(GL_PACK_ALIGNMENT
, pack_alignment_
);
163 glPixelStorei(GL_UNPACK_ALIGNMENT
, unpack_alignment_
);
165 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(vertex_attrib_
); ++i
) {
166 glVertexAttribPointer(i
,
167 vertex_attrib_
[i
].size
,
168 vertex_attrib_
[i
].type
,
169 vertex_attrib_
[i
].normalized
,
170 vertex_attrib_
[i
].stride
,
171 vertex_attrib_
[i
].pointer
);
173 if (vertex_attrib_
[i
].enabled
) {
174 glEnableVertexAttribArray(i
);
176 glDisableVertexAttribArray(i
);
180 GLEnableDisable(GL_DEPTH_TEST
, depth_test_
);
182 GLEnableDisable(GL_CULL_FACE
, cull_face_
);
183 glCullFace(cull_face_mode_
);
185 glColorMask(color_mask_
[0], color_mask_
[1], color_mask_
[2], color_mask_
[3]);
187 glUseProgram(current_program_
);
190 color_clear_
[0], color_clear_
[1], color_clear_
[2], color_clear_
[3]);
191 glClearDepth(depth_clear_
);
192 glDepthFunc(depth_func_
);
193 glDepthMask(depth_mask_
);
194 glDepthRange(depth_rage_
[0], depth_rage_
[1]);
195 glFrontFace(front_face_
);
196 glHint(GL_GENERATE_MIPMAP_HINT
, hint_generate_mipmap_
);
197 // TODO(boliu): GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES ??
198 glLineWidth(line_width_
);
199 glPolygonOffset(polygon_offset_factor_
, polygon_offset_units_
);
200 glSampleCoverage(sample_coverage_value_
, sample_coverage_invert_
);
202 GLEnableDisable(GL_DITHER
, enable_dither_
);
203 GLEnableDisable(GL_POLYGON_OFFSET_FILL
, enable_polygon_offset_fill_
);
204 GLEnableDisable(GL_SAMPLE_ALPHA_TO_COVERAGE
,
205 enable_sample_alpha_to_coverage_
);
206 GLEnableDisable(GL_SAMPLE_COVERAGE
, enable_sample_coverage_
);
212 case MODE_RESOURCE_MANAGEMENT
:
213 GLEnableDisable(GL_BLEND
, blend_enabled_
);
215 blend_src_rgb_
, blend_dest_rgb_
, blend_src_alpha_
, blend_dest_alpha_
);
217 glViewport(viewport_
[0], viewport_
[1], viewport_
[2], viewport_
[3]);
219 GLEnableDisable(GL_SCISSOR_TEST
, scissor_test_
);
222 scissor_box_
[0], scissor_box_
[1], scissor_box_
[2], scissor_box_
[3]);
226 GLEnableDisable(GL_STENCIL_TEST
, stencil_test_
);
227 glStencilFunc(stencil_func_
, stencil_mask_
, stencil_ref_
);
230 } // namespace android_webview