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.
5 #include "gpu/command_buffer/service/context_state.h"
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"
21 void EnableDisable(GLenum pname, bool enable) {
29 GLuint Get2dServiceId(const TextureUnit& unit) {
30 return unit.bound_texture_2d.get()
31 ? unit.bound_texture_2d->service_id() : 0;
34 GLuint GetCubeServiceId(const TextureUnit& unit) {
35 return unit.bound_texture_cube_map.get()
36 ? unit.bound_texture_cube_map->service_id() : 0;
39 GLuint GetOesServiceId(const TextureUnit& unit) {
40 return unit.bound_texture_external_oes.get()
41 ? unit.bound_texture_external_oes->service_id() : 0;
44 GLuint GetArbServiceId(const TextureUnit& unit) {
45 return unit.bound_texture_rectangle_arb.get()
46 ? unit.bound_texture_rectangle_arb->service_id() : 0;
49 GLuint GetServiceId(const TextureUnit& unit, GLuint target) {
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);
65 bool TargetIsSupported(const FeatureInfo* feature_info, GLuint target) {
69 case GL_TEXTURE_CUBE_MAP:
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;
81 } // anonymous namespace.
83 TextureUnit::TextureUnit()
84 : bind_target(GL_TEXTURE_2D) {
87 TextureUnit::~TextureUnit() {
90 ContextState::ContextState(FeatureInfo* feature_info, Logger* logger)
91 : active_texture_unit(0),
92 pack_reverse_row_order(false),
93 fbo_binding_for_scissor_workaround_dirty_(false),
94 feature_info_(feature_info),
95 error_state_(ErrorState::Create(logger)) {
99 ContextState::~ContextState() {
102 void ContextState::RestoreTextureUnitBindings(
103 GLuint unit, const ContextState* prev_state) const {
104 DCHECK_LT(unit, texture_units.size());
105 const TextureUnit& texture_unit = texture_units[unit];
106 GLuint service_id_2d = Get2dServiceId(texture_unit);
107 GLuint service_id_cube = GetCubeServiceId(texture_unit);
108 GLuint service_id_oes = GetOesServiceId(texture_unit);
109 GLuint service_id_arb = GetArbServiceId(texture_unit);
111 bool bind_texture_2d = true;
112 bool bind_texture_cube = true;
113 bool bind_texture_oes = feature_info_->feature_flags().oes_egl_image_external;
114 bool bind_texture_arb = feature_info_->feature_flags().arb_texture_rectangle;
117 const TextureUnit& prev_unit = prev_state->texture_units[unit];
118 bind_texture_2d = service_id_2d != Get2dServiceId(prev_unit);
119 bind_texture_cube = service_id_cube != GetCubeServiceId(prev_unit);
121 bind_texture_oes && service_id_oes != GetOesServiceId(prev_unit);
123 bind_texture_arb && service_id_arb != GetArbServiceId(prev_unit);
126 // Early-out if nothing has changed from the previous state.
127 if (!bind_texture_2d && !bind_texture_cube
128 && !bind_texture_oes && !bind_texture_arb) {
132 glActiveTexture(GL_TEXTURE0 + unit);
133 if (bind_texture_2d) {
134 glBindTexture(GL_TEXTURE_2D, service_id_2d);
136 if (bind_texture_cube) {
137 glBindTexture(GL_TEXTURE_CUBE_MAP, service_id_cube);
139 if (bind_texture_oes) {
140 glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id_oes);
142 if (bind_texture_arb) {
143 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, service_id_arb);
147 void ContextState::RestoreBufferBindings() const {
148 if (vertex_attrib_manager.get()) {
149 Buffer* element_array_buffer =
150 vertex_attrib_manager->element_array_buffer();
151 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
152 element_array_buffer ? element_array_buffer->service_id() : 0);
154 glBindBuffer(GL_ARRAY_BUFFER,
155 bound_array_buffer.get() ? bound_array_buffer->service_id() : 0);
158 void ContextState::RestoreRenderbufferBindings() const {
160 glBindRenderbufferEXT(
162 bound_renderbuffer.get() ? bound_renderbuffer->service_id() : 0);
165 void ContextState::RestoreProgramBindings() const {
166 glUseProgram(current_program.get() ? current_program->service_id() : 0);
169 void ContextState::RestoreActiveTexture() const {
170 glActiveTexture(GL_TEXTURE0 + active_texture_unit);
173 void ContextState::RestoreAllTextureUnitBindings(
174 const ContextState* prev_state) const {
175 // Restore Texture state.
176 for (size_t ii = 0; ii < texture_units.size(); ++ii) {
177 RestoreTextureUnitBindings(ii, prev_state);
179 RestoreActiveTexture();
182 void ContextState::RestoreActiveTextureUnitBinding(unsigned int target) const {
183 DCHECK_LT(active_texture_unit, texture_units.size());
184 const TextureUnit& texture_unit = texture_units[active_texture_unit];
185 if (TargetIsSupported(feature_info_, target))
186 glBindTexture(target, GetServiceId(texture_unit, target));
189 void ContextState::RestoreAttribute(GLuint attrib_index) const {
190 const VertexAttrib* attrib =
191 vertex_attrib_manager->GetVertexAttrib(attrib_index);
192 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
193 Buffer* buffer = attrib->buffer();
194 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
195 glVertexAttribPointer(
196 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
197 attrib->gl_stride(), ptr);
198 if (attrib->divisor())
199 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
200 // Never touch vertex attribute 0's state (in particular, never
201 // disable it) when running on desktop GL because it will never be
203 if (attrib_index != 0 ||
204 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
205 if (attrib->enabled()) {
206 glEnableVertexAttribArray(attrib_index);
208 glDisableVertexAttribArray(attrib_index);
211 glVertexAttrib4fv(attrib_index, attrib_values[attrib_index].v);
214 void ContextState::RestoreGlobalState() const {
219 void ContextState::RestoreState(const ContextState* prev_state) const {
220 RestoreAllTextureUnitBindings(prev_state);
222 // Restore Attrib State
223 // TODO: This if should not be needed. RestoreState is getting called
224 // before GLES2Decoder::Initialize which is a bug.
225 if (vertex_attrib_manager.get()) {
226 // TODO(gman): Move this restoration to VertexAttribManager.
227 for (size_t attrib = 0; attrib < vertex_attrib_manager->num_attribs();
229 RestoreAttribute(attrib);
233 RestoreBufferBindings();
234 RestoreRenderbufferBindings();
235 RestoreProgramBindings();
236 RestoreGlobalState();
239 ErrorState* ContextState::GetErrorState() {
240 return error_state_.get();
243 // Include the auto-generated part of this file. We split this because it means
244 // we can easily edit the non-auto generated parts right here in this file
245 // instead of having to edit some template or the code generator.
246 #include "gpu/command_buffer/service/context_state_impl_autogen.h"