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"
17 #include "ui/gl/gl_version_info.h"
24 GLuint
Get2dServiceId(const TextureUnit
& unit
) {
25 return unit
.bound_texture_2d
.get()
26 ? unit
.bound_texture_2d
->service_id() : 0;
29 GLuint
GetCubeServiceId(const TextureUnit
& unit
) {
30 return unit
.bound_texture_cube_map
.get()
31 ? unit
.bound_texture_cube_map
->service_id() : 0;
34 GLuint
GetOesServiceId(const TextureUnit
& unit
) {
35 return unit
.bound_texture_external_oes
.get()
36 ? unit
.bound_texture_external_oes
->service_id() : 0;
39 GLuint
GetArbServiceId(const TextureUnit
& unit
) {
40 return unit
.bound_texture_rectangle_arb
.get()
41 ? unit
.bound_texture_rectangle_arb
->service_id() : 0;
44 GLuint
GetServiceId(const TextureUnit
& unit
, GLuint target
) {
47 return Get2dServiceId(unit
);
48 case GL_TEXTURE_CUBE_MAP
:
49 return GetCubeServiceId(unit
);
50 case GL_TEXTURE_RECTANGLE_ARB
:
51 return GetArbServiceId(unit
);
52 case GL_TEXTURE_EXTERNAL_OES
:
53 return GetOesServiceId(unit
);
60 bool TargetIsSupported(const FeatureInfo
* feature_info
, GLuint target
) {
64 case GL_TEXTURE_CUBE_MAP
:
66 case GL_TEXTURE_RECTANGLE_ARB
:
67 return feature_info
->feature_flags().arb_texture_rectangle
;
68 case GL_TEXTURE_EXTERNAL_OES
:
69 return feature_info
->feature_flags().oes_egl_image_external
;
76 GLuint
GetBufferId(const Buffer
* buffer
) {
78 return buffer
->service_id();
82 } // anonymous namespace.
84 TextureUnit::TextureUnit()
85 : bind_target(GL_TEXTURE_2D
) {
88 TextureUnit::~TextureUnit() {
91 bool Vec4::Equal(const Vec4
& other
) const {
92 if (type_
!= other
.type_
)
96 for (size_t ii
= 0; ii
< 4; ++ii
) {
97 if (v_
[ii
].float_value
!= other
.v_
[ii
].float_value
)
102 for (size_t ii
= 0; ii
< 4; ++ii
) {
103 if (v_
[ii
].int_value
!= other
.v_
[ii
].int_value
)
108 for (size_t ii
= 0; ii
< 4; ++ii
) {
109 if (v_
[ii
].uint_value
!= other
.v_
[ii
].uint_value
)
118 void Vec4::GetValues
<GLfloat
>(GLfloat
* values
) const {
122 for (size_t ii
= 0; ii
< 4; ++ii
)
123 values
[ii
] = v_
[ii
].float_value
;
126 for (size_t ii
= 0; ii
< 4; ++ii
)
127 values
[ii
] = static_cast<GLfloat
>(v_
[ii
].int_value
);
130 for (size_t ii
= 0; ii
< 4; ++ii
)
131 values
[ii
] = static_cast<GLfloat
>(v_
[ii
].uint_value
);
137 void Vec4::GetValues
<GLint
>(GLint
* values
) const {
141 for (size_t ii
= 0; ii
< 4; ++ii
)
142 values
[ii
] = static_cast<GLint
>(v_
[ii
].float_value
);
145 for (size_t ii
= 0; ii
< 4; ++ii
)
146 values
[ii
] = v_
[ii
].int_value
;
149 for (size_t ii
= 0; ii
< 4; ++ii
)
150 values
[ii
] = static_cast<GLint
>(v_
[ii
].uint_value
);
156 void Vec4::GetValues
<GLuint
>(GLuint
* values
) const {
160 for (size_t ii
= 0; ii
< 4; ++ii
)
161 values
[ii
] = static_cast<GLuint
>(v_
[ii
].float_value
);
164 for (size_t ii
= 0; ii
< 4; ++ii
)
165 values
[ii
] = static_cast<GLuint
>(v_
[ii
].int_value
);
168 for (size_t ii
= 0; ii
< 4; ++ii
)
169 values
[ii
] = v_
[ii
].uint_value
;
175 void Vec4::SetValues
<GLfloat
>(const GLfloat
* values
) {
177 for (size_t ii
= 0; ii
< 4; ++ii
)
178 v_
[ii
].float_value
= values
[ii
];
183 void Vec4::SetValues
<GLint
>(const GLint
* values
) {
185 for (size_t ii
= 0; ii
< 4; ++ii
)
186 v_
[ii
].int_value
= values
[ii
];
191 void Vec4::SetValues
<GLuint
>(const GLuint
* values
) {
193 for (size_t ii
= 0; ii
< 4; ++ii
)
194 v_
[ii
].uint_value
= values
[ii
];
198 ContextState::ContextState(FeatureInfo
* feature_info
,
199 ErrorStateClient
* error_state_client
,
201 : active_texture_unit(0),
202 bound_renderbuffer_valid(false),
203 pack_reverse_row_order(false),
204 ignore_cached_state(false),
205 fbo_binding_for_scissor_workaround_dirty(false),
206 feature_info_(feature_info
),
207 error_state_(ErrorState::Create(error_state_client
, logger
)) {
211 ContextState::~ContextState() {
214 void ContextState::RestoreTextureUnitBindings(
215 GLuint unit
, const ContextState
* prev_state
) const {
216 DCHECK_LT(unit
, texture_units
.size());
217 const TextureUnit
& texture_unit
= texture_units
[unit
];
218 GLuint service_id_2d
= Get2dServiceId(texture_unit
);
219 GLuint service_id_cube
= GetCubeServiceId(texture_unit
);
220 GLuint service_id_oes
= GetOesServiceId(texture_unit
);
221 GLuint service_id_arb
= GetArbServiceId(texture_unit
);
223 bool bind_texture_2d
= true;
224 bool bind_texture_cube
= true;
225 bool bind_texture_oes
= feature_info_
->feature_flags().oes_egl_image_external
;
226 bool bind_texture_arb
= feature_info_
->feature_flags().arb_texture_rectangle
;
229 const TextureUnit
& prev_unit
= prev_state
->texture_units
[unit
];
230 bind_texture_2d
= service_id_2d
!= Get2dServiceId(prev_unit
);
231 bind_texture_cube
= service_id_cube
!= GetCubeServiceId(prev_unit
);
233 bind_texture_oes
&& service_id_oes
!= GetOesServiceId(prev_unit
);
235 bind_texture_arb
&& service_id_arb
!= GetArbServiceId(prev_unit
);
238 // Early-out if nothing has changed from the previous state.
239 if (!bind_texture_2d
&& !bind_texture_cube
240 && !bind_texture_oes
&& !bind_texture_arb
) {
244 glActiveTexture(GL_TEXTURE0
+ unit
);
245 if (bind_texture_2d
) {
246 glBindTexture(GL_TEXTURE_2D
, service_id_2d
);
248 if (bind_texture_cube
) {
249 glBindTexture(GL_TEXTURE_CUBE_MAP
, service_id_cube
);
251 if (bind_texture_oes
) {
252 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, service_id_oes
);
254 if (bind_texture_arb
) {
255 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, service_id_arb
);
259 void ContextState::RestoreBufferBindings() const {
260 if (vertex_attrib_manager
.get()) {
261 Buffer
* element_array_buffer
=
262 vertex_attrib_manager
->element_array_buffer();
263 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, GetBufferId(element_array_buffer
));
265 glBindBuffer(GL_ARRAY_BUFFER
, GetBufferId(bound_array_buffer
.get()));
266 if (feature_info_
->IsES3Capable()) {
267 glBindBuffer(GL_COPY_READ_BUFFER
,
268 GetBufferId(bound_copy_read_buffer
.get()));
269 glBindBuffer(GL_COPY_WRITE_BUFFER
,
270 GetBufferId(bound_copy_write_buffer
.get()));
271 glBindBuffer(GL_PIXEL_PACK_BUFFER
,
272 GetBufferId(bound_pixel_pack_buffer
.get()));
273 glBindBuffer(GL_PIXEL_UNPACK_BUFFER
,
274 GetBufferId(bound_pixel_unpack_buffer
.get()));
275 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
,
276 GetBufferId(bound_transform_feedback_buffer
.get()));
277 glBindBuffer(GL_UNIFORM_BUFFER
, GetBufferId(bound_uniform_buffer
.get()));
281 void ContextState::RestoreRenderbufferBindings() {
282 // Require Renderbuffer rebind.
283 bound_renderbuffer_valid
= false;
286 void ContextState::RestoreProgramBindings() const {
287 glUseProgram(current_program
.get() ? current_program
->service_id() : 0);
290 void ContextState::RestoreActiveTexture() const {
291 glActiveTexture(GL_TEXTURE0
+ active_texture_unit
);
294 void ContextState::RestoreAllTextureUnitBindings(
295 const ContextState
* prev_state
) const {
296 // Restore Texture state.
297 for (size_t ii
= 0; ii
< texture_units
.size(); ++ii
) {
298 RestoreTextureUnitBindings(ii
, prev_state
);
300 RestoreActiveTexture();
303 void ContextState::RestoreActiveTextureUnitBinding(unsigned int target
) const {
304 DCHECK_LT(active_texture_unit
, texture_units
.size());
305 const TextureUnit
& texture_unit
= texture_units
[active_texture_unit
];
306 if (TargetIsSupported(feature_info_
, target
))
307 glBindTexture(target
, GetServiceId(texture_unit
, target
));
310 void ContextState::RestoreVertexAttribValues() const {
311 for (size_t attrib
= 0; attrib
< vertex_attrib_manager
->num_attribs();
313 switch (attrib_values
[attrib
].type()) {
317 attrib_values
[attrib
].GetValues(v
);
318 glVertexAttrib4fv(attrib
, v
);
324 attrib_values
[attrib
].GetValues(v
);
325 glVertexAttribI4iv(attrib
, v
);
331 attrib_values
[attrib
].GetValues(v
);
332 glVertexAttribI4uiv(attrib
, v
);
339 void ContextState::RestoreVertexAttribArrays(
340 const scoped_refptr
<VertexAttribManager
> attrib_manager
) const {
341 // This is expected to be called only for VAO with service_id 0,
342 // either to restore the default VAO or a virtual VAO with service_id 0.
343 GLuint vao_service_id
= attrib_manager
->service_id();
344 DCHECK(vao_service_id
== 0);
346 // Bind VAO if supported.
347 if (feature_info_
->feature_flags().native_vertex_array_object
)
348 glBindVertexArrayOES(vao_service_id
);
350 // Restore vertex attrib arrays.
351 for (size_t attrib_index
= 0; attrib_index
< attrib_manager
->num_attribs();
353 const VertexAttrib
* attrib
= attrib_manager
->GetVertexAttrib(attrib_index
);
355 // Restore vertex array.
356 Buffer
* buffer
= attrib
->buffer();
357 GLuint buffer_service_id
= buffer
? buffer
->service_id() : 0;
358 glBindBuffer(GL_ARRAY_BUFFER
, buffer_service_id
);
359 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
360 glVertexAttribPointer(attrib_index
,
363 attrib
->normalized(),
367 // Restore attrib divisor if supported.
368 if (feature_info_
->feature_flags().angle_instanced_arrays
)
369 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
371 // Never touch vertex attribute 0's state (in particular, never
372 // disable it) when running on desktop GL because it will never be
374 if (attrib_index
!= 0 ||
375 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
376 if (attrib
->enabled()) {
377 glEnableVertexAttribArray(attrib_index
);
379 glDisableVertexAttribArray(attrib_index
);
385 void ContextState::RestoreVertexAttribs() const {
386 // Restore Vertex Attrib Arrays
387 // TODO: This if should not be needed. RestoreState is getting called
388 // before GLES2Decoder::Initialize which is a bug.
389 if (vertex_attrib_manager
.get()) {
391 if (feature_info_
->feature_flags().native_vertex_array_object
) {
392 // If default VAO is still using shared id 0 instead of unique ids
393 // per-context, default VAO state must be restored.
394 GLuint default_vao_service_id
=
395 default_vertex_attrib_manager
->service_id();
396 if (default_vao_service_id
== 0)
397 RestoreVertexAttribArrays(default_vertex_attrib_manager
);
399 // Restore the current VAO binding, unless it's the same as the
401 GLuint curr_vao_service_id
= vertex_attrib_manager
->service_id();
402 if (curr_vao_service_id
!= 0)
403 glBindVertexArrayOES(curr_vao_service_id
);
405 // If native VAO isn't supported, emulated VAOs are used.
406 // Restore to the currently bound VAO.
407 RestoreVertexAttribArrays(vertex_attrib_manager
);
411 // glVertexAttrib4fv aren't part of VAO state and must be restored.
412 RestoreVertexAttribValues();
415 void ContextState::RestoreGlobalState(const ContextState
* prev_state
) const {
416 InitCapabilities(prev_state
);
417 InitState(prev_state
);
420 void ContextState::RestoreState(const ContextState
* prev_state
) {
421 RestoreAllTextureUnitBindings(prev_state
);
422 RestoreVertexAttribs();
423 RestoreBufferBindings();
424 RestoreRenderbufferBindings();
425 RestoreProgramBindings();
426 RestoreGlobalState(prev_state
);
429 ErrorState
* ContextState::GetErrorState() {
430 return error_state_
.get();
433 void ContextState::EnableDisable(GLenum pname
, bool enable
) const {
434 if (pname
== GL_PRIMITIVE_RESTART_FIXED_INDEX
) {
435 if (feature_info_
->feature_flags().emulate_primitive_restart_fixed_index
)
436 pname
= GL_PRIMITIVE_RESTART
;
445 void ContextState::SetBoundBuffer(GLenum target
, Buffer
* buffer
) {
447 case GL_ARRAY_BUFFER
:
448 bound_array_buffer
= buffer
;
450 case GL_ELEMENT_ARRAY_BUFFER
:
451 vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
453 case GL_COPY_READ_BUFFER
:
454 bound_copy_read_buffer
= buffer
;
456 case GL_COPY_WRITE_BUFFER
:
457 bound_copy_write_buffer
= buffer
;
459 case GL_PIXEL_PACK_BUFFER
:
460 bound_pixel_pack_buffer
= buffer
;
462 case GL_PIXEL_UNPACK_BUFFER
:
463 bound_pixel_unpack_buffer
= buffer
;
465 case GL_TRANSFORM_FEEDBACK_BUFFER
:
466 bound_transform_feedback_buffer
= buffer
;
468 case GL_UNIFORM_BUFFER
:
469 bound_uniform_buffer
= buffer
;
477 void ContextState::RemoveBoundBuffer(Buffer
* buffer
) {
479 vertex_attrib_manager
->Unbind(buffer
);
480 if (bound_array_buffer
.get() == buffer
) {
481 bound_array_buffer
= nullptr;
483 if (bound_copy_read_buffer
.get() == buffer
) {
484 bound_copy_read_buffer
= nullptr;
486 if (bound_copy_write_buffer
.get() == buffer
) {
487 bound_copy_write_buffer
= nullptr;
489 if (bound_pixel_pack_buffer
.get() == buffer
) {
490 bound_pixel_pack_buffer
= nullptr;
492 if (bound_pixel_unpack_buffer
.get() == buffer
) {
493 bound_pixel_unpack_buffer
= nullptr;
495 if (bound_transform_feedback_buffer
.get() == buffer
) {
496 bound_transform_feedback_buffer
= nullptr;
498 if (bound_uniform_buffer
.get() == buffer
) {
499 bound_uniform_buffer
= nullptr;
503 void ContextState::UnbindTexture(TextureRef
* texture
) {
504 GLuint active_unit
= active_texture_unit
;
505 for (size_t jj
= 0; jj
< texture_units
.size(); ++jj
) {
506 TextureUnit
& unit
= texture_units
[jj
];
507 if (unit
.bound_texture_2d
.get() == texture
) {
508 unit
.bound_texture_2d
= NULL
;
509 if (active_unit
!= jj
) {
510 glActiveTexture(GL_TEXTURE0
+ jj
);
513 glBindTexture(GL_TEXTURE_2D
, 0);
514 } else if (unit
.bound_texture_cube_map
.get() == texture
) {
515 unit
.bound_texture_cube_map
= NULL
;
516 if (active_unit
!= jj
) {
517 glActiveTexture(GL_TEXTURE0
+ jj
);
520 glBindTexture(GL_TEXTURE_CUBE_MAP
, 0);
521 } else if (unit
.bound_texture_external_oes
.get() == texture
) {
522 unit
.bound_texture_external_oes
= NULL
;
523 if (active_unit
!= jj
) {
524 glActiveTexture(GL_TEXTURE0
+ jj
);
527 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, 0);
528 } else if (unit
.bound_texture_3d
.get() == texture
) {
529 unit
.bound_texture_3d
= NULL
;
530 if (active_unit
!= jj
) {
531 glActiveTexture(GL_TEXTURE0
+ jj
);
534 glBindTexture(GL_TEXTURE_3D
, 0);
535 } else if (unit
.bound_texture_2d_array
.get() == texture
) {
536 unit
.bound_texture_2d_array
= NULL
;
537 if (active_unit
!= jj
) {
538 glActiveTexture(GL_TEXTURE0
+ jj
);
541 glBindTexture(GL_TEXTURE_2D_ARRAY
, 0);
545 if (active_unit
!= active_texture_unit
) {
546 glActiveTexture(GL_TEXTURE0
+ active_texture_unit
);
550 // Include the auto-generated part of this file. We split this because it means
551 // we can easily edit the non-auto generated parts right here in this file
552 // instead of having to edit some template or the code generator.
553 #include "gpu/command_buffer/service/context_state_impl_autogen.h"