Elim cr-checkbox
[chromium-blink-merge.git] / gpu / command_buffer / service / context_state.cc
blobe8c00727cf43ce7bfdcb9647325d53bea20b3858
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 <cmath>
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"
19 namespace gpu {
20 namespace gles2 {
22 namespace {
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) {
45 switch (target) {
46 case GL_TEXTURE_2D:
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);
54 default:
55 NOTREACHED();
56 return 0;
60 bool TargetIsSupported(const FeatureInfo* feature_info, GLuint target) {
61 switch (target) {
62 case GL_TEXTURE_2D:
63 return true;
64 case GL_TEXTURE_CUBE_MAP:
65 return true;
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;
70 default:
71 NOTREACHED();
72 return false;
76 GLuint GetBufferId(const Buffer* buffer) {
77 if (buffer)
78 return buffer->service_id();
79 return 0;
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_)
93 return false;
94 switch (type_) {
95 case kFloat:
96 for (size_t ii = 0; ii < 4; ++ii) {
97 if (v_[ii].float_value != other.v_[ii].float_value)
98 return false;
100 break;
101 case kInt:
102 for (size_t ii = 0; ii < 4; ++ii) {
103 if (v_[ii].int_value != other.v_[ii].int_value)
104 return false;
106 break;
107 case kUInt:
108 for (size_t ii = 0; ii < 4; ++ii) {
109 if (v_[ii].uint_value != other.v_[ii].uint_value)
110 return false;
112 break;
114 return true;
117 template <>
118 void Vec4::GetValues<GLfloat>(GLfloat* values) const {
119 DCHECK(values);
120 switch (type_) {
121 case kFloat:
122 for (size_t ii = 0; ii < 4; ++ii)
123 values[ii] = v_[ii].float_value;
124 break;
125 case kInt:
126 for (size_t ii = 0; ii < 4; ++ii)
127 values[ii] = static_cast<GLfloat>(v_[ii].int_value);
128 break;
129 case kUInt:
130 for (size_t ii = 0; ii < 4; ++ii)
131 values[ii] = static_cast<GLfloat>(v_[ii].uint_value);
132 break;
136 template <>
137 void Vec4::GetValues<GLint>(GLint* values) const {
138 DCHECK(values);
139 switch (type_) {
140 case kFloat:
141 for (size_t ii = 0; ii < 4; ++ii)
142 values[ii] = static_cast<GLint>(v_[ii].float_value);
143 break;
144 case kInt:
145 for (size_t ii = 0; ii < 4; ++ii)
146 values[ii] = v_[ii].int_value;
147 break;
148 case kUInt:
149 for (size_t ii = 0; ii < 4; ++ii)
150 values[ii] = static_cast<GLint>(v_[ii].uint_value);
151 break;
155 template<>
156 void Vec4::GetValues<GLuint>(GLuint* values) const {
157 DCHECK(values);
158 switch (type_) {
159 case kFloat:
160 for (size_t ii = 0; ii < 4; ++ii)
161 values[ii] = static_cast<GLuint>(v_[ii].float_value);
162 break;
163 case kInt:
164 for (size_t ii = 0; ii < 4; ++ii)
165 values[ii] = static_cast<GLuint>(v_[ii].int_value);
166 break;
167 case kUInt:
168 for (size_t ii = 0; ii < 4; ++ii)
169 values[ii] = v_[ii].uint_value;
170 break;
174 template <>
175 void Vec4::SetValues<GLfloat>(const GLfloat* values) {
176 DCHECK(values);
177 for (size_t ii = 0; ii < 4; ++ii)
178 v_[ii].float_value = values[ii];
179 type_ = kFloat;
182 template <>
183 void Vec4::SetValues<GLint>(const GLint* values) {
184 DCHECK(values);
185 for (size_t ii = 0; ii < 4; ++ii)
186 v_[ii].int_value = values[ii];
187 type_ = kInt;
190 template <>
191 void Vec4::SetValues<GLuint>(const GLuint* values) {
192 DCHECK(values);
193 for (size_t ii = 0; ii < 4; ++ii)
194 v_[ii].uint_value = values[ii];
195 type_ = kUInt;
198 ContextState::ContextState(FeatureInfo* feature_info,
199 ErrorStateClient* error_state_client,
200 Logger* logger)
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)) {
208 Initialize();
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;
228 if (prev_state) {
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);
232 bind_texture_oes =
233 bind_texture_oes && service_id_oes != GetOesServiceId(prev_unit);
234 bind_texture_arb =
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) {
241 return;
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();
312 ++attrib) {
313 switch (attrib_values[attrib].type()) {
314 case Vec4::kFloat:
316 GLfloat v[4];
317 attrib_values[attrib].GetValues(v);
318 glVertexAttrib4fv(attrib, v);
320 break;
321 case Vec4::kInt:
323 GLint v[4];
324 attrib_values[attrib].GetValues(v);
325 glVertexAttribI4iv(attrib, v);
327 break;
328 case Vec4::kUInt:
330 GLuint v[4];
331 attrib_values[attrib].GetValues(v);
332 glVertexAttribI4uiv(attrib, v);
334 break;
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();
352 ++attrib_index) {
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,
361 attrib->size(),
362 attrib->type(),
363 attrib->normalized(),
364 attrib->gl_stride(),
365 ptr);
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
373 // re-enabled.
374 if (attrib_index != 0 ||
375 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
376 if (attrib->enabled()) {
377 glEnableVertexAttribArray(attrib_index);
378 } else {
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()) {
390 // Restore VAOs.
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
400 // default above.
401 GLuint curr_vao_service_id = vertex_attrib_manager->service_id();
402 if (curr_vao_service_id != 0)
403 glBindVertexArrayOES(curr_vao_service_id);
404 } else {
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;
438 if (enable) {
439 glEnable(pname);
440 } else {
441 glDisable(pname);
445 void ContextState::SetBoundBuffer(GLenum target, Buffer* buffer) {
446 switch (target) {
447 case GL_ARRAY_BUFFER:
448 bound_array_buffer = buffer;
449 break;
450 case GL_ELEMENT_ARRAY_BUFFER:
451 vertex_attrib_manager->SetElementArrayBuffer(buffer);
452 break;
453 case GL_COPY_READ_BUFFER:
454 bound_copy_read_buffer = buffer;
455 break;
456 case GL_COPY_WRITE_BUFFER:
457 bound_copy_write_buffer = buffer;
458 break;
459 case GL_PIXEL_PACK_BUFFER:
460 bound_pixel_pack_buffer = buffer;
461 break;
462 case GL_PIXEL_UNPACK_BUFFER:
463 bound_pixel_unpack_buffer = buffer;
464 break;
465 case GL_TRANSFORM_FEEDBACK_BUFFER:
466 bound_transform_feedback_buffer = buffer;
467 break;
468 case GL_UNIFORM_BUFFER:
469 bound_uniform_buffer = buffer;
470 break;
471 default:
472 NOTREACHED();
473 break;
477 void ContextState::RemoveBoundBuffer(Buffer* buffer) {
478 DCHECK(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);
511 active_unit = 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);
518 active_unit = 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);
525 active_unit = 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);
532 active_unit = 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);
539 active_unit = 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"
555 } // namespace gles2
556 } // namespace gpu