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