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 GLuint
Get2dServiceId(const TextureUnit
& unit
) {
24 return unit
.bound_texture_2d
.get()
25 ? unit
.bound_texture_2d
->service_id() : 0;
28 GLuint
GetCubeServiceId(const TextureUnit
& unit
) {
29 return unit
.bound_texture_cube_map
.get()
30 ? unit
.bound_texture_cube_map
->service_id() : 0;
33 GLuint
GetOesServiceId(const TextureUnit
& unit
) {
34 return unit
.bound_texture_external_oes
.get()
35 ? unit
.bound_texture_external_oes
->service_id() : 0;
38 GLuint
GetArbServiceId(const TextureUnit
& unit
) {
39 return unit
.bound_texture_rectangle_arb
.get()
40 ? unit
.bound_texture_rectangle_arb
->service_id() : 0;
43 GLuint
GetServiceId(const TextureUnit
& unit
, GLuint target
) {
46 return Get2dServiceId(unit
);
47 case GL_TEXTURE_CUBE_MAP
:
48 return GetCubeServiceId(unit
);
49 case GL_TEXTURE_RECTANGLE_ARB
:
50 return GetArbServiceId(unit
);
51 case GL_TEXTURE_EXTERNAL_OES
:
52 return GetOesServiceId(unit
);
59 bool TargetIsSupported(const FeatureInfo
* feature_info
, GLuint target
) {
63 case GL_TEXTURE_CUBE_MAP
:
65 case GL_TEXTURE_RECTANGLE_ARB
:
66 return feature_info
->feature_flags().arb_texture_rectangle
;
67 case GL_TEXTURE_EXTERNAL_OES
:
68 return feature_info
->feature_flags().oes_egl_image_external
;
75 GLuint
GetBufferId(const Buffer
* buffer
) {
77 return buffer
->service_id();
81 } // anonymous namespace.
83 TextureUnit::TextureUnit()
84 : bind_target(GL_TEXTURE_2D
) {
87 TextureUnit::~TextureUnit() {
90 bool Vec4::Equal(const Vec4
& other
) const {
91 if (type_
!= other
.type_
)
95 for (size_t ii
= 0; ii
< 4; ++ii
) {
96 if (v_
[ii
].float_value
!= other
.v_
[ii
].float_value
)
101 for (size_t ii
= 0; ii
< 4; ++ii
) {
102 if (v_
[ii
].int_value
!= other
.v_
[ii
].int_value
)
107 for (size_t ii
= 0; ii
< 4; ++ii
) {
108 if (v_
[ii
].uint_value
!= other
.v_
[ii
].uint_value
)
117 void Vec4::GetValues
<GLfloat
>(GLfloat
* values
) const {
121 for (size_t ii
= 0; ii
< 4; ++ii
)
122 values
[ii
] = v_
[ii
].float_value
;
125 for (size_t ii
= 0; ii
< 4; ++ii
)
126 values
[ii
] = static_cast<GLfloat
>(v_
[ii
].int_value
);
129 for (size_t ii
= 0; ii
< 4; ++ii
)
130 values
[ii
] = static_cast<GLfloat
>(v_
[ii
].uint_value
);
136 void Vec4::GetValues
<GLint
>(GLint
* values
) const {
140 for (size_t ii
= 0; ii
< 4; ++ii
)
141 values
[ii
] = static_cast<GLint
>(v_
[ii
].float_value
);
144 for (size_t ii
= 0; ii
< 4; ++ii
)
145 values
[ii
] = v_
[ii
].int_value
;
148 for (size_t ii
= 0; ii
< 4; ++ii
)
149 values
[ii
] = static_cast<GLint
>(v_
[ii
].uint_value
);
155 void Vec4::GetValues
<GLuint
>(GLuint
* values
) const {
159 for (size_t ii
= 0; ii
< 4; ++ii
)
160 values
[ii
] = static_cast<GLuint
>(v_
[ii
].float_value
);
163 for (size_t ii
= 0; ii
< 4; ++ii
)
164 values
[ii
] = static_cast<GLuint
>(v_
[ii
].int_value
);
167 for (size_t ii
= 0; ii
< 4; ++ii
)
168 values
[ii
] = v_
[ii
].uint_value
;
174 void Vec4::SetValues
<GLfloat
>(const GLfloat
* values
) {
176 for (size_t ii
= 0; ii
< 4; ++ii
)
177 v_
[ii
].float_value
= values
[ii
];
182 void Vec4::SetValues
<GLint
>(const GLint
* values
) {
184 for (size_t ii
= 0; ii
< 4; ++ii
)
185 v_
[ii
].int_value
= values
[ii
];
190 void Vec4::SetValues
<GLuint
>(const GLuint
* values
) {
192 for (size_t ii
= 0; ii
< 4; ++ii
)
193 v_
[ii
].uint_value
= values
[ii
];
197 ContextState::ContextState(FeatureInfo
* feature_info
,
198 ErrorStateClient
* error_state_client
,
200 : active_texture_unit(0),
201 bound_renderbuffer_valid(false),
202 pack_reverse_row_order(false),
203 ignore_cached_state(false),
204 fbo_binding_for_scissor_workaround_dirty(false),
205 feature_info_(feature_info
),
206 error_state_(ErrorState::Create(error_state_client
, logger
)) {
210 ContextState::~ContextState() {
213 void ContextState::RestoreTextureUnitBindings(
214 GLuint unit
, const ContextState
* prev_state
) const {
215 DCHECK_LT(unit
, texture_units
.size());
216 const TextureUnit
& texture_unit
= texture_units
[unit
];
217 GLuint service_id_2d
= Get2dServiceId(texture_unit
);
218 GLuint service_id_cube
= GetCubeServiceId(texture_unit
);
219 GLuint service_id_oes
= GetOesServiceId(texture_unit
);
220 GLuint service_id_arb
= GetArbServiceId(texture_unit
);
222 bool bind_texture_2d
= true;
223 bool bind_texture_cube
= true;
224 bool bind_texture_oes
= feature_info_
->feature_flags().oes_egl_image_external
;
225 bool bind_texture_arb
= feature_info_
->feature_flags().arb_texture_rectangle
;
228 const TextureUnit
& prev_unit
= prev_state
->texture_units
[unit
];
229 bind_texture_2d
= service_id_2d
!= Get2dServiceId(prev_unit
);
230 bind_texture_cube
= service_id_cube
!= GetCubeServiceId(prev_unit
);
232 bind_texture_oes
&& service_id_oes
!= GetOesServiceId(prev_unit
);
234 bind_texture_arb
&& service_id_arb
!= GetArbServiceId(prev_unit
);
237 // Early-out if nothing has changed from the previous state.
238 if (!bind_texture_2d
&& !bind_texture_cube
239 && !bind_texture_oes
&& !bind_texture_arb
) {
243 glActiveTexture(GL_TEXTURE0
+ unit
);
244 if (bind_texture_2d
) {
245 glBindTexture(GL_TEXTURE_2D
, service_id_2d
);
247 if (bind_texture_cube
) {
248 glBindTexture(GL_TEXTURE_CUBE_MAP
, service_id_cube
);
250 if (bind_texture_oes
) {
251 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, service_id_oes
);
253 if (bind_texture_arb
) {
254 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, service_id_arb
);
258 void ContextState::RestoreBufferBindings() const {
259 if (vertex_attrib_manager
.get()) {
260 Buffer
* element_array_buffer
=
261 vertex_attrib_manager
->element_array_buffer();
262 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, GetBufferId(element_array_buffer
));
264 glBindBuffer(GL_ARRAY_BUFFER
, GetBufferId(bound_array_buffer
.get()));
265 if (feature_info_
->IsES3Enabled()) {
266 glBindBuffer(GL_COPY_READ_BUFFER
,
267 GetBufferId(bound_copy_read_buffer
.get()));
268 glBindBuffer(GL_COPY_WRITE_BUFFER
,
269 GetBufferId(bound_copy_write_buffer
.get()));
270 glBindBuffer(GL_PIXEL_PACK_BUFFER
,
271 GetBufferId(bound_pixel_pack_buffer
.get()));
272 glBindBuffer(GL_PIXEL_UNPACK_BUFFER
,
273 GetBufferId(bound_pixel_unpack_buffer
.get()));
274 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
,
275 GetBufferId(bound_transform_feedback_buffer
.get()));
276 glBindBuffer(GL_UNIFORM_BUFFER
, GetBufferId(bound_uniform_buffer
.get()));
280 void ContextState::RestoreRenderbufferBindings() {
281 // Require Renderbuffer rebind.
282 bound_renderbuffer_valid
= false;
285 void ContextState::RestoreProgramBindings() const {
286 glUseProgram(current_program
.get() ? current_program
->service_id() : 0);
289 void ContextState::RestoreActiveTexture() const {
290 glActiveTexture(GL_TEXTURE0
+ active_texture_unit
);
293 void ContextState::RestoreAllTextureUnitBindings(
294 const ContextState
* prev_state
) const {
295 // Restore Texture state.
296 for (size_t ii
= 0; ii
< texture_units
.size(); ++ii
) {
297 RestoreTextureUnitBindings(ii
, prev_state
);
299 RestoreActiveTexture();
302 void ContextState::RestoreActiveTextureUnitBinding(unsigned int target
) const {
303 DCHECK_LT(active_texture_unit
, texture_units
.size());
304 const TextureUnit
& texture_unit
= texture_units
[active_texture_unit
];
305 if (TargetIsSupported(feature_info_
, target
))
306 glBindTexture(target
, GetServiceId(texture_unit
, target
));
309 void ContextState::RestoreVertexAttribValues() const {
310 for (size_t attrib
= 0; attrib
< vertex_attrib_manager
->num_attribs();
312 switch (attrib_values
[attrib
].type()) {
316 attrib_values
[attrib
].GetValues(v
);
317 glVertexAttrib4fv(attrib
, v
);
323 attrib_values
[attrib
].GetValues(v
);
324 glVertexAttribI4iv(attrib
, v
);
330 attrib_values
[attrib
].GetValues(v
);
331 glVertexAttribI4uiv(attrib
, v
);
338 void ContextState::RestoreVertexAttribArrays(
339 const scoped_refptr
<VertexAttribManager
> attrib_manager
) const {
340 // This is expected to be called only for VAO with service_id 0,
341 // either to restore the default VAO or a virtual VAO with service_id 0.
342 GLuint vao_service_id
= attrib_manager
->service_id();
343 DCHECK(vao_service_id
== 0);
345 // Bind VAO if supported.
346 if (feature_info_
->feature_flags().native_vertex_array_object
)
347 glBindVertexArrayOES(vao_service_id
);
349 // Restore vertex attrib arrays.
350 for (size_t attrib_index
= 0; attrib_index
< attrib_manager
->num_attribs();
352 const VertexAttrib
* attrib
= attrib_manager
->GetVertexAttrib(attrib_index
);
354 // Restore vertex array.
355 Buffer
* buffer
= attrib
->buffer();
356 GLuint buffer_service_id
= buffer
? buffer
->service_id() : 0;
357 glBindBuffer(GL_ARRAY_BUFFER
, buffer_service_id
);
358 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
359 glVertexAttribPointer(attrib_index
,
362 attrib
->normalized(),
366 // Restore attrib divisor if supported.
367 if (feature_info_
->feature_flags().angle_instanced_arrays
)
368 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
370 // Never touch vertex attribute 0's state (in particular, never
371 // disable it) when running on desktop GL because it will never be
373 if (attrib_index
!= 0 ||
374 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
375 if (attrib
->enabled()) {
376 glEnableVertexAttribArray(attrib_index
);
378 glDisableVertexAttribArray(attrib_index
);
384 void ContextState::RestoreVertexAttribs() const {
385 // Restore Vertex Attrib Arrays
386 // TODO: This if should not be needed. RestoreState is getting called
387 // before GLES2Decoder::Initialize which is a bug.
388 if (vertex_attrib_manager
.get()) {
390 if (feature_info_
->feature_flags().native_vertex_array_object
) {
391 // If default VAO is still using shared id 0 instead of unique ids
392 // per-context, default VAO state must be restored.
393 GLuint default_vao_service_id
=
394 default_vertex_attrib_manager
->service_id();
395 if (default_vao_service_id
== 0)
396 RestoreVertexAttribArrays(default_vertex_attrib_manager
);
398 // Restore the current VAO binding, unless it's the same as the
400 GLuint curr_vao_service_id
= vertex_attrib_manager
->service_id();
401 if (curr_vao_service_id
!= 0)
402 glBindVertexArrayOES(curr_vao_service_id
);
404 // If native VAO isn't supported, emulated VAOs are used.
405 // Restore to the currently bound VAO.
406 RestoreVertexAttribArrays(vertex_attrib_manager
);
410 // glVertexAttrib4fv aren't part of VAO state and must be restored.
411 RestoreVertexAttribValues();
414 void ContextState::RestoreGlobalState(const ContextState
* prev_state
) const {
415 InitCapabilities(prev_state
);
416 InitState(prev_state
);
419 void ContextState::RestoreState(const ContextState
* prev_state
) {
420 RestoreAllTextureUnitBindings(prev_state
);
421 RestoreVertexAttribs();
422 RestoreBufferBindings();
423 RestoreRenderbufferBindings();
424 RestoreProgramBindings();
425 RestoreGlobalState(prev_state
);
428 ErrorState
* ContextState::GetErrorState() {
429 return error_state_
.get();
432 void ContextState::EnableDisable(GLenum pname
, bool enable
) const {
433 if (pname
== GL_PRIMITIVE_RESTART_FIXED_INDEX
) {
434 if (feature_info_
->feature_flags().emulate_primitive_restart_fixed_index
)
435 pname
= GL_PRIMITIVE_RESTART
;
444 void ContextState::SetBoundBuffer(GLenum target
, Buffer
* buffer
) {
446 case GL_ARRAY_BUFFER
:
447 bound_array_buffer
= buffer
;
449 case GL_ELEMENT_ARRAY_BUFFER
:
450 vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
452 case GL_COPY_READ_BUFFER
:
453 bound_copy_read_buffer
= buffer
;
455 case GL_COPY_WRITE_BUFFER
:
456 bound_copy_write_buffer
= buffer
;
458 case GL_PIXEL_PACK_BUFFER
:
459 bound_pixel_pack_buffer
= buffer
;
461 case GL_PIXEL_UNPACK_BUFFER
:
462 bound_pixel_unpack_buffer
= buffer
;
464 case GL_TRANSFORM_FEEDBACK_BUFFER
:
465 bound_transform_feedback_buffer
= buffer
;
467 case GL_UNIFORM_BUFFER
:
468 bound_uniform_buffer
= buffer
;
476 void ContextState::RemoveBoundBuffer(Buffer
* buffer
) {
478 vertex_attrib_manager
->Unbind(buffer
);
479 if (bound_array_buffer
.get() == buffer
) {
480 bound_array_buffer
= nullptr;
482 if (bound_copy_read_buffer
.get() == buffer
) {
483 bound_copy_read_buffer
= nullptr;
485 if (bound_copy_write_buffer
.get() == buffer
) {
486 bound_copy_write_buffer
= nullptr;
488 if (bound_pixel_pack_buffer
.get() == buffer
) {
489 bound_pixel_pack_buffer
= nullptr;
491 if (bound_pixel_unpack_buffer
.get() == buffer
) {
492 bound_pixel_unpack_buffer
= nullptr;
494 if (bound_transform_feedback_buffer
.get() == buffer
) {
495 bound_transform_feedback_buffer
= nullptr;
497 if (bound_uniform_buffer
.get() == buffer
) {
498 bound_uniform_buffer
= nullptr;
502 // Include the auto-generated part of this file. We split this because it means
503 // we can easily edit the non-auto generated parts right here in this file
504 // instead of having to edit some template or the code generator.
505 #include "gpu/command_buffer/service/context_state_impl_autogen.h"