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"
9 #include "base/debug/trace_event.h"
10 #include "base/lazy_instance.h"
11 #include "ui/gl/gl_context.h"
12 #include "ui/gl/gl_surface_stub.h"
14 namespace android_webview
{
18 // "App" context is a bit of a stretch. Basically we use this context while
19 // saving and restoring the App GL state.
20 class AppContextSurface
{
23 : surface(new gfx::GLSurfaceStub
),
24 context(gfx::GLContext::CreateGLContext(NULL
,
26 gfx::PreferDiscreteGpu
)) {}
27 void MakeCurrent() { context
->MakeCurrent(surface
.get()); }
30 scoped_refptr
<gfx::GLSurfaceStub
> surface
;
31 scoped_refptr
<gfx::GLContext
> context
;
33 DISALLOW_COPY_AND_ASSIGN(AppContextSurface
);
36 base::LazyInstance
<AppContextSurface
> g_app_context_surface
=
37 LAZY_INSTANCE_INITIALIZER
;
39 // Make the global g_app_context_surface current so that the gl_binding is not
40 // NULL for making gl* calls. The binding can be null if another GlContext was
41 // destroyed immediately before gl* calls here.
42 void MakeAppContextCurrent() {
43 g_app_context_surface
.Get().MakeCurrent();
46 void GLEnableDisable(GLenum cap
, bool enable
) {
53 bool g_globals_initialized
= false;
54 GLint g_gl_max_texture_units
= 0;
55 bool g_supports_oes_vertex_array_object
= false;
59 ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode
) : mode_(mode
) {
60 TRACE_EVENT0("android_webview", "AppGLStateSave");
61 MakeAppContextCurrent();
63 if (!g_globals_initialized
) {
64 g_globals_initialized
= true;
66 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
, &g_gl_max_texture_units
);
67 DCHECK_GT(g_gl_max_texture_units
, 0);
69 std::string
extensions(
70 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS
)));
71 g_supports_oes_vertex_array_object
=
72 extensions
.find("GL_OES_vertex_array_object") != std::string::npos
;
75 glGetIntegerv(GL_ARRAY_BUFFER_BINDING
, &vertex_array_buffer_binding_
);
76 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING
, &index_array_buffer_binding_
);
80 DCHECK_EQ(0, vertex_array_buffer_binding_
);
81 DCHECK_EQ(0, index_array_buffer_binding_
);
83 case MODE_RESOURCE_MANAGEMENT
:
84 glGetBooleanv(GL_BLEND
, &blend_enabled_
);
85 glGetIntegerv(GL_BLEND_SRC_RGB
, &blend_src_rgb_
);
86 glGetIntegerv(GL_BLEND_SRC_ALPHA
, &blend_src_alpha_
);
87 glGetIntegerv(GL_BLEND_DST_RGB
, &blend_dest_rgb_
);
88 glGetIntegerv(GL_BLEND_DST_ALPHA
, &blend_dest_alpha_
);
89 glGetIntegerv(GL_VIEWPORT
, viewport_
);
90 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_test_
);
91 glGetIntegerv(GL_SCISSOR_BOX
, scissor_box_
);
95 glGetIntegerv(GL_PACK_ALIGNMENT
, &pack_alignment_
);
96 glGetIntegerv(GL_UNPACK_ALIGNMENT
, &unpack_alignment_
);
98 glGetBooleanv(GL_DEPTH_TEST
, &depth_test_
);
99 glGetBooleanv(GL_CULL_FACE
, &cull_face_
);
100 glGetIntegerv(GL_CULL_FACE_MODE
, &cull_face_mode_
);
101 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask_
);
102 glGetIntegerv(GL_CURRENT_PROGRAM
, ¤t_program_
);
103 glGetFloatv(GL_COLOR_CLEAR_VALUE
, color_clear_
);
104 glGetFloatv(GL_DEPTH_CLEAR_VALUE
, &depth_clear_
);
105 glGetIntegerv(GL_DEPTH_FUNC
, &depth_func_
);
106 glGetBooleanv(GL_DEPTH_WRITEMASK
, &depth_mask_
);
107 glGetFloatv(GL_DEPTH_RANGE
, depth_rage_
);
108 glGetIntegerv(GL_FRONT_FACE
, &front_face_
);
109 glGetIntegerv(GL_GENERATE_MIPMAP_HINT
, &hint_generate_mipmap_
);
110 glGetFloatv(GL_LINE_WIDTH
, &line_width_
);
111 glGetFloatv(GL_POLYGON_OFFSET_FACTOR
, &polygon_offset_factor_
);
112 glGetFloatv(GL_POLYGON_OFFSET_UNITS
, &polygon_offset_units_
);
113 glGetFloatv(GL_SAMPLE_COVERAGE_VALUE
, &sample_coverage_value_
);
114 glGetBooleanv(GL_SAMPLE_COVERAGE_INVERT
, &sample_coverage_invert_
);
116 glGetBooleanv(GL_DITHER
, &enable_dither_
);
117 glGetBooleanv(GL_POLYGON_OFFSET_FILL
, &enable_polygon_offset_fill_
);
118 glGetBooleanv(GL_SAMPLE_ALPHA_TO_COVERAGE
, &enable_sample_alpha_to_coverage_
);
119 glGetBooleanv(GL_SAMPLE_COVERAGE
, &enable_sample_coverage_
);
121 glGetBooleanv(GL_STENCIL_TEST
, &stencil_test_
);
122 glGetIntegerv(GL_STENCIL_FUNC
, &stencil_func_
);
123 glGetIntegerv(GL_STENCIL_VALUE_MASK
, &stencil_mask_
);
124 glGetIntegerv(GL_STENCIL_REF
, &stencil_ref_
);
126 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &framebuffer_binding_ext_
);
128 glGetIntegerv(GL_ACTIVE_TEXTURE
, &active_texture_
);
130 texture_bindings_
.resize(g_gl_max_texture_units
);
131 for (int ii
= 0; ii
< g_gl_max_texture_units
; ++ii
) {
132 glActiveTexture(GL_TEXTURE0
+ ii
);
133 TextureBindings
& bindings
= texture_bindings_
[ii
];
134 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bindings
.texture_2d
);
135 glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP
, &bindings
.texture_cube_map
);
136 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES
,
137 &bindings
.texture_external_oes
);
140 if (g_supports_oes_vertex_array_object
) {
141 glGetIntegerv(GL_VERTEX_ARRAY_BINDING_OES
, &vertex_array_bindings_oes_
);
142 glBindVertexArrayOES(0);
145 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(vertex_attrib_
); ++i
) {
147 i
, GL_VERTEX_ATTRIB_ARRAY_ENABLED
, &vertex_attrib_
[i
].enabled
);
149 i
, GL_VERTEX_ATTRIB_ARRAY_SIZE
, &vertex_attrib_
[i
].size
);
151 i
, GL_VERTEX_ATTRIB_ARRAY_TYPE
, &vertex_attrib_
[i
].type
);
153 i
, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
, &vertex_attrib_
[i
].normalized
);
155 i
, GL_VERTEX_ATTRIB_ARRAY_STRIDE
, &vertex_attrib_
[i
].stride
);
156 glGetVertexAttribPointerv(
157 i
, GL_VERTEX_ATTRIB_ARRAY_POINTER
, &vertex_attrib_
[i
].pointer
);
158 glGetVertexAttribPointerv(
159 i
, GL_VERTEX_ATTRIB_ARRAY_POINTER
, &vertex_attrib_
[i
].pointer
);
160 glGetVertexAttribiv(i
,
161 GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
,
162 &vertex_attrib_
[i
].vertex_attrib_array_buffer_binding
);
164 i
, GL_CURRENT_VERTEX_ATTRIB
, vertex_attrib_
[i
].current_vertex_attrib
);
168 ScopedAppGLStateRestore::~ScopedAppGLStateRestore() {
169 TRACE_EVENT0("android_webview", "AppGLStateRestore");
170 MakeAppContextCurrent();
172 glBindFramebufferEXT(GL_FRAMEBUFFER
, framebuffer_binding_ext_
);
173 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, index_array_buffer_binding_
);
175 if (g_supports_oes_vertex_array_object
)
176 glBindVertexArrayOES(0);
178 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(vertex_attrib_
); ++i
) {
179 glBindBuffer(GL_ARRAY_BUFFER
,
180 vertex_attrib_
[i
].vertex_attrib_array_buffer_binding
);
181 glVertexAttribPointer(i
,
182 vertex_attrib_
[i
].size
,
183 vertex_attrib_
[i
].type
,
184 vertex_attrib_
[i
].normalized
,
185 vertex_attrib_
[i
].stride
,
186 vertex_attrib_
[i
].pointer
);
188 glVertexAttrib4fv(i
, vertex_attrib_
[i
].current_vertex_attrib
);
190 if (vertex_attrib_
[i
].enabled
) {
191 glEnableVertexAttribArray(i
);
193 glDisableVertexAttribArray(i
);
197 if (g_supports_oes_vertex_array_object
&& vertex_array_bindings_oes_
!= 0)
198 glBindVertexArrayOES(vertex_array_bindings_oes_
);
200 glBindBuffer(GL_ARRAY_BUFFER
, vertex_array_buffer_binding_
);
202 for (int ii
= 0; ii
< g_gl_max_texture_units
; ++ii
) {
203 glActiveTexture(GL_TEXTURE0
+ ii
);
204 TextureBindings
& bindings
= texture_bindings_
[ii
];
205 glBindTexture(GL_TEXTURE_2D
, bindings
.texture_2d
);
206 glBindTexture(GL_TEXTURE_CUBE_MAP
, bindings
.texture_cube_map
);
207 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, bindings
.texture_external_oes
);
209 glActiveTexture(active_texture_
);
211 glPixelStorei(GL_PACK_ALIGNMENT
, pack_alignment_
);
212 glPixelStorei(GL_UNPACK_ALIGNMENT
, unpack_alignment_
);
214 GLEnableDisable(GL_DEPTH_TEST
, depth_test_
);
216 GLEnableDisable(GL_CULL_FACE
, cull_face_
);
217 glCullFace(cull_face_mode_
);
219 glColorMask(color_mask_
[0], color_mask_
[1], color_mask_
[2], color_mask_
[3]);
221 glUseProgram(current_program_
);
224 color_clear_
[0], color_clear_
[1], color_clear_
[2], color_clear_
[3]);
225 glClearDepth(depth_clear_
);
226 glDepthFunc(depth_func_
);
227 glDepthMask(depth_mask_
);
228 glDepthRange(depth_rage_
[0], depth_rage_
[1]);
229 glFrontFace(front_face_
);
230 glHint(GL_GENERATE_MIPMAP_HINT
, hint_generate_mipmap_
);
231 // TODO(boliu): GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES ??
232 glLineWidth(line_width_
);
233 glPolygonOffset(polygon_offset_factor_
, polygon_offset_units_
);
234 glSampleCoverage(sample_coverage_value_
, sample_coverage_invert_
);
236 GLEnableDisable(GL_DITHER
, enable_dither_
);
237 GLEnableDisable(GL_POLYGON_OFFSET_FILL
, enable_polygon_offset_fill_
);
238 GLEnableDisable(GL_SAMPLE_ALPHA_TO_COVERAGE
,
239 enable_sample_alpha_to_coverage_
);
240 GLEnableDisable(GL_SAMPLE_COVERAGE
, enable_sample_coverage_
);
246 case MODE_RESOURCE_MANAGEMENT
:
247 GLEnableDisable(GL_BLEND
, blend_enabled_
);
249 blend_src_rgb_
, blend_dest_rgb_
, blend_src_alpha_
, blend_dest_alpha_
);
251 glViewport(viewport_
[0], viewport_
[1], viewport_
[2], viewport_
[3]);
253 GLEnableDisable(GL_SCISSOR_TEST
, scissor_test_
);
256 scissor_box_
[0], scissor_box_
[1], scissor_box_
[2], scissor_box_
[3]);
260 GLEnableDisable(GL_STENCIL_TEST
, stencil_test_
);
261 glStencilFunc(stencil_func_
, stencil_mask_
, stencil_ref_
);
264 } // namespace android_webview