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 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 102 ContextState::~ContextState() { 103 } 104 105 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 150 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 161 void ContextState::RestoreRenderbufferBindings() const { 162 // Restore Bindings 163 glBindRenderbufferEXT( 164 GL_RENDERBUFFER, 165 bound_renderbuffer.get() ? bound_renderbuffer->service_id() : 0); 166 } 167 168 void ContextState::RestoreProgramBindings() const { 169 glUseProgram(current_program.get() ? current_program->service_id() : 0); 170 } 171 172 void ContextState::RestoreActiveTexture() const { 173 glActiveTexture(GL_TEXTURE0 + active_texture_unit); 174 } 175 176 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 185 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 192 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 199 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 245 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 275 void ContextState::RestoreGlobalState(const ContextState* prev_state) const { 276 InitCapabilities(prev_state); 277 InitState(prev_state); 278 } 279 280 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 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