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