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 "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