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