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"
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"
23 static void EnableDisable(GLenum pname
, bool enable
) {
31 GLuint
Get2dServiceId(const TextureUnit
& unit
) {
32 return unit
.bound_texture_2d
.get()
33 ? unit
.bound_texture_2d
->service_id() : 0;
36 GLuint
GetCubeServiceId(const TextureUnit
& unit
) {
37 return unit
.bound_texture_cube_map
.get()
38 ? unit
.bound_texture_cube_map
->service_id() : 0;
41 GLuint
GetOesServiceId(const TextureUnit
& unit
) {
42 return unit
.bound_texture_external_oes
.get()
43 ? unit
.bound_texture_external_oes
->service_id() : 0;
46 GLuint
GetArbServiceId(const TextureUnit
& unit
) {
47 return unit
.bound_texture_rectangle_arb
.get()
48 ? unit
.bound_texture_rectangle_arb
->service_id() : 0;
51 GLuint
GetServiceId(const TextureUnit
& unit
, GLuint target
) {
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
);
67 bool TargetIsSupported(const FeatureInfo
* feature_info
, GLuint target
) {
71 case GL_TEXTURE_CUBE_MAP
:
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
;
83 } // anonymous namespace.
85 TextureUnit::TextureUnit()
86 : bind_target(GL_TEXTURE_2D
) {
89 TextureUnit::~TextureUnit() {
92 ContextState::ContextState(FeatureInfo
* feature_info
,
93 ErrorStateClient
* error_state_client
,
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
)) {
105 ContextState::~ContextState() {
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
);
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
;
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
);
127 bind_texture_oes
&& service_id_oes
!= GetOesServiceId(prev_unit
);
129 bind_texture_arb
&& service_id_arb
!= GetArbServiceId(prev_unit
);
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
) {
138 glActiveTexture(GL_TEXTURE0
+ unit
);
139 if (bind_texture_2d
) {
140 glBindTexture(GL_TEXTURE_2D
, service_id_2d
);
142 if (bind_texture_cube
) {
143 glBindTexture(GL_TEXTURE_CUBE_MAP
, service_id_cube
);
145 if (bind_texture_oes
) {
146 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, service_id_oes
);
148 if (bind_texture_arb
) {
149 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, service_id_arb
);
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);
160 glBindBuffer(GL_ARRAY_BUFFER
,
161 bound_array_buffer
.get() ? bound_array_buffer
->service_id() : 0);
164 void ContextState::RestoreRenderbufferBindings() {
165 // Require Renderbuffer rebind.
166 bound_renderbuffer_valid
= false;
169 void ContextState::RestoreProgramBindings() const {
170 glUseProgram(current_program
.get() ? current_program
->service_id() : 0);
173 void ContextState::RestoreActiveTexture() const {
174 glActiveTexture(GL_TEXTURE0
+ active_texture_unit
);
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
);
183 RestoreActiveTexture();
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
));
193 void ContextState::RestoreVertexAttribValues() const {
194 for (size_t attrib
= 0; attrib
< vertex_attrib_manager
->num_attribs();
196 glVertexAttrib4fv(attrib
, attrib_values
[attrib
].v
);
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);
207 // Bind VAO if supported.
208 if (feature_info_
->feature_flags().native_vertex_array_object
)
209 glBindVertexArrayOES(vao_service_id
);
211 // Restore vertex attrib arrays.
212 for (size_t attrib_index
= 0; attrib_index
< attrib_manager
->num_attribs();
214 const VertexAttrib
* attrib
= attrib_manager
->GetVertexAttrib(attrib_index
);
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
,
224 attrib
->normalized(),
228 // Restore attrib divisor if supported.
229 if (feature_info_
->feature_flags().angle_instanced_arrays
)
230 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
232 // Never touch vertex attribute 0's state (in particular, never
233 // disable it) when running on desktop GL because it will never be
235 if (attrib_index
!= 0 ||
236 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
237 if (attrib
->enabled()) {
238 glEnableVertexAttribArray(attrib_index
);
240 glDisableVertexAttribArray(attrib_index
);
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()) {
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
);
260 // Restore the current VAO binding, unless it's the same as the
262 GLuint curr_vao_service_id
= vertex_attrib_manager
->service_id();
263 if (curr_vao_service_id
!= 0)
264 glBindVertexArrayOES(curr_vao_service_id
);
266 // If native VAO isn't supported, emulated VAOs are used.
267 // Restore to the currently bound VAO.
268 RestoreVertexAttribArrays(vertex_attrib_manager
);
272 // glVertexAttrib4fv aren't part of VAO state and must be restored.
273 RestoreVertexAttribValues();
276 void ContextState::RestoreGlobalState(const ContextState
* prev_state
) const {
277 InitCapabilities(prev_state
);
278 InitState(prev_state
);
281 void ContextState::RestoreState(const ContextState
* prev_state
) {
282 RestoreAllTextureUnitBindings(prev_state
);
283 RestoreVertexAttribs();
284 RestoreBufferBindings();
285 RestoreRenderbufferBindings();
286 RestoreProgramBindings();
287 RestoreGlobalState(prev_state
);
290 ErrorState
* ContextState::GetErrorState() {
291 return error_state_
.get();
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"