Home | History | Annotate | Download | only in service
      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