f046872a72ff9887d9bbb89de3b807c46a195c6e
[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 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, Logger* logger)
91     : active_texture_unit(0),
92       pack_reverse_row_order(false),
93       fbo_binding_for_scissor_workaround_dirty_(false),
94       feature_info_(feature_info),
95       error_state_(ErrorState::Create(logger)) {
96   Initialize();
97 }
98
99 ContextState::~ContextState() {
100 }
101
102 void ContextState::RestoreTextureUnitBindings(
103     GLuint unit, const ContextState* prev_state) const {
104   DCHECK_LT(unit, texture_units.size());
105   const TextureUnit& texture_unit = texture_units[unit];
106   GLuint service_id_2d = Get2dServiceId(texture_unit);
107   GLuint service_id_cube = GetCubeServiceId(texture_unit);
108   GLuint service_id_oes = GetOesServiceId(texture_unit);
109   GLuint service_id_arb = GetArbServiceId(texture_unit);
110
111   bool bind_texture_2d = true;
112   bool bind_texture_cube = true;
113   bool bind_texture_oes = feature_info_->feature_flags().oes_egl_image_external;
114   bool bind_texture_arb = feature_info_->feature_flags().arb_texture_rectangle;
115
116   if (prev_state) {
117     const TextureUnit& prev_unit = prev_state->texture_units[unit];
118     bind_texture_2d = service_id_2d != Get2dServiceId(prev_unit);
119     bind_texture_cube = service_id_cube != GetCubeServiceId(prev_unit);
120     bind_texture_oes =
121         bind_texture_oes && service_id_oes != GetOesServiceId(prev_unit);
122     bind_texture_arb =
123         bind_texture_arb && service_id_arb != GetArbServiceId(prev_unit);
124   }
125
126   // Early-out if nothing has changed from the previous state.
127   if (!bind_texture_2d && !bind_texture_cube
128       && !bind_texture_oes && !bind_texture_arb) {
129     return;
130   }
131
132   glActiveTexture(GL_TEXTURE0 + unit);
133   if (bind_texture_2d) {
134     glBindTexture(GL_TEXTURE_2D, service_id_2d);
135   }
136   if (bind_texture_cube) {
137     glBindTexture(GL_TEXTURE_CUBE_MAP, service_id_cube);
138   }
139   if (bind_texture_oes) {
140     glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id_oes);
141   }
142   if (bind_texture_arb) {
143     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, service_id_arb);
144   }
145 }
146
147 void ContextState::RestoreBufferBindings() const {
148   if (vertex_attrib_manager.get()) {
149     Buffer* element_array_buffer =
150         vertex_attrib_manager->element_array_buffer();
151     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
152         element_array_buffer ? element_array_buffer->service_id() : 0);
153   }
154   glBindBuffer(GL_ARRAY_BUFFER,
155                bound_array_buffer.get() ? bound_array_buffer->service_id() : 0);
156 }
157
158 void ContextState::RestoreRenderbufferBindings() const {
159   // Restore Bindings
160   glBindRenderbufferEXT(
161       GL_RENDERBUFFER,
162       bound_renderbuffer.get() ? bound_renderbuffer->service_id() : 0);
163 }
164
165 void ContextState::RestoreProgramBindings() const {
166   glUseProgram(current_program.get() ? current_program->service_id() : 0);
167 }
168
169 void ContextState::RestoreActiveTexture() const {
170   glActiveTexture(GL_TEXTURE0 + active_texture_unit);
171 }
172
173 void ContextState::RestoreAllTextureUnitBindings(
174     const ContextState* prev_state) const {
175   // Restore Texture state.
176   for (size_t ii = 0; ii < texture_units.size(); ++ii) {
177     RestoreTextureUnitBindings(ii, prev_state);
178   }
179   RestoreActiveTexture();
180 }
181
182 void ContextState::RestoreActiveTextureUnitBinding(unsigned int target) const {
183   DCHECK_LT(active_texture_unit, texture_units.size());
184   const TextureUnit& texture_unit = texture_units[active_texture_unit];
185   if (TargetIsSupported(feature_info_, target))
186     glBindTexture(target, GetServiceId(texture_unit, target));
187 }
188
189 void ContextState::RestoreAttribute(GLuint attrib_index) const {
190   const VertexAttrib* attrib =
191       vertex_attrib_manager->GetVertexAttrib(attrib_index);
192   const void* ptr = reinterpret_cast<const void*>(attrib->offset());
193   Buffer* buffer = attrib->buffer();
194   glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
195   glVertexAttribPointer(
196       attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
197       attrib->gl_stride(), ptr);
198   if (attrib->divisor())
199     glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
200   // Never touch vertex attribute 0's state (in particular, never
201   // disable it) when running on desktop GL because it will never be
202   // re-enabled.
203   if (attrib_index != 0 ||
204       gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
205     if (attrib->enabled()) {
206       glEnableVertexAttribArray(attrib_index);
207     } else {
208       glDisableVertexAttribArray(attrib_index);
209     }
210   }
211   glVertexAttrib4fv(attrib_index, attrib_values[attrib_index].v);
212 }
213
214 void ContextState::RestoreGlobalState() const {
215   InitCapabilities();
216   InitState();
217 }
218
219 void ContextState::RestoreState(const ContextState* prev_state) const {
220   RestoreAllTextureUnitBindings(prev_state);
221
222   // Restore Attrib State
223   // TODO: This if should not be needed. RestoreState is getting called
224   // before GLES2Decoder::Initialize which is a bug.
225   if (vertex_attrib_manager.get()) {
226     // TODO(gman): Move this restoration to VertexAttribManager.
227     for (size_t attrib = 0; attrib < vertex_attrib_manager->num_attribs();
228          ++attrib) {
229       RestoreAttribute(attrib);
230     }
231   }
232
233   RestoreBufferBindings();
234   RestoreRenderbufferBindings();
235   RestoreProgramBindings();
236   RestoreGlobalState();
237 }
238
239 ErrorState* ContextState::GetErrorState() {
240   return error_state_.get();
241 }
242
243 // Include the auto-generated part of this file. We split this because it means
244 // we can easily edit the non-auto generated parts right here in this file
245 // instead of having to edit some template or the code generator.
246 #include "gpu/command_buffer/service/context_state_impl_autogen.h"
247
248 }  // namespace gles2
249 }  // namespace gpu
250
251