Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / context_state.cc
1 // Copyright (c) 2012 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 "gpu/command_buffer/service/context_state.h"
6
7 #include <cmath>
8
9 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
10 #include "gpu/command_buffer/service/buffer_manager.h"
11 #include "gpu/command_buffer/service/error_state.h"
12 #include "gpu/command_buffer/service/framebuffer_manager.h"
13 #include "gpu/command_buffer/service/program_manager.h"
14 #include "gpu/command_buffer/service/renderbuffer_manager.h"
15 #include "ui/gl/gl_bindings.h"
16 #include "ui/gl/gl_implementation.h"
17
18 namespace gpu {
19 namespace gles2 {
20
21 namespace {
22
23 static void EnableDisable(GLenum pname, bool enable) {
24   if (enable) {
25     glEnable(pname);
26   } else {
27     glDisable(pname);
28   }
29 }
30
31 GLuint Get2dServiceId(const TextureUnit& unit) {
32   return unit.bound_texture_2d.get()
33       ? unit.bound_texture_2d->service_id() : 0;
34 }
35
36 GLuint GetCubeServiceId(const TextureUnit& unit) {
37   return unit.bound_texture_cube_map.get()
38       ? unit.bound_texture_cube_map->service_id() : 0;
39 }
40
41 GLuint GetOesServiceId(const TextureUnit& unit) {
42   return unit.bound_texture_external_oes.get()
43       ? unit.bound_texture_external_oes->service_id() : 0;
44 }
45
46 GLuint GetArbServiceId(const TextureUnit& unit) {
47   return unit.bound_texture_rectangle_arb.get()
48       ? unit.bound_texture_rectangle_arb->service_id() : 0;
49 }
50
51 GLuint GetServiceId(const TextureUnit& unit, GLuint target) {
52   switch (target) {
53     case GL_TEXTURE_2D:
54       return Get2dServiceId(unit);
55     case GL_TEXTURE_CUBE_MAP:
56       return GetCubeServiceId(unit);
57     case GL_TEXTURE_RECTANGLE_ARB:
58       return GetArbServiceId(unit);
59     case GL_TEXTURE_EXTERNAL_OES:
60       return GetOesServiceId(unit);
61     default:
62       NOTREACHED();
63       return 0;
64   }
65 }
66
67 bool TargetIsSupported(const FeatureInfo* feature_info, GLuint target) {
68   switch (target) {
69     case GL_TEXTURE_2D:
70       return true;
71     case GL_TEXTURE_CUBE_MAP:
72       return true;
73     case GL_TEXTURE_RECTANGLE_ARB:
74       return feature_info->feature_flags().arb_texture_rectangle;
75     case GL_TEXTURE_EXTERNAL_OES:
76       return feature_info->feature_flags().oes_egl_image_external;
77     default:
78       NOTREACHED();
79       return false;
80   }
81 }
82
83 }  // anonymous namespace.
84
85 TextureUnit::TextureUnit()
86     : bind_target(GL_TEXTURE_2D) {
87 }
88
89 TextureUnit::~TextureUnit() {
90 }
91
92 ContextState::ContextState(FeatureInfo* feature_info,
93                            ErrorStateClient* error_state_client,
94                            Logger* logger)
95     : active_texture_unit(0),
96       bound_renderbuffer_valid(false),
97       pack_reverse_row_order(false),
98       ignore_cached_state(false),
99       fbo_binding_for_scissor_workaround_dirty_(false),
100       feature_info_(feature_info),
101       error_state_(ErrorState::Create(error_state_client, logger)) {
102   Initialize();
103 }
104
105 ContextState::~ContextState() {
106 }
107
108 void ContextState::RestoreTextureUnitBindings(
109     GLuint unit, const ContextState* prev_state) const {
110   DCHECK_LT(unit, texture_units.size());
111   const TextureUnit& texture_unit = texture_units[unit];
112   GLuint service_id_2d = Get2dServiceId(texture_unit);
113   GLuint service_id_cube = GetCubeServiceId(texture_unit);
114   GLuint service_id_oes = GetOesServiceId(texture_unit);
115   GLuint service_id_arb = GetArbServiceId(texture_unit);
116
117   bool bind_texture_2d = true;
118   bool bind_texture_cube = true;
119   bool bind_texture_oes = feature_info_->feature_flags().oes_egl_image_external;
120   bool bind_texture_arb = feature_info_->feature_flags().arb_texture_rectangle;
121
122   if (prev_state) {
123     const TextureUnit& prev_unit = prev_state->texture_units[unit];
124     bind_texture_2d = service_id_2d != Get2dServiceId(prev_unit);
125     bind_texture_cube = service_id_cube != GetCubeServiceId(prev_unit);
126     bind_texture_oes =
127         bind_texture_oes && service_id_oes != GetOesServiceId(prev_unit);
128     bind_texture_arb =
129         bind_texture_arb && service_id_arb != GetArbServiceId(prev_unit);
130   }
131
132   // Early-out if nothing has changed from the previous state.
133   if (!bind_texture_2d && !bind_texture_cube
134       && !bind_texture_oes && !bind_texture_arb) {
135     return;
136   }
137
138   glActiveTexture(GL_TEXTURE0 + unit);
139   if (bind_texture_2d) {
140     glBindTexture(GL_TEXTURE_2D, service_id_2d);
141   }
142   if (bind_texture_cube) {
143     glBindTexture(GL_TEXTURE_CUBE_MAP, service_id_cube);
144   }
145   if (bind_texture_oes) {
146     glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id_oes);
147   }
148   if (bind_texture_arb) {
149     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, service_id_arb);
150   }
151 }
152
153 void ContextState::RestoreBufferBindings() const {
154   if (vertex_attrib_manager.get()) {
155     Buffer* element_array_buffer =
156         vertex_attrib_manager->element_array_buffer();
157     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
158         element_array_buffer ? element_array_buffer->service_id() : 0);
159   }
160   glBindBuffer(GL_ARRAY_BUFFER,
161                bound_array_buffer.get() ? bound_array_buffer->service_id() : 0);
162 }
163
164 void ContextState::RestoreRenderbufferBindings() {
165   // Require Renderbuffer rebind.
166   bound_renderbuffer_valid = false;
167 }
168
169 void ContextState::RestoreProgramBindings() const {
170   glUseProgram(current_program.get() ? current_program->service_id() : 0);
171 }
172
173 void ContextState::RestoreActiveTexture() const {
174   glActiveTexture(GL_TEXTURE0 + active_texture_unit);
175 }
176
177 void ContextState::RestoreAllTextureUnitBindings(
178     const ContextState* prev_state) const {
179   // Restore Texture state.
180   for (size_t ii = 0; ii < texture_units.size(); ++ii) {
181     RestoreTextureUnitBindings(ii, prev_state);
182   }
183   RestoreActiveTexture();
184 }
185
186 void ContextState::RestoreActiveTextureUnitBinding(unsigned int target) const {
187   DCHECK_LT(active_texture_unit, texture_units.size());
188   const TextureUnit& texture_unit = texture_units[active_texture_unit];
189   if (TargetIsSupported(feature_info_, target))
190     glBindTexture(target, GetServiceId(texture_unit, target));
191 }
192
193 void ContextState::RestoreVertexAttribValues() const {
194   for (size_t attrib = 0; attrib < vertex_attrib_manager->num_attribs();
195        ++attrib) {
196     glVertexAttrib4fv(attrib, attrib_values[attrib].v);
197   }
198 }
199
200 void ContextState::RestoreVertexAttribArrays(
201     const scoped_refptr<VertexAttribManager> attrib_manager) const {
202   // This is expected to be called only for VAO with service_id 0,
203   // either to restore the default VAO or a virtual VAO with service_id 0.
204   GLuint vao_service_id = attrib_manager->service_id();
205   DCHECK(vao_service_id == 0);
206
207   // Bind VAO if supported.
208   if (feature_info_->feature_flags().native_vertex_array_object)
209     glBindVertexArrayOES(vao_service_id);
210
211   // Restore vertex attrib arrays.
212   for (size_t attrib_index = 0; attrib_index < attrib_manager->num_attribs();
213        ++attrib_index) {
214     const VertexAttrib* attrib = attrib_manager->GetVertexAttrib(attrib_index);
215
216     // Restore vertex array.
217     Buffer* buffer = attrib->buffer();
218     GLuint buffer_service_id = buffer ? buffer->service_id() : 0;
219     glBindBuffer(GL_ARRAY_BUFFER, buffer_service_id);
220     const void* ptr = reinterpret_cast<const void*>(attrib->offset());
221     glVertexAttribPointer(attrib_index,
222                           attrib->size(),
223                           attrib->type(),
224                           attrib->normalized(),
225                           attrib->gl_stride(),
226                           ptr);
227
228     // Restore attrib divisor if supported.
229     if (feature_info_->feature_flags().angle_instanced_arrays)
230       glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
231
232     // Never touch vertex attribute 0's state (in particular, never
233     // disable it) when running on desktop GL because it will never be
234     // re-enabled.
235     if (attrib_index != 0 ||
236         gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
237       if (attrib->enabled()) {
238         glEnableVertexAttribArray(attrib_index);
239       } else {
240         glDisableVertexAttribArray(attrib_index);
241       }
242     }
243   }
244 }
245
246 void ContextState::RestoreVertexAttribs() const {
247   // Restore Vertex Attrib Arrays
248   // TODO: This if should not be needed. RestoreState is getting called
249   // before GLES2Decoder::Initialize which is a bug.
250   if (vertex_attrib_manager.get()) {
251     // Restore VAOs.
252     if (feature_info_->feature_flags().native_vertex_array_object) {
253       // If default VAO is still using shared id 0 instead of unique ids
254       // per-context, default VAO state must be restored.
255       GLuint default_vao_service_id =
256           default_vertex_attrib_manager->service_id();
257       if (default_vao_service_id == 0)
258         RestoreVertexAttribArrays(default_vertex_attrib_manager);
259
260       // Restore the current VAO binding, unless it's the same as the
261       // default above.
262       GLuint curr_vao_service_id = vertex_attrib_manager->service_id();
263       if (curr_vao_service_id != 0)
264         glBindVertexArrayOES(curr_vao_service_id);
265     } else {
266       // If native VAO isn't supported, emulated VAOs are used.
267       // Restore to the currently bound VAO.
268       RestoreVertexAttribArrays(vertex_attrib_manager);
269     }
270   }
271
272   // glVertexAttrib4fv aren't part of VAO state and must be restored.
273   RestoreVertexAttribValues();
274 }
275
276 void ContextState::RestoreGlobalState(const ContextState* prev_state) const {
277   InitCapabilities(prev_state);
278   InitState(prev_state);
279 }
280
281 void ContextState::RestoreState(const ContextState* prev_state) {
282   RestoreAllTextureUnitBindings(prev_state);
283   RestoreVertexAttribs();
284   RestoreBufferBindings();
285   RestoreRenderbufferBindings();
286   RestoreProgramBindings();
287   RestoreGlobalState(prev_state);
288 }
289
290 ErrorState* ContextState::GetErrorState() {
291   return error_state_.get();
292 }
293
294 // Include the auto-generated part of this file. We split this because it means
295 // we can easily edit the non-auto generated parts right here in this file
296 // instead of having to edit some template or the code generator.
297 #include "gpu/command_buffer/service/context_state_impl_autogen.h"
298
299 }  // namespace gles2
300 }  // namespace gpu
301
302