- add sources.
[platform/framework/web/crosswalk.git] / src / android_webview / browser / scoped_app_gl_state_restore.cc
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.
4
5 #include "android_webview/browser/scoped_app_gl_state_restore.h"
6
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"
11
12 namespace android_webview {
13
14 namespace {
15
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 {
19  public:
20   AppContextSurface()
21       : surface(new gfx::GLSurfaceStub),
22         context(gfx::GLContext::CreateGLContext(NULL,
23                                                 surface.get(),
24                                                 gfx::PreferDiscreteGpu)) {}
25   void MakeCurrent() { context->MakeCurrent(surface.get()); }
26
27  private:
28   scoped_refptr<gfx::GLSurfaceStub> surface;
29   scoped_refptr<gfx::GLContext> context;
30
31   DISALLOW_COPY_AND_ASSIGN(AppContextSurface);
32 };
33
34 base::LazyInstance<AppContextSurface> g_app_context_surface =
35     LAZY_INSTANCE_INITIALIZER;
36
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();
42 }
43
44 void GLEnableDisable(GLenum cap, bool enable) {
45   if (enable)
46     glEnable(cap);
47   else
48     glDisable(cap);
49 }
50
51 GLint g_gl_max_texture_units = 0;
52
53 }  // namespace
54
55 ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode) : mode_(mode) {
56   TRACE_EVENT0("android_webview", "AppGLStateSave");
57   MakeAppContextCurrent();
58
59   glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vertex_array_buffer_binding_);
60   glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &index_array_buffer_binding_);
61
62   switch(mode_) {
63     case MODE_DRAW:
64       DCHECK_EQ(0, vertex_array_buffer_binding_);
65       DCHECK_EQ(0, index_array_buffer_binding_);
66       break;
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_);
76       break;
77   }
78
79   glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment_);
80   glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment_);
81
82   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(vertex_attrib_); ++i) {
83     glGetVertexAttribiv(
84         i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &vertex_attrib_[i].enabled);
85     glGetVertexAttribiv(
86         i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &vertex_attrib_[i].size);
87     glGetVertexAttribiv(
88         i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &vertex_attrib_[i].type);
89     glGetVertexAttribiv(
90         i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &vertex_attrib_[i].normalized);
91     glGetVertexAttribiv(
92         i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &vertex_attrib_[i].stride);
93     glGetVertexAttribPointerv(
94         i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &vertex_attrib_[i].pointer);
95   }
96
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, &current_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_);
114
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_);
119
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_);
124
125   glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &framebuffer_binding_ext_);
126
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);
130   }
131
132   glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture_);
133
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);
142   }
143 }
144
145 ScopedAppGLStateRestore::~ScopedAppGLStateRestore() {
146   TRACE_EVENT0("android_webview", "AppGLStateRestore");
147   MakeAppContextCurrent();
148
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_);
152
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);
159   }
160   glActiveTexture(active_texture_);
161
162   glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment_);
163   glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment_);
164
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);
172
173     if (vertex_attrib_[i].enabled) {
174       glEnableVertexAttribArray(i);
175     } else {
176       glDisableVertexAttribArray(i);
177     }
178   }
179
180   GLEnableDisable(GL_DEPTH_TEST, depth_test_);
181
182   GLEnableDisable(GL_CULL_FACE, cull_face_);
183   glCullFace(cull_face_mode_);
184
185   glColorMask(color_mask_[0], color_mask_[1], color_mask_[2], color_mask_[3]);
186
187   glUseProgram(current_program_);
188
189   glClearColor(
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_);
201
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_);
207
208   switch(mode_) {
209     case MODE_DRAW:
210       // No-op.
211       break;
212     case MODE_RESOURCE_MANAGEMENT:
213       GLEnableDisable(GL_BLEND, blend_enabled_);
214       glBlendFuncSeparate(
215           blend_src_rgb_, blend_dest_rgb_, blend_src_alpha_, blend_dest_alpha_);
216
217       glViewport(viewport_[0], viewport_[1], viewport_[2], viewport_[3]);
218
219       GLEnableDisable(GL_SCISSOR_TEST, scissor_test_);
220
221       glScissor(
222           scissor_box_[0], scissor_box_[1], scissor_box_[2], scissor_box_[3]);
223       break;
224   }
225
226   GLEnableDisable(GL_STENCIL_TEST, stencil_test_);
227   glStencilFunc(stencil_func_, stencil_mask_, stencil_ref_);
228 }
229
230 }  // namespace android_webview