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.
4
5 #include "gpu/command_buffer/service/context_state.h"
6
7 #include <stddef.h>
8
9 #include <cmath>
10
11 #include "base/numerics/ranges.h"
12 #include "base/optional.h"
13 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
14 #include "gpu/command_buffer/service/buffer_manager.h"
15 #include "gpu/command_buffer/service/framebuffer_manager.h"
16 #include "gpu/command_buffer/service/program_manager.h"
17 #include "gpu/command_buffer/service/renderbuffer_manager.h"
18 #include "gpu/command_buffer/service/transform_feedback_manager.h"
19 #include "ui/gl/gl_bindings.h"
20 #include "ui/gl/gl_implementation.h"
21 #include "ui/gl/gl_version_info.h"
22
23 namespace gpu {
24 namespace gles2 {
25
26 namespace {
27
Get2dServiceId(const TextureUnit & unit)28 GLuint Get2dServiceId(const TextureUnit& unit) {
29 return unit.bound_texture_2d.get() ? unit.bound_texture_2d->service_id() : 0;
30 }
31
Get2dArrayServiceId(const TextureUnit & unit)32 GLuint Get2dArrayServiceId(const TextureUnit& unit) {
33 return unit.bound_texture_2d_array.get()
34 ? unit.bound_texture_2d_array->service_id()
35 : 0;
36 }
37
Get3dServiceId(const TextureUnit & unit)38 GLuint Get3dServiceId(const TextureUnit& unit) {
39 return unit.bound_texture_3d.get() ? unit.bound_texture_3d->service_id() : 0;
40 }
41
GetCubeServiceId(const TextureUnit & unit)42 GLuint GetCubeServiceId(const TextureUnit& unit) {
43 return unit.bound_texture_cube_map.get()
44 ? unit.bound_texture_cube_map->service_id()
45 : 0;
46 }
47
GetOesServiceId(const TextureUnit & unit)48 GLuint GetOesServiceId(const TextureUnit& unit) {
49 return unit.bound_texture_external_oes.get()
50 ? unit.bound_texture_external_oes->service_id()
51 : 0;
52 }
53
GetArbServiceId(const TextureUnit & unit)54 GLuint GetArbServiceId(const TextureUnit& unit) {
55 return unit.bound_texture_rectangle_arb.get()
56 ? unit.bound_texture_rectangle_arb->service_id()
57 : 0;
58 }
59
GetServiceId(const TextureUnit & unit,GLuint target)60 GLuint GetServiceId(const TextureUnit& unit, GLuint target) {
61 switch (target) {
62 case GL_TEXTURE_2D:
63 return Get2dServiceId(unit);
64 case GL_TEXTURE_CUBE_MAP:
65 return GetCubeServiceId(unit);
66 case GL_TEXTURE_RECTANGLE_ARB:
67 return GetArbServiceId(unit);
68 case GL_TEXTURE_EXTERNAL_OES:
69 return GetOesServiceId(unit);
70 default:
71 NOTREACHED();
72 return 0;
73 }
74 }
75
TargetIsSupported(const FeatureInfo * feature_info,GLuint target)76 bool TargetIsSupported(const FeatureInfo* feature_info, GLuint target) {
77 switch (target) {
78 case GL_TEXTURE_2D:
79 return true;
80 case GL_TEXTURE_CUBE_MAP:
81 return true;
82 case GL_TEXTURE_RECTANGLE_ARB:
83 return feature_info->feature_flags().arb_texture_rectangle;
84 case GL_TEXTURE_EXTERNAL_OES:
85 return feature_info->feature_flags().oes_egl_image_external ||
86 feature_info->feature_flags().nv_egl_stream_consumer_external;
87 default:
88 NOTREACHED();
89 return false;
90 }
91 }
92
GetBufferId(const Buffer * buffer)93 GLuint GetBufferId(const Buffer* buffer) {
94 if (buffer)
95 return buffer->service_id();
96 return 0;
97 }
98
99 } // anonymous namespace.
100
TextureUnit()101 TextureUnit::TextureUnit() : bind_target(GL_TEXTURE_2D) {}
102
103 TextureUnit::TextureUnit(const TextureUnit& other) = default;
104
105 TextureUnit::~TextureUnit() = default;
106
Equal(const Vec4 & other) const107 bool Vec4::Equal(const Vec4& other) const {
108 if (type_ != other.type_)
109 return false;
110 switch (type_) {
111 case SHADER_VARIABLE_FLOAT:
112 for (size_t ii = 0; ii < 4; ++ii) {
113 if (v_[ii].float_value != other.v_[ii].float_value)
114 return false;
115 }
116 break;
117 case SHADER_VARIABLE_INT:
118 for (size_t ii = 0; ii < 4; ++ii) {
119 if (v_[ii].int_value != other.v_[ii].int_value)
120 return false;
121 }
122 break;
123 case SHADER_VARIABLE_UINT:
124 for (size_t ii = 0; ii < 4; ++ii) {
125 if (v_[ii].uint_value != other.v_[ii].uint_value)
126 return false;
127 }
128 break;
129 default:
130 NOTREACHED();
131 break;
132 }
133 return true;
134 }
135
136 template <>
GetValues(GLfloat * values) const137 void Vec4::GetValues<GLfloat>(GLfloat* values) const {
138 DCHECK(values);
139 switch (type_) {
140 case SHADER_VARIABLE_FLOAT:
141 for (size_t ii = 0; ii < 4; ++ii)
142 values[ii] = v_[ii].float_value;
143 break;
144 case SHADER_VARIABLE_INT:
145 for (size_t ii = 0; ii < 4; ++ii)
146 values[ii] = static_cast<GLfloat>(v_[ii].int_value);
147 break;
148 case SHADER_VARIABLE_UINT:
149 for (size_t ii = 0; ii < 4; ++ii)
150 values[ii] = static_cast<GLfloat>(v_[ii].uint_value);
151 break;
152 default:
153 NOTREACHED();
154 break;
155 }
156 }
157
158 template <>
GetValues(GLint * values) const159 void Vec4::GetValues<GLint>(GLint* values) const {
160 DCHECK(values);
161 switch (type_) {
162 case SHADER_VARIABLE_FLOAT:
163 for (size_t ii = 0; ii < 4; ++ii)
164 values[ii] = static_cast<GLint>(v_[ii].float_value);
165 break;
166 case SHADER_VARIABLE_INT:
167 for (size_t ii = 0; ii < 4; ++ii)
168 values[ii] = v_[ii].int_value;
169 break;
170 case SHADER_VARIABLE_UINT:
171 for (size_t ii = 0; ii < 4; ++ii)
172 values[ii] = static_cast<GLint>(v_[ii].uint_value);
173 break;
174 default:
175 NOTREACHED();
176 break;
177 }
178 }
179
180 template <>
GetValues(GLuint * values) const181 void Vec4::GetValues<GLuint>(GLuint* values) const {
182 DCHECK(values);
183 switch (type_) {
184 case SHADER_VARIABLE_FLOAT:
185 for (size_t ii = 0; ii < 4; ++ii)
186 values[ii] = static_cast<GLuint>(v_[ii].float_value);
187 break;
188 case SHADER_VARIABLE_INT:
189 for (size_t ii = 0; ii < 4; ++ii)
190 values[ii] = static_cast<GLuint>(v_[ii].int_value);
191 break;
192 case SHADER_VARIABLE_UINT:
193 for (size_t ii = 0; ii < 4; ++ii)
194 values[ii] = v_[ii].uint_value;
195 break;
196 default:
197 NOTREACHED();
198 break;
199 }
200 }
201
202 template <>
SetValues(const GLfloat * values)203 void Vec4::SetValues<GLfloat>(const GLfloat* values) {
204 DCHECK(values);
205 for (size_t ii = 0; ii < 4; ++ii)
206 v_[ii].float_value = values[ii];
207 type_ = SHADER_VARIABLE_FLOAT;
208 }
209
210 template <>
SetValues(const GLint * values)211 void Vec4::SetValues<GLint>(const GLint* values) {
212 DCHECK(values);
213 for (size_t ii = 0; ii < 4; ++ii)
214 v_[ii].int_value = values[ii];
215 type_ = SHADER_VARIABLE_INT;
216 }
217
218 template <>
SetValues(const GLuint * values)219 void Vec4::SetValues<GLuint>(const GLuint* values) {
220 DCHECK(values);
221 for (size_t ii = 0; ii < 4; ++ii)
222 v_[ii].uint_value = values[ii];
223 type_ = SHADER_VARIABLE_UINT;
224 }
225
ContextState(FeatureInfo * feature_info,bool track_texture_and_sampler_units)226 ContextState::ContextState(FeatureInfo* feature_info,
227 bool track_texture_and_sampler_units)
228 : track_texture_and_sampler_units(track_texture_and_sampler_units),
229 feature_info_(feature_info) {
230 Initialize();
231 }
232
233 ContextState::~ContextState() = default;
234
SetLineWidthBounds(GLfloat min,GLfloat max)235 void ContextState::SetLineWidthBounds(GLfloat min, GLfloat max) {
236 line_width_min_ = min;
237 line_width_max_ = max;
238 }
239
RestoreTextureUnitBindings(GLuint unit,const ContextState * prev_state) const240 void ContextState::RestoreTextureUnitBindings(
241 GLuint unit,
242 const ContextState* prev_state) const {
243 DCHECK(unit < texture_units.size() ||
244 (unit == 0 && !track_texture_and_sampler_units));
245
246 GLuint service_id_2d = 0u;
247 GLuint service_id_2d_array = 0u;
248 GLuint service_id_3d = 0u;
249 GLuint service_id_cube = 0u;
250 GLuint service_id_oes = 0u;
251 GLuint service_id_arb = 0u;
252
253 if (track_texture_and_sampler_units) {
254 const TextureUnit& texture_unit = texture_units[unit];
255 service_id_2d = Get2dServiceId(texture_unit);
256 service_id_2d_array = Get2dArrayServiceId(texture_unit);
257 service_id_3d = Get3dServiceId(texture_unit);
258 service_id_cube = GetCubeServiceId(texture_unit);
259 service_id_oes = GetOesServiceId(texture_unit);
260 service_id_arb = GetArbServiceId(texture_unit);
261 }
262
263 bool bind_texture_2d = true;
264 bool bind_texture_cube = true;
265 bool bind_texture_oes =
266 feature_info_->feature_flags().oes_egl_image_external ||
267 feature_info_->feature_flags().nv_egl_stream_consumer_external;
268 bool bind_texture_arb = feature_info_->feature_flags().arb_texture_rectangle;
269 // TEXTURE_2D_ARRAY and TEXTURE_3D are only applicable from ES3 version.
270 // So set it to FALSE by default.
271 bool bind_texture_2d_array = false;
272 bool bind_texture_3d = false;
273 // set the variables to true only if the application is ES3 or newer
274 if (feature_info_->IsES3Capable()) {
275 bind_texture_2d_array = true;
276 bind_texture_3d = true;
277 }
278
279 if (prev_state) {
280 if (prev_state->track_texture_and_sampler_units) {
281 const TextureUnit& prev_unit = prev_state->texture_units[unit];
282 bind_texture_2d = service_id_2d != Get2dServiceId(prev_unit);
283 bind_texture_2d_array =
284 bind_texture_2d_array &&
285 service_id_2d_array != Get2dArrayServiceId(prev_unit);
286 bind_texture_3d =
287 bind_texture_3d && service_id_3d != Get3dServiceId(prev_unit);
288 bind_texture_cube = service_id_cube != GetCubeServiceId(prev_unit);
289 bind_texture_oes =
290 bind_texture_oes && service_id_oes != GetOesServiceId(prev_unit);
291 bind_texture_arb =
292 bind_texture_arb && service_id_arb != GetArbServiceId(prev_unit);
293 } else if (prev_state->texture_units_in_ground_state) {
294 bind_texture_2d = service_id_2d;
295 bind_texture_2d_array = bind_texture_2d_array && service_id_2d_array;
296 bind_texture_3d = bind_texture_3d && service_id_3d;
297 bind_texture_cube = service_id_cube;
298 bind_texture_oes = bind_texture_oes && service_id_oes;
299 bind_texture_arb = bind_texture_arb && service_id_arb;
300 } else {
301 // We need bind all restore target binding, if texture units is not in
302 // ground state.
303 }
304 }
305
306 // Early-out if nothing has changed from the previous state.
307 if (!bind_texture_2d && !bind_texture_2d_array && !bind_texture_3d &&
308 !bind_texture_cube && !bind_texture_oes && !bind_texture_arb) {
309 return;
310 }
311
312 api()->glActiveTextureFn(GL_TEXTURE0 + unit);
313 if (bind_texture_2d) {
314 api()->glBindTextureFn(GL_TEXTURE_2D, service_id_2d);
315 }
316 if (bind_texture_cube) {
317 api()->glBindTextureFn(GL_TEXTURE_CUBE_MAP, service_id_cube);
318 }
319 if (bind_texture_oes) {
320 api()->glBindTextureFn(GL_TEXTURE_EXTERNAL_OES, service_id_oes);
321 }
322 if (bind_texture_arb) {
323 api()->glBindTextureFn(GL_TEXTURE_RECTANGLE_ARB, service_id_arb);
324 }
325 if (bind_texture_2d_array) {
326 api()->glBindTextureFn(GL_TEXTURE_2D_ARRAY, service_id_2d_array);
327 }
328 if (bind_texture_3d) {
329 api()->glBindTextureFn(GL_TEXTURE_3D, service_id_3d);
330 }
331 } // namespace gles2
332
RestoreSamplerBinding(GLuint unit,const ContextState * prev_state) const333 void ContextState::RestoreSamplerBinding(GLuint unit,
334 const ContextState* prev_state) const {
335 if (!feature_info_->IsES3Capable())
336 return;
337
338 GLuint cur_id = 0u;
339 if (const auto& cur_sampler = sampler_units[unit])
340 cur_id = cur_sampler->service_id();
341
342 base::Optional<GLuint> prev_id;
343 if (prev_state) {
344 const auto& prev_sampler = prev_state->sampler_units[unit];
345 prev_id.emplace(prev_sampler ? prev_sampler->service_id() : 0);
346 }
347
348 if (!prev_id || cur_id != *prev_id)
349 api()->glBindSamplerFn(unit, cur_id);
350 }
351
PushTextureUnpackState() const352 void ContextState::PushTextureUnpackState() const {
353 api()->glPixelStoreiFn(GL_UNPACK_ALIGNMENT, 1);
354
355 if (bound_pixel_unpack_buffer.get()) {
356 api()->glBindBufferFn(GL_PIXEL_UNPACK_BUFFER, 0);
357 api()->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, 0);
358 api()->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, 0);
359 DCHECK_EQ(0, unpack_skip_pixels);
360 DCHECK_EQ(0, unpack_skip_rows);
361 DCHECK_EQ(0, unpack_skip_images);
362 }
363 }
364
RestoreUnpackState() const365 void ContextState::RestoreUnpackState() const {
366 api()->glPixelStoreiFn(GL_UNPACK_ALIGNMENT, unpack_alignment);
367 if (bound_pixel_unpack_buffer.get()) {
368 api()->glBindBufferFn(GL_PIXEL_UNPACK_BUFFER,
369 GetBufferId(bound_pixel_unpack_buffer.get()));
370 api()->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, unpack_row_length);
371 api()->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, unpack_image_height);
372 }
373 }
374
DoLineWidth(GLfloat width) const375 void ContextState::DoLineWidth(GLfloat width) const {
376 api()->glLineWidthFn(
377 base::ClampToRange(width, line_width_min_, line_width_max_));
378 }
379
RestoreBufferBindings() const380 void ContextState::RestoreBufferBindings() const {
381 if (vertex_attrib_manager.get()) {
382 Buffer* element_array_buffer =
383 vertex_attrib_manager->element_array_buffer();
384 api()->glBindBufferFn(GL_ELEMENT_ARRAY_BUFFER,
385 GetBufferId(element_array_buffer));
386 }
387 api()->glBindBufferFn(GL_ARRAY_BUFFER, GetBufferId(bound_array_buffer.get()));
388 if (feature_info_->IsES3Capable()) {
389 api()->glBindBufferFn(GL_COPY_READ_BUFFER,
390 GetBufferId(bound_copy_read_buffer.get()));
391 api()->glBindBufferFn(GL_COPY_WRITE_BUFFER,
392 GetBufferId(bound_copy_write_buffer.get()));
393 api()->glBindBufferFn(GL_PIXEL_PACK_BUFFER,
394 GetBufferId(bound_pixel_pack_buffer.get()));
395 UpdatePackParameters();
396 api()->glBindBufferFn(GL_PIXEL_UNPACK_BUFFER,
397 GetBufferId(bound_pixel_unpack_buffer.get()));
398 UpdateUnpackParameters();
399 api()->glBindBufferFn(GL_TRANSFORM_FEEDBACK_BUFFER,
400 GetBufferId(bound_transform_feedback_buffer.get()));
401 api()->glBindBufferFn(GL_UNIFORM_BUFFER,
402 GetBufferId(bound_uniform_buffer.get()));
403 }
404 }
405
RestoreRenderbufferBindings()406 void ContextState::RestoreRenderbufferBindings() {
407 // Require Renderbuffer rebind.
408 bound_renderbuffer_valid = false;
409 }
410
RestoreProgramSettings(const ContextState * prev_state,bool restore_transform_feedback_bindings) const411 void ContextState::RestoreProgramSettings(
412 const ContextState* prev_state,
413 bool restore_transform_feedback_bindings) const {
414 bool flag =
415 (restore_transform_feedback_bindings && feature_info_->IsES3Capable());
416 if (flag && prev_state) {
417 if (prev_state->bound_transform_feedback.get() &&
418 prev_state->bound_transform_feedback->active() &&
419 !prev_state->bound_transform_feedback->paused()) {
420 api()->glPauseTransformFeedbackFn();
421 }
422 }
423 api()->glUseProgramFn(current_program.get() ? current_program->service_id()
424 : 0);
425 if (flag) {
426 if (bound_transform_feedback.get()) {
427 bound_transform_feedback->DoBindTransformFeedback(
428 GL_TRANSFORM_FEEDBACK, bound_transform_feedback.get(),
429 bound_transform_feedback_buffer.get());
430 } else {
431 api()->glBindTransformFeedbackFn(GL_TRANSFORM_FEEDBACK, 0);
432 }
433 }
434 }
435
RestoreIndexedUniformBufferBindings(const ContextState * prev_state)436 void ContextState::RestoreIndexedUniformBufferBindings(
437 const ContextState* prev_state) {
438 if (!feature_info_->IsES3Capable())
439 return;
440 indexed_uniform_buffer_bindings->RestoreBindings(
441 prev_state ? prev_state->indexed_uniform_buffer_bindings.get() : nullptr);
442 }
443
RestoreActiveTexture() const444 void ContextState::RestoreActiveTexture() const {
445 api()->glActiveTextureFn(GL_TEXTURE0 + active_texture_unit);
446 }
447
RestoreAllTextureUnitAndSamplerBindings(const ContextState * prev_state) const448 void ContextState::RestoreAllTextureUnitAndSamplerBindings(
449 const ContextState* prev_state) const {
450 if (!track_texture_and_sampler_units) {
451 if (prev_state) {
452 if (!prev_state->track_texture_and_sampler_units) {
453 texture_units_in_ground_state =
454 prev_state->texture_units_in_ground_state;
455 return;
456 }
457
458 texture_units_in_ground_state = true;
459 for (size_t i = 1; i < prev_state->texture_units.size(); ++i) {
460 if (prev_state->texture_units[i].AnyTargetBound()) {
461 texture_units_in_ground_state = false;
462 break;
463 }
464 }
465
466 // Make sure all texture units are in ground state, we need to reset the
467 // 0th texture units. If some of non zero textures aren't in ground state,
468 // when another context is being make current, we will restore all texture
469 // units, then it is not necessary to reset the 0th texture units anymore.
470 if (texture_units_in_ground_state)
471 RestoreTextureUnitBindings(0, prev_state);
472 } else {
473 texture_units_in_ground_state = false;
474 }
475
476 // GrContext is not aware of sampler objects and skia will not restore them,
477 // so we need to reset them to ground state.
478 // TODO(penghuang): Remove it when GrContext is created for ES 3.0.
479 for (size_t i = 0; i < sampler_units.size(); ++i)
480 RestoreSamplerBinding(i, prev_state);
481 } else {
482 // Restore Texture state.
483 for (size_t i = 0; i < texture_units.size(); ++i) {
484 RestoreTextureUnitBindings(i, prev_state);
485 RestoreSamplerBinding(i, prev_state);
486 }
487 RestoreActiveTexture();
488 }
489 }
490
RestoreActiveTextureUnitBinding(unsigned int target) const491 void ContextState::RestoreActiveTextureUnitBinding(unsigned int target) const {
492 DCHECK(active_texture_unit < texture_units.size() ||
493 (active_texture_unit == 0 && !track_texture_and_sampler_units));
494 GLuint service_id = 0;
495 if (track_texture_and_sampler_units) {
496 const TextureUnit& texture_unit = texture_units[active_texture_unit];
497 service_id = GetServiceId(texture_unit, target);
498 }
499 if (TargetIsSupported(feature_info_, target))
500 api()->glBindTextureFn(target, service_id);
501 }
502
RestoreVertexAttribValues() const503 void ContextState::RestoreVertexAttribValues() const {
504 for (size_t attrib = 0; attrib < vertex_attrib_manager->num_attribs();
505 ++attrib) {
506 switch (attrib_values[attrib].type()) {
507 case SHADER_VARIABLE_FLOAT: {
508 GLfloat v[4];
509 attrib_values[attrib].GetValues(v);
510 api()->glVertexAttrib4fvFn(attrib, v);
511 } break;
512 case SHADER_VARIABLE_INT: {
513 GLint v[4];
514 attrib_values[attrib].GetValues(v);
515 api()->glVertexAttribI4ivFn(attrib, v);
516 } break;
517 case SHADER_VARIABLE_UINT: {
518 GLuint v[4];
519 attrib_values[attrib].GetValues(v);
520 api()->glVertexAttribI4uivFn(attrib, v);
521 } break;
522 default:
523 NOTREACHED();
524 break;
525 }
526 }
527 }
528
RestoreVertexAttribArrays(const scoped_refptr<VertexAttribManager> attrib_manager) const529 void ContextState::RestoreVertexAttribArrays(
530 const scoped_refptr<VertexAttribManager> attrib_manager) const {
531 // This is expected to be called only for VAO with service_id 0,
532 // either to restore the default VAO or a virtual VAO with service_id 0.
533 GLuint vao_service_id = attrib_manager->service_id();
534 DCHECK(vao_service_id == 0);
535
536 // Bind VAO if supported.
537 if (feature_info_->feature_flags().native_vertex_array_object)
538 api()->glBindVertexArrayOESFn(vao_service_id);
539
540 // Restore vertex attrib arrays.
541 for (size_t attrib_index = 0; attrib_index < attrib_manager->num_attribs();
542 ++attrib_index) {
543 const VertexAttrib* attrib = attrib_manager->GetVertexAttrib(attrib_index);
544
545 // Restore vertex array.
546 Buffer* buffer = attrib->buffer();
547 GLuint buffer_service_id = buffer ? buffer->service_id() : 0;
548 api()->glBindBufferFn(GL_ARRAY_BUFFER, buffer_service_id);
549 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
550 api()->glVertexAttribPointerFn(attrib_index, attrib->size(), attrib->type(),
551 attrib->normalized(), attrib->gl_stride(),
552 ptr);
553
554 // Restore attrib divisor if supported.
555 if (feature_info_->feature_flags().angle_instanced_arrays)
556 api()->glVertexAttribDivisorANGLEFn(attrib_index, attrib->divisor());
557
558 if (attrib->enabled_in_driver()) {
559 api()->glEnableVertexAttribArrayFn(attrib_index);
560 } else {
561 api()->glDisableVertexAttribArrayFn(attrib_index);
562 }
563 }
564 }
565
RestoreVertexAttribs(const ContextState * prev_state) const566 void ContextState::RestoreVertexAttribs(const ContextState* prev_state) const {
567 // Restore Vertex Attrib Arrays
568 DCHECK(vertex_attrib_manager.get());
569 // Restore VAOs.
570 if (feature_info_->feature_flags().native_vertex_array_object) {
571 // If default VAO is still using shared id 0 instead of unique ids
572 // per-context, default VAO state must be restored.
573 GLuint default_vao_service_id = default_vertex_attrib_manager->service_id();
574 if (default_vao_service_id == 0)
575 RestoreVertexAttribArrays(default_vertex_attrib_manager);
576
577 // Restore the current VAO binding, unless it's the same as the
578 // default above.
579 GLuint curr_vao_service_id = vertex_attrib_manager->service_id();
580 if (curr_vao_service_id != 0)
581 api()->glBindVertexArrayOESFn(curr_vao_service_id);
582 } else {
583 if (prev_state &&
584 prev_state->feature_info_->feature_flags().native_vertex_array_object &&
585 feature_info_->workarounds()
586 .use_client_side_arrays_for_stream_buffers) {
587 // In order to use client side arrays, the driver's default VAO has to be
588 // bound.
589 api()->glBindVertexArrayOESFn(0);
590 }
591 // If native VAO isn't supported, emulated VAOs are used.
592 // Restore to the currently bound VAO.
593 RestoreVertexAttribArrays(vertex_attrib_manager);
594 }
595
596 // glVertexAttrib4fv aren't part of VAO state and must be restored.
597 RestoreVertexAttribValues();
598 }
599
RestoreGlobalState(const ContextState * prev_state) const600 void ContextState::RestoreGlobalState(const ContextState* prev_state) const {
601 InitCapabilities(prev_state);
602 InitState(prev_state);
603 }
604
RestoreState(const ContextState * prev_state)605 void ContextState::RestoreState(const ContextState* prev_state) {
606 RestoreAllTextureUnitAndSamplerBindings(prev_state);
607 // For RasterDecoder, |vertex_attrib_manager| will be nullptr, and we don't
608 // need restore vertex attribs for them.
609 if (vertex_attrib_manager)
610 RestoreVertexAttribs(prev_state);
611 // RestoreIndexedUniformBufferBindings must be called before
612 // RestoreBufferBindings. This is because setting the indexed uniform buffer
613 // bindings via glBindBuffer{Base,Range} also sets the general uniform buffer
614 // bindings (glBindBuffer), but not vice versa.
615 // For RasterDecoder, |indexed_uniform_buffer_bindings| will be nullptr, and
616 // we don't need restore indexed uniform buffer for them.
617 if (indexed_uniform_buffer_bindings)
618 RestoreIndexedUniformBufferBindings(prev_state);
619 RestoreBufferBindings();
620 RestoreRenderbufferBindings();
621 RestoreProgramSettings(prev_state, true);
622 RestoreGlobalState(prev_state);
623
624 // FRAMEBUFFER_SRGB will be restored lazily at render time.
625 framebuffer_srgb_valid_ = false;
626 }
627
EnableDisable(GLenum pname,bool enable) const628 void ContextState::EnableDisable(GLenum pname, bool enable) const {
629 if (pname == GL_PRIMITIVE_RESTART_FIXED_INDEX &&
630 feature_info_->feature_flags().emulate_primitive_restart_fixed_index) {
631 // GLES2DecoderImpl::DoDrawElements can handle this situation
632 return;
633 }
634 if (enable) {
635 api()->glEnableFn(pname);
636 } else {
637 api()->glDisableFn(pname);
638 }
639 }
640
UpdatePackParameters() const641 void ContextState::UpdatePackParameters() const {
642 if (!feature_info_->IsES3Capable())
643 return;
644 if (bound_pixel_pack_buffer.get()) {
645 api()->glPixelStoreiFn(GL_PACK_ROW_LENGTH, pack_row_length);
646 } else {
647 api()->glPixelStoreiFn(GL_PACK_ROW_LENGTH, 0);
648 }
649 }
650
SetMaxWindowRectangles(size_t max)651 void ContextState::SetMaxWindowRectangles(size_t max) {
652 window_rectangles_ = std::vector<GLint>(max * 4, 0);
653 }
654
GetMaxWindowRectangles() const655 size_t ContextState::GetMaxWindowRectangles() const {
656 size_t size = window_rectangles_.size();
657 DCHECK_EQ(0ull, size % 4);
658 return size / 4;
659 }
660
SetWindowRectangles(GLenum mode,size_t count,const volatile GLint * box)661 void ContextState::SetWindowRectangles(GLenum mode,
662 size_t count,
663 const volatile GLint* box) {
664 window_rectangles_mode = mode;
665 num_window_rectangles = count;
666 DCHECK_LE(count, GetMaxWindowRectangles());
667 if (count) {
668 std::copy(box, &box[count * 4], window_rectangles_.begin());
669 }
670 }
671
UpdateWindowRectangles() const672 void ContextState::UpdateWindowRectangles() const {
673 if (!feature_info_->feature_flags().ext_window_rectangles) {
674 return;
675 }
676
677 if (current_draw_framebuffer_client_id == 0) {
678 // Window rectangles must not take effect for client_id 0 (backbuffer).
679 api()->glWindowRectanglesEXTFn(GL_EXCLUSIVE_EXT, 0, nullptr);
680 } else {
681 DCHECK_LE(static_cast<size_t>(num_window_rectangles),
682 GetMaxWindowRectangles());
683 const GLint* data =
684 num_window_rectangles ? window_rectangles_.data() : nullptr;
685 api()->glWindowRectanglesEXTFn(window_rectangles_mode,
686 num_window_rectangles, data);
687 }
688 }
689
UpdateWindowRectanglesForBoundDrawFramebufferClientID(GLuint client_id)690 void ContextState::UpdateWindowRectanglesForBoundDrawFramebufferClientID(
691 GLuint client_id) {
692 bool old_id_nonzero = current_draw_framebuffer_client_id != 0;
693 bool new_id_nonzero = client_id != 0;
694 current_draw_framebuffer_client_id = client_id;
695 // If switching from FBO to backbuffer, or vice versa, update driver state.
696 if (old_id_nonzero ^ new_id_nonzero) {
697 UpdateWindowRectangles();
698 }
699 }
700
UpdateUnpackParameters() const701 void ContextState::UpdateUnpackParameters() const {
702 if (!feature_info_->IsES3Capable())
703 return;
704 if (bound_pixel_unpack_buffer.get()) {
705 api()->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, unpack_row_length);
706 api()->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, unpack_image_height);
707 } else {
708 api()->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, 0);
709 api()->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, 0);
710 }
711 }
712
SetBoundBuffer(GLenum target,Buffer * buffer)713 void ContextState::SetBoundBuffer(GLenum target, Buffer* buffer) {
714 bool do_refcounting = feature_info_->IsWebGL2OrES3Context();
715 switch (target) {
716 case GL_ARRAY_BUFFER:
717 if (do_refcounting && bound_array_buffer)
718 bound_array_buffer->OnUnbind(target, false);
719 bound_array_buffer = buffer;
720 if (do_refcounting && buffer)
721 buffer->OnBind(target, false);
722 break;
723 case GL_ELEMENT_ARRAY_BUFFER:
724 vertex_attrib_manager->SetElementArrayBuffer(buffer);
725 break;
726 case GL_COPY_READ_BUFFER:
727 if (do_refcounting && bound_copy_read_buffer)
728 bound_copy_read_buffer->OnUnbind(target, false);
729 bound_copy_read_buffer = buffer;
730 if (do_refcounting && buffer)
731 buffer->OnBind(target, false);
732 break;
733 case GL_COPY_WRITE_BUFFER:
734 if (do_refcounting && bound_copy_write_buffer)
735 bound_copy_write_buffer->OnUnbind(target, false);
736 bound_copy_write_buffer = buffer;
737 if (do_refcounting && buffer)
738 buffer->OnBind(target, false);
739 break;
740 case GL_PIXEL_PACK_BUFFER:
741 if (do_refcounting && bound_pixel_pack_buffer)
742 bound_pixel_pack_buffer->OnUnbind(target, false);
743 bound_pixel_pack_buffer = buffer;
744 if (do_refcounting && buffer)
745 buffer->OnBind(target, false);
746 UpdatePackParameters();
747 break;
748 case GL_PIXEL_UNPACK_BUFFER:
749 if (do_refcounting && bound_pixel_unpack_buffer)
750 bound_pixel_unpack_buffer->OnUnbind(target, false);
751 bound_pixel_unpack_buffer = buffer;
752 if (do_refcounting && buffer)
753 buffer->OnBind(target, false);
754 UpdateUnpackParameters();
755 break;
756 case GL_TRANSFORM_FEEDBACK_BUFFER:
757 if (do_refcounting && bound_transform_feedback_buffer)
758 bound_transform_feedback_buffer->OnUnbind(target, false);
759 bound_transform_feedback_buffer = buffer;
760 if (do_refcounting && buffer)
761 buffer->OnBind(target, false);
762 break;
763 case GL_UNIFORM_BUFFER:
764 if (do_refcounting && bound_uniform_buffer)
765 bound_uniform_buffer->OnUnbind(target, false);
766 bound_uniform_buffer = buffer;
767 if (do_refcounting && buffer)
768 buffer->OnBind(target, false);
769 break;
770 default:
771 NOTREACHED();
772 break;
773 }
774 }
775
RemoveBoundBuffer(Buffer * buffer)776 void ContextState::RemoveBoundBuffer(Buffer* buffer) {
777 DCHECK(buffer);
778 bool do_refcounting = feature_info_->IsWebGL2OrES3Context();
779 if (bound_array_buffer.get() == buffer) {
780 bound_array_buffer = nullptr;
781 if (do_refcounting)
782 buffer->OnUnbind(GL_ARRAY_BUFFER, false);
783 if (!context_lost_)
784 api()->glBindBufferFn(GL_ARRAY_BUFFER, 0);
785 }
786 // Needs to be called after bound_array_buffer handled.
787 vertex_attrib_manager->Unbind(buffer, bound_array_buffer.get());
788 if (bound_copy_read_buffer.get() == buffer) {
789 bound_copy_read_buffer = nullptr;
790 if (do_refcounting)
791 buffer->OnUnbind(GL_COPY_READ_BUFFER, false);
792 if (!context_lost_)
793 api()->glBindBufferFn(GL_COPY_READ_BUFFER, 0);
794 }
795 if (bound_copy_write_buffer.get() == buffer) {
796 bound_copy_write_buffer = nullptr;
797 if (do_refcounting)
798 buffer->OnUnbind(GL_COPY_WRITE_BUFFER, false);
799 if (!context_lost_)
800 api()->glBindBufferFn(GL_COPY_WRITE_BUFFER, 0);
801 }
802 if (bound_pixel_pack_buffer.get() == buffer) {
803 bound_pixel_pack_buffer = nullptr;
804 if (do_refcounting)
805 buffer->OnUnbind(GL_PIXEL_PACK_BUFFER, false);
806 if (!context_lost_)
807 api()->glBindBufferFn(GL_PIXEL_PACK_BUFFER, 0);
808 UpdatePackParameters();
809 }
810 if (bound_pixel_unpack_buffer.get() == buffer) {
811 bound_pixel_unpack_buffer = nullptr;
812 if (do_refcounting)
813 buffer->OnUnbind(GL_PIXEL_UNPACK_BUFFER, false);
814 if (!context_lost_)
815 api()->glBindBufferFn(GL_PIXEL_UNPACK_BUFFER, 0);
816 UpdateUnpackParameters();
817 }
818 if (bound_transform_feedback_buffer.get() == buffer) {
819 bound_transform_feedback_buffer = nullptr;
820 if (do_refcounting)
821 buffer->OnUnbind(GL_TRANSFORM_FEEDBACK_BUFFER, false);
822 if (!context_lost_)
823 api()->glBindBufferFn(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
824 }
825 // Needs to be called after bound_transform_feedback_buffer handled.
826 if (bound_transform_feedback.get()) {
827 bound_transform_feedback->RemoveBoundBuffer(
828 GL_TRANSFORM_FEEDBACK_BUFFER, buffer,
829 bound_transform_feedback_buffer.get(), !context_lost_);
830 }
831 if (bound_uniform_buffer.get() == buffer) {
832 bound_uniform_buffer = nullptr;
833 if (do_refcounting)
834 buffer->OnUnbind(GL_UNIFORM_BUFFER, false);
835 if (!context_lost_)
836 api()->glBindBufferFn(GL_UNIFORM_BUFFER, 0);
837 }
838 // Needs to be called after bound_uniform_buffer handled.
839 if (indexed_uniform_buffer_bindings) {
840 indexed_uniform_buffer_bindings->RemoveBoundBuffer(
841 GL_UNIFORM_BUFFER, buffer, bound_uniform_buffer.get(), !context_lost_);
842 }
843 }
844
UnbindTexture(TextureRef * texture)845 void ContextState::UnbindTexture(TextureRef* texture) {
846 GLuint active_unit = active_texture_unit;
847 for (size_t jj = 0; jj < texture_units.size(); ++jj) {
848 TextureUnit& unit = texture_units[jj];
849 if (unit.bound_texture_2d.get() == texture) {
850 unit.bound_texture_2d = nullptr;
851 if (active_unit != jj) {
852 api()->glActiveTextureFn(GL_TEXTURE0 + jj);
853 active_unit = jj;
854 }
855 api()->glBindTextureFn(GL_TEXTURE_2D, 0);
856 } else if (unit.bound_texture_cube_map.get() == texture) {
857 unit.bound_texture_cube_map = nullptr;
858 if (active_unit != jj) {
859 api()->glActiveTextureFn(GL_TEXTURE0 + jj);
860 active_unit = jj;
861 }
862 api()->glBindTextureFn(GL_TEXTURE_CUBE_MAP, 0);
863 } else if (unit.bound_texture_external_oes.get() == texture) {
864 unit.bound_texture_external_oes = nullptr;
865 if (active_unit != jj) {
866 api()->glActiveTextureFn(GL_TEXTURE0 + jj);
867 active_unit = jj;
868 }
869 api()->glBindTextureFn(GL_TEXTURE_EXTERNAL_OES, 0);
870 } else if (unit.bound_texture_rectangle_arb.get() == texture) {
871 unit.bound_texture_rectangle_arb = nullptr;
872 if (active_unit != jj) {
873 api()->glActiveTextureFn(GL_TEXTURE0 + jj);
874 active_unit = jj;
875 }
876 api()->glBindTextureFn(GL_TEXTURE_RECTANGLE_ARB, 0);
877 } else if (unit.bound_texture_3d.get() == texture) {
878 unit.bound_texture_3d = nullptr;
879 if (active_unit != jj) {
880 api()->glActiveTextureFn(GL_TEXTURE0 + jj);
881 active_unit = jj;
882 }
883 api()->glBindTextureFn(GL_TEXTURE_3D, 0);
884 } else if (unit.bound_texture_2d_array.get() == texture) {
885 unit.bound_texture_2d_array = nullptr;
886 if (active_unit != jj) {
887 api()->glActiveTextureFn(GL_TEXTURE0 + jj);
888 active_unit = jj;
889 }
890 api()->glBindTextureFn(GL_TEXTURE_2D_ARRAY, 0);
891 }
892 }
893
894 if (active_unit != active_texture_unit) {
895 api()->glActiveTextureFn(GL_TEXTURE0 + active_texture_unit);
896 }
897 }
898
UnbindSampler(Sampler * sampler)899 void ContextState::UnbindSampler(Sampler* sampler) {
900 for (size_t jj = 0; jj < sampler_units.size(); ++jj) {
901 if (sampler_units[jj].get() == sampler) {
902 sampler_units[jj] = nullptr;
903 api()->glBindSamplerFn(jj, 0);
904 }
905 }
906 }
907
GetPackParams()908 PixelStoreParams ContextState::GetPackParams() {
909 DCHECK_EQ(0, pack_skip_pixels);
910 DCHECK_EQ(0, pack_skip_rows);
911 PixelStoreParams params;
912 params.alignment = pack_alignment;
913 params.row_length = pack_row_length;
914 return params;
915 }
916
GetUnpackParams(Dimension dimension)917 PixelStoreParams ContextState::GetUnpackParams(Dimension dimension) {
918 DCHECK_EQ(0, unpack_skip_pixels);
919 DCHECK_EQ(0, unpack_skip_rows);
920 DCHECK_EQ(0, unpack_skip_images);
921 PixelStoreParams params;
922 params.alignment = unpack_alignment;
923 params.row_length = unpack_row_length;
924 if (dimension == k3D) {
925 params.image_height = unpack_image_height;
926 }
927 return params;
928 }
929
EnableDisableFramebufferSRGB(bool enable)930 void ContextState::EnableDisableFramebufferSRGB(bool enable) {
931 if (framebuffer_srgb_valid_ && framebuffer_srgb_ == enable)
932 return;
933 EnableDisable(GL_FRAMEBUFFER_SRGB, enable);
934 framebuffer_srgb_ = enable;
935 framebuffer_srgb_valid_ = true;
936 }
937
InitStateManual(const ContextState *) const938 void ContextState::InitStateManual(const ContextState*) const {
939 // Here we always reset the states whether it's different from previous ones.
940 // We have very limited states here; also, once we switch to MANGLE, MANGLE
941 // will opmitize this.
942 UpdatePackParameters();
943 UpdateUnpackParameters();
944 UpdateWindowRectangles();
945 }
946
947 // Include the auto-generated part of this file. We split this because it means
948 // we can easily edit the non-auto generated parts right here in this file
949 // instead of having to edit some template or the code generator.
950 #include "gpu/command_buffer/service/context_state_impl_autogen.h"
951
952 } // namespace gles2
953 } // namespace gpu
954