Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / android_webview / browser / scoped_app_gl_state_restore.cc
bloba36e061cca559587c9ee0087e4b4bf7cf76bd967
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/debug/trace_event.h"
10 #include "base/lazy_instance.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);
183 DCHECK_GT(g_gl_max_texture_units, 0);
185 std::string extensions(
186 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
187 g_supports_oes_vertex_array_object =
188 extensions.find("GL_OES_vertex_array_object") != std::string::npos;
191 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vertex_array_buffer_binding_);
192 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &index_array_buffer_binding_);
194 switch(mode_) {
195 case ScopedAppGLStateRestore::MODE_DRAW:
196 DCHECK_EQ(0, vertex_array_buffer_binding_);
197 DCHECK_EQ(0, index_array_buffer_binding_);
198 break;
199 case ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT:
200 glGetBooleanv(GL_BLEND, &blend_enabled_);
201 glGetIntegerv(GL_BLEND_SRC_RGB, &blend_src_rgb_);
202 glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_alpha_);
203 glGetIntegerv(GL_BLEND_DST_RGB, &blend_dest_rgb_);
204 glGetIntegerv(GL_BLEND_DST_ALPHA, &blend_dest_alpha_);
205 glGetIntegerv(GL_VIEWPORT, viewport_);
206 glGetBooleanv(GL_SCISSOR_TEST, &scissor_test_);
207 glGetIntegerv(GL_SCISSOR_BOX, scissor_box_);
208 break;
211 glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment_);
212 glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment_);
214 glGetBooleanv(GL_DEPTH_TEST, &depth_test_);
215 glGetBooleanv(GL_CULL_FACE, &cull_face_);
216 glGetIntegerv(GL_CULL_FACE_MODE, &cull_face_mode_);
217 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask_);
218 glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_);
219 glGetFloatv(GL_COLOR_CLEAR_VALUE, color_clear_);
220 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &depth_clear_);
221 glGetFloatv(GL_BLEND_COLOR, blend_color_);
222 glGetIntegerv(GL_DEPTH_FUNC, &depth_func_);
223 glGetBooleanv(GL_DEPTH_WRITEMASK, &depth_mask_);
224 glGetFloatv(GL_DEPTH_RANGE, depth_rage_);
225 glGetIntegerv(GL_FRONT_FACE, &front_face_);
226 glGetIntegerv(GL_GENERATE_MIPMAP_HINT, &hint_generate_mipmap_);
227 glGetFloatv(GL_LINE_WIDTH, &line_width_);
228 glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &polygon_offset_factor_);
229 glGetFloatv(GL_POLYGON_OFFSET_UNITS, &polygon_offset_units_);
230 glGetFloatv(GL_SAMPLE_COVERAGE_VALUE, &sample_coverage_value_);
231 glGetBooleanv(GL_SAMPLE_COVERAGE_INVERT, &sample_coverage_invert_);
232 glGetIntegerv(GL_BLEND_EQUATION_RGB, &blend_equation_rgb_);
233 glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blend_equation_alpha_);
235 glGetBooleanv(GL_DITHER, &enable_dither_);
236 glGetBooleanv(GL_POLYGON_OFFSET_FILL, &enable_polygon_offset_fill_);
237 glGetBooleanv(GL_SAMPLE_ALPHA_TO_COVERAGE, &enable_sample_alpha_to_coverage_);
238 glGetBooleanv(GL_SAMPLE_COVERAGE, &enable_sample_coverage_);
240 glGetBooleanv(GL_STENCIL_TEST, &stencil_test_);
241 glGetIntegerv(GL_STENCIL_FUNC, &stencil_front_func_);
242 glGetIntegerv(GL_STENCIL_VALUE_MASK, &stencil_front_mask_);
243 glGetIntegerv(GL_STENCIL_REF, &stencil_front_ref_);
244 glGetIntegerv(GL_STENCIL_BACK_FUNC, &stencil_back_func_);
245 glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &stencil_back_mask_);
246 glGetIntegerv(GL_STENCIL_BACK_REF, &stencil_back_ref_);
247 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &stencil_clear_);
248 glGetIntegerv(GL_STENCIL_WRITEMASK, &stencil_front_writemask_);
249 glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &stencil_back_writemask_);
250 glGetIntegerv(GL_STENCIL_FAIL, &stencil_front_fail_op_);
251 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &stencil_front_z_fail_op_);
252 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencil_front_z_pass_op_);
253 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencil_back_fail_op_);
254 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &stencil_back_z_fail_op_);
255 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencil_back_z_pass_op_);
257 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &framebuffer_binding_ext_);
259 glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture_);
261 texture_bindings_.resize(g_gl_max_texture_units);
262 for (int ii = 0; ii < g_gl_max_texture_units; ++ii) {
263 glActiveTexture(GL_TEXTURE0 + ii);
264 TextureBindings& bindings = texture_bindings_[ii];
265 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bindings.texture_2d);
266 glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &bindings.texture_cube_map);
267 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES,
268 &bindings.texture_external_oes);
271 if (g_supports_oes_vertex_array_object) {
272 glGetIntegerv(GL_VERTEX_ARRAY_BINDING_OES, &vertex_array_bindings_oes_);
273 glBindVertexArrayOES(0);
276 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(vertex_attrib_); ++i) {
277 glGetVertexAttribiv(
278 i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &vertex_attrib_[i].enabled);
279 glGetVertexAttribiv(
280 i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &vertex_attrib_[i].size);
281 glGetVertexAttribiv(
282 i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &vertex_attrib_[i].type);
283 glGetVertexAttribiv(
284 i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &vertex_attrib_[i].normalized);
285 glGetVertexAttribiv(
286 i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &vertex_attrib_[i].stride);
287 glGetVertexAttribPointerv(
288 i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &vertex_attrib_[i].pointer);
289 glGetVertexAttribPointerv(
290 i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &vertex_attrib_[i].pointer);
291 glGetVertexAttribiv(i,
292 GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
293 &vertex_attrib_[i].vertex_attrib_array_buffer_binding);
294 glGetVertexAttribfv(
295 i, GL_CURRENT_VERTEX_ATTRIB, vertex_attrib_[i].current_vertex_attrib);
297 DCHECK(ClearGLErrors(false, NULL));
300 ScopedAppGLStateRestoreImpl::~ScopedAppGLStateRestoreImpl() {
301 TRACE_EVENT0("android_webview", "AppGLStateRestore");
302 MakeAppContextCurrent();
304 DCHECK(ClearGLErrors(false, NULL));
306 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_binding_ext_);
307 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_buffer_binding_);
309 if (g_supports_oes_vertex_array_object)
310 glBindVertexArrayOES(0);
312 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(vertex_attrib_); ++i) {
313 glBindBuffer(GL_ARRAY_BUFFER,
314 vertex_attrib_[i].vertex_attrib_array_buffer_binding);
315 glVertexAttribPointer(i,
316 vertex_attrib_[i].size,
317 vertex_attrib_[i].type,
318 vertex_attrib_[i].normalized,
319 vertex_attrib_[i].stride,
320 vertex_attrib_[i].pointer);
322 glVertexAttrib4fv(i, vertex_attrib_[i].current_vertex_attrib);
324 if (vertex_attrib_[i].enabled) {
325 glEnableVertexAttribArray(i);
326 } else {
327 glDisableVertexAttribArray(i);
331 if (g_supports_oes_vertex_array_object && vertex_array_bindings_oes_ != 0)
332 glBindVertexArrayOES(vertex_array_bindings_oes_);
334 glBindBuffer(GL_ARRAY_BUFFER, vertex_array_buffer_binding_);
336 for (int ii = 0; ii < g_gl_max_texture_units; ++ii) {
337 glActiveTexture(GL_TEXTURE0 + ii);
338 TextureBindings& bindings = texture_bindings_[ii];
339 glBindTexture(GL_TEXTURE_2D, bindings.texture_2d);
340 glBindTexture(GL_TEXTURE_CUBE_MAP, bindings.texture_cube_map);
341 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bindings.texture_external_oes);
343 glActiveTexture(active_texture_);
345 glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment_);
346 glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment_);
348 GLEnableDisable(GL_DEPTH_TEST, depth_test_);
350 GLEnableDisable(GL_CULL_FACE, cull_face_);
351 glCullFace(cull_face_mode_);
353 glColorMask(color_mask_[0], color_mask_[1], color_mask_[2], color_mask_[3]);
355 glUseProgram(current_program_);
357 glClearColor(
358 color_clear_[0], color_clear_[1], color_clear_[2], color_clear_[3]);
359 glBlendColor(
360 blend_color_[0], blend_color_[1], blend_color_[2], blend_color_[3]);
361 glClearDepth(depth_clear_);
362 glDepthFunc(depth_func_);
363 glDepthMask(depth_mask_);
364 glDepthRange(depth_rage_[0], depth_rage_[1]);
365 glFrontFace(front_face_);
366 glHint(GL_GENERATE_MIPMAP_HINT, hint_generate_mipmap_);
367 // TODO(boliu): GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES ??
368 glLineWidth(line_width_);
369 glPolygonOffset(polygon_offset_factor_, polygon_offset_units_);
370 glSampleCoverage(sample_coverage_value_, sample_coverage_invert_);
371 glBlendEquationSeparate(blend_equation_rgb_, blend_equation_alpha_);
373 GLEnableDisable(GL_DITHER, enable_dither_);
374 GLEnableDisable(GL_POLYGON_OFFSET_FILL, enable_polygon_offset_fill_);
375 GLEnableDisable(GL_SAMPLE_ALPHA_TO_COVERAGE,
376 enable_sample_alpha_to_coverage_);
377 GLEnableDisable(GL_SAMPLE_COVERAGE, enable_sample_coverage_);
379 switch(mode_) {
380 case ScopedAppGLStateRestore::MODE_DRAW:
381 // No-op.
382 break;
383 case ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT:
384 GLEnableDisable(GL_BLEND, blend_enabled_);
385 glBlendFuncSeparate(
386 blend_src_rgb_, blend_dest_rgb_, blend_src_alpha_, blend_dest_alpha_);
388 glViewport(viewport_[0], viewport_[1], viewport_[2], viewport_[3]);
390 GLEnableDisable(GL_SCISSOR_TEST, scissor_test_);
392 glScissor(
393 scissor_box_[0], scissor_box_[1], scissor_box_[2], scissor_box_[3]);
394 break;
397 GLEnableDisable(GL_STENCIL_TEST, stencil_test_);
398 glStencilFuncSeparate(
399 GL_FRONT, stencil_front_func_, stencil_front_mask_, stencil_front_ref_);
400 glStencilFuncSeparate(
401 GL_BACK, stencil_back_func_, stencil_back_mask_, stencil_back_ref_);
402 glClearStencil(stencil_clear_);
403 glStencilMaskSeparate(GL_FRONT, stencil_front_writemask_);
404 glStencilMaskSeparate(GL_BACK, stencil_back_writemask_);
405 glStencilOpSeparate(GL_FRONT,
406 stencil_front_fail_op_,
407 stencil_front_z_fail_op_,
408 stencil_front_z_pass_op_);
409 glStencilOpSeparate(GL_BACK,
410 stencil_back_fail_op_,
411 stencil_back_z_fail_op_,
412 stencil_back_z_pass_op_);
414 // Do not leak GLError out of chromium.
415 ClearGLErrors(true, "Chromium GLError");
418 } // namespace internal
420 ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode)
421 : impl_(new internal::ScopedAppGLStateRestoreImpl(mode)) {
424 ScopedAppGLStateRestore::~ScopedAppGLStateRestore() {}
426 bool ScopedAppGLStateRestore::stencil_enabled() const {
427 return impl_->stencil_enabled();
429 int ScopedAppGLStateRestore::framebuffer_binding_ext() const {
430 return impl_->framebuffer_binding_ext();
433 } // namespace android_webview