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 303