1# Copyright (c) 2018 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"""Common code generator for command buffers."""
5
6import errno
7import itertools
8import os
9import os.path
10import re
11import platform
12from subprocess import call
13
14_SIZE_OF_UINT32 = 4
15_SIZE_OF_COMMAND_HEADER = 4
16_FIRST_SPECIFIC_COMMAND_ID = 256
17
18_LICENSE = """// Copyright %s The Chromium Authors. All rights reserved.
19// Use of this source code is governed by a BSD-style license that can be
20// found in the LICENSE file.
21
22"""
23
24_DO_NOT_EDIT_WARNING = """// This file is auto-generated from
25// gpu/command_buffer/build_%s_cmd_buffer.py
26// It's formatted by clang-format using chromium coding style:
27//    clang-format -i -style=chromium filename
28// DO NOT EDIT!
29
30"""
31
32# This string is copied directly out of the gl2.h file from GLES2.0
33#
34# Edits:
35#
36# *) Any argument that is a resourceID has been changed to GLid<Type>.
37#    (not pointer arguments) and if it's allowed to be zero it's GLidZero<Type>
38#    If it's allowed to not exist it's GLidBind<Type>
39#
40# *) All GLenums have been changed to GLenumTypeOfEnum
41#
42_GL_TYPES = {
43  'GLenum': 'unsigned int',
44  'GLboolean': 'unsigned char',
45  'GLbitfield': 'unsigned int',
46  'GLbyte': 'signed char',
47  'GLshort': 'short',
48  'GLint': 'int',
49  'GLsizei': 'int',
50  'GLubyte': 'unsigned char',
51  'GLushort': 'unsigned short',
52  'GLuint': 'unsigned int',
53  'GLfloat': 'float',
54  'GLclampf': 'float',
55  'GLvoid': 'void',
56  'GLfixed': 'int',
57  'GLclampx': 'int'
58}
59
60_GL_TYPES_32 = {
61  'GLintptr': 'long int',
62  'GLsizeiptr': 'long int'
63}
64
65_GL_TYPES_64 = {
66  'GLintptr': 'long long int',
67  'GLsizeiptr': 'long long int'
68}
69
70_ETC_COMPRESSED_TEXTURE_FORMATS = [
71  'GL_COMPRESSED_R11_EAC',
72  'GL_COMPRESSED_SIGNED_R11_EAC',
73  'GL_COMPRESSED_RG11_EAC',
74  'GL_COMPRESSED_SIGNED_RG11_EAC',
75  'GL_COMPRESSED_RGB8_ETC2',
76  'GL_COMPRESSED_SRGB8_ETC2',
77  'GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2',
78  'GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2',
79  'GL_COMPRESSED_RGBA8_ETC2_EAC',
80  'GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC',
81]
82
83# This table specifies the different pepper interfaces that are supported for
84# GL commands. 'dev' is true if it's a dev interface.
85_PEPPER_INTERFACES = [
86  {'name': '', 'dev': False},
87  {'name': 'InstancedArrays', 'dev': False},
88  {'name': 'FramebufferBlit', 'dev': False},
89  {'name': 'FramebufferMultisample', 'dev': False},
90  {'name': 'ChromiumEnableFeature', 'dev': False},
91  {'name': 'ChromiumMapSub', 'dev': False},
92  {'name': 'Query', 'dev': False},
93  {'name': 'VertexArrayObject', 'dev': False},
94  {'name': 'DrawBuffers', 'dev': True},
95]
96
97
98# Capabilities selected with glEnable
99# on_change:    string of C++ code that is executed when the state is changed.
100_CAPABILITY_FLAGS = [
101  {'name': 'blend'},
102  {'name': 'cull_face'},
103  {'name': 'depth_test',
104    'on_change': 'framebuffer_state_.clear_state_dirty = true;'},
105  {'name': 'dither', 'default': True},
106  {'name': 'framebuffer_srgb_ext', 'default': True, 'no_init': True,
107   'extension_flag': 'ext_srgb_write_control'},
108  {'name': 'polygon_offset_fill'},
109  {'name': 'sample_alpha_to_coverage'},
110  {'name': 'sample_coverage'},
111  {'name': 'scissor_test'},
112  {'name': 'stencil_test',
113    'on_change': '''state_.stencil_state_changed_since_validation = true;
114                    framebuffer_state_.clear_state_dirty = true;'''},
115  {'name': 'rasterizer_discard', 'es3': True},
116  {'name': 'primitive_restart_fixed_index', 'es3': True},
117  {'name': 'multisample_ext', 'default': True,
118   'extension_flag': 'ext_multisample_compatibility'},
119  {'name': 'sample_alpha_to_one_ext',
120   'extension_flag': 'ext_multisample_compatibility'},
121]
122
123_STATE_INFO = {
124  'ClearColor': {
125    'type': 'Normal',
126    'func': 'ClearColor',
127    'enum': 'GL_COLOR_CLEAR_VALUE',
128    'states': [
129      {'name': 'color_clear_red', 'type': 'GLfloat', 'default': '0.0f'},
130      {'name': 'color_clear_green', 'type': 'GLfloat', 'default': '0.0f'},
131      {'name': 'color_clear_blue', 'type': 'GLfloat', 'default': '0.0f'},
132      {'name': 'color_clear_alpha', 'type': 'GLfloat', 'default': '0.0f'},
133    ],
134  },
135  'ClearDepthf': {
136    'type': 'Normal',
137    'func': 'ClearDepth',
138    'enum': 'GL_DEPTH_CLEAR_VALUE',
139    'states': [
140      {'name': 'depth_clear', 'type': 'GLclampf', 'default': '1.0f'},
141    ],
142  },
143  'ColorMask': {
144    'type': 'Normal',
145    'func': 'ColorMask',
146    'enum': 'GL_COLOR_WRITEMASK',
147    'states': [
148      {
149        'name': 'color_mask_red',
150        'type': 'GLboolean',
151        'default': 'true',
152        'cached': True
153      },
154      {
155        'name': 'color_mask_green',
156        'type': 'GLboolean',
157        'default': 'true',
158        'cached': True
159      },
160      {
161        'name': 'color_mask_blue',
162        'type': 'GLboolean',
163        'default': 'true',
164        'cached': True
165      },
166      {
167        'name': 'color_mask_alpha',
168        'type': 'GLboolean',
169        'default': 'true',
170        'cached': True
171      },
172    ],
173    'on_change': 'framebuffer_state_.clear_state_dirty = true;',
174  },
175  'ClearStencil': {
176    'type': 'Normal',
177    'func': 'ClearStencil',
178    'enum': 'GL_STENCIL_CLEAR_VALUE',
179    'states': [
180      {'name': 'stencil_clear', 'type': 'GLint', 'default': '0'},
181    ],
182  },
183  'CoverageModulationCHROMIUM': {
184    'type': 'Normal',
185    'func': 'CoverageModulationNV',
186    'extension_flag': 'chromium_framebuffer_mixed_samples',
187    'states': [
188      { 'enum': 'GL_COVERAGE_MODULATION_CHROMIUM',
189        'name': 'coverage_modulation',
190        'type': 'GLenum',
191        'default': 'GL_NONE',
192      },
193    ]
194  },
195  'BlendColor': {
196    'type': 'Normal',
197    'func': 'BlendColor',
198    'enum': 'GL_BLEND_COLOR',
199    'states': [
200      {'name': 'blend_color_red', 'type': 'GLfloat', 'default': '0.0f'},
201      {'name': 'blend_color_green', 'type': 'GLfloat', 'default': '0.0f'},
202      {'name': 'blend_color_blue', 'type': 'GLfloat', 'default': '0.0f'},
203      {'name': 'blend_color_alpha', 'type': 'GLfloat', 'default': '0.0f'},
204    ],
205  },
206  'BlendEquation': {
207    'type': 'SrcDst',
208    'func': 'BlendEquationSeparate',
209    'states': [
210      {
211        'name': 'blend_equation_rgb',
212        'type': 'GLenum',
213        'enum': 'GL_BLEND_EQUATION_RGB',
214        'default': 'GL_FUNC_ADD',
215      },
216      {
217        'name': 'blend_equation_alpha',
218        'type': 'GLenum',
219        'enum': 'GL_BLEND_EQUATION_ALPHA',
220        'default': 'GL_FUNC_ADD',
221      },
222    ],
223  },
224  'BlendFunc': {
225    'type': 'SrcDst',
226    'func': 'BlendFuncSeparate',
227    'states': [
228      {
229        'name': 'blend_source_rgb',
230        'type': 'GLenum',
231        'enum': 'GL_BLEND_SRC_RGB',
232        'default': 'GL_ONE',
233      },
234      {
235        'name': 'blend_dest_rgb',
236        'type': 'GLenum',
237        'enum': 'GL_BLEND_DST_RGB',
238        'default': 'GL_ZERO',
239      },
240      {
241        'name': 'blend_source_alpha',
242        'type': 'GLenum',
243        'enum': 'GL_BLEND_SRC_ALPHA',
244        'default': 'GL_ONE',
245      },
246      {
247        'name': 'blend_dest_alpha',
248        'type': 'GLenum',
249        'enum': 'GL_BLEND_DST_ALPHA',
250        'default': 'GL_ZERO',
251      },
252    ],
253  },
254  'PolygonOffset': {
255    'type': 'Normal',
256    'func': 'PolygonOffset',
257    'states': [
258      {
259        'name': 'polygon_offset_factor',
260        'type': 'GLfloat',
261        'enum': 'GL_POLYGON_OFFSET_FACTOR',
262        'default': '0.0f',
263      },
264      {
265        'name': 'polygon_offset_units',
266        'type': 'GLfloat',
267        'enum': 'GL_POLYGON_OFFSET_UNITS',
268        'default': '0.0f',
269      },
270    ],
271  },
272  'CullFace':  {
273    'type': 'Normal',
274    'func': 'CullFace',
275    'enum': 'GL_CULL_FACE_MODE',
276    'states': [
277      {
278        'name': 'cull_mode',
279        'type': 'GLenum',
280        'default': 'GL_BACK',
281      },
282    ],
283  },
284  'FrontFace': {
285    'type': 'Normal',
286    'func': 'FrontFace',
287    'enum': 'GL_FRONT_FACE',
288    'states': [{'name': 'front_face', 'type': 'GLenum', 'default': 'GL_CCW'}],
289  },
290  'DepthFunc': {
291    'type': 'Normal',
292    'func': 'DepthFunc',
293    'enum': 'GL_DEPTH_FUNC',
294    'states': [{'name': 'depth_func', 'type': 'GLenum', 'default': 'GL_LESS'}],
295  },
296  'DepthRange': {
297    'type': 'Normal',
298    'func': 'DepthRange',
299    'enum': 'GL_DEPTH_RANGE',
300    'states': [
301      {'name': 'z_near', 'type': 'GLclampf', 'default': '0.0f'},
302      {'name': 'z_far', 'type': 'GLclampf', 'default': '1.0f'},
303    ],
304  },
305  'SampleCoverage': {
306    'type': 'Normal',
307    'func': 'SampleCoverage',
308    'states': [
309      {
310        'name': 'sample_coverage_value',
311        'type': 'GLclampf',
312        'enum': 'GL_SAMPLE_COVERAGE_VALUE',
313        'default': '1.0f',
314      },
315      {
316        'name': 'sample_coverage_invert',
317        'type': 'GLboolean',
318        'enum': 'GL_SAMPLE_COVERAGE_INVERT',
319        'default': 'false',
320      },
321    ],
322  },
323  'StencilMask': {
324    'type': 'FrontBack',
325    'func': 'StencilMaskSeparate',
326    'states': [
327      {
328        'name': 'stencil_front_writemask',
329        'type': 'GLuint',
330        'enum': 'GL_STENCIL_WRITEMASK',
331        'default': '0xFFFFFFFFU',
332        'cached': True,
333      },
334      {
335        'name': 'stencil_back_writemask',
336        'type': 'GLuint',
337        'enum': 'GL_STENCIL_BACK_WRITEMASK',
338        'default': '0xFFFFFFFFU',
339        'cached': True,
340      },
341    ],
342    'on_change': '''framebuffer_state_.clear_state_dirty = true;
343                    state_.stencil_state_changed_since_validation = true;''',
344  },
345  'StencilOp': {
346    'type': 'FrontBack',
347    'func': 'StencilOpSeparate',
348    'states': [
349      {
350        'name': 'stencil_front_fail_op',
351        'type': 'GLenum',
352        'enum': 'GL_STENCIL_FAIL',
353        'default': 'GL_KEEP',
354      },
355      {
356        'name': 'stencil_front_z_fail_op',
357        'type': 'GLenum',
358        'enum': 'GL_STENCIL_PASS_DEPTH_FAIL',
359        'default': 'GL_KEEP',
360      },
361      {
362        'name': 'stencil_front_z_pass_op',
363        'type': 'GLenum',
364        'enum': 'GL_STENCIL_PASS_DEPTH_PASS',
365        'default': 'GL_KEEP',
366      },
367      {
368        'name': 'stencil_back_fail_op',
369        'type': 'GLenum',
370        'enum': 'GL_STENCIL_BACK_FAIL',
371        'default': 'GL_KEEP',
372      },
373      {
374        'name': 'stencil_back_z_fail_op',
375        'type': 'GLenum',
376        'enum': 'GL_STENCIL_BACK_PASS_DEPTH_FAIL',
377        'default': 'GL_KEEP',
378      },
379      {
380        'name': 'stencil_back_z_pass_op',
381        'type': 'GLenum',
382        'enum': 'GL_STENCIL_BACK_PASS_DEPTH_PASS',
383        'default': 'GL_KEEP',
384      },
385    ],
386  },
387  'StencilFunc': {
388    'type': 'FrontBack',
389    'func': 'StencilFuncSeparate',
390    'states': [
391      {
392        'name': 'stencil_front_func',
393        'type': 'GLenum',
394        'enum': 'GL_STENCIL_FUNC',
395        'default': 'GL_ALWAYS',
396      },
397      {
398        'name': 'stencil_front_ref',
399        'type': 'GLint',
400        'enum': 'GL_STENCIL_REF',
401        'default': '0',
402      },
403      {
404        'name': 'stencil_front_mask',
405        'type': 'GLuint',
406        'enum': 'GL_STENCIL_VALUE_MASK',
407        'default': '0xFFFFFFFFU',
408      },
409      {
410        'name': 'stencil_back_func',
411        'type': 'GLenum',
412        'enum': 'GL_STENCIL_BACK_FUNC',
413        'default': 'GL_ALWAYS',
414      },
415      {
416        'name': 'stencil_back_ref',
417        'type': 'GLint',
418        'enum': 'GL_STENCIL_BACK_REF',
419        'default': '0',
420      },
421      {
422        'name': 'stencil_back_mask',
423        'type': 'GLuint',
424        'enum': 'GL_STENCIL_BACK_VALUE_MASK',
425        'default': '0xFFFFFFFFU',
426      },
427    ],
428    'on_change': 'state_.stencil_state_changed_since_validation = true;',
429  },
430  'Hint': {
431    'type': 'NamedParameter',
432    'func': 'Hint',
433    'states': [
434      {
435        'name': 'hint_generate_mipmap',
436        'type': 'GLenum',
437        'enum': 'GL_GENERATE_MIPMAP_HINT',
438        'default': 'GL_DONT_CARE',
439        'gl_version_flag': '!is_desktop_core_profile'
440      },
441      {
442        'name': 'hint_fragment_shader_derivative',
443        'type': 'GLenum',
444        'enum': 'GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES',
445        'default': 'GL_DONT_CARE',
446        'extension_flag': 'oes_standard_derivatives'
447      },
448      {
449        'name': 'hint_texture_filtering',
450        'type': 'GLenum',
451        'enum': 'GL_TEXTURE_FILTERING_HINT_CHROMIUM',
452        'default': 'GL_NICEST',
453        'extension_flag': 'chromium_texture_filtering_hint'
454      }
455    ],
456  },
457  'PixelStore': {
458    'type': 'NamedParameter',
459    'func': 'PixelStorei',
460    'states': [
461      {
462        'name': 'pack_alignment',
463        'type': 'GLint',
464        'enum': 'GL_PACK_ALIGNMENT',
465        'default': '4'
466      },
467      {
468        'name': 'unpack_alignment',
469        'type': 'GLint',
470        'enum': 'GL_UNPACK_ALIGNMENT',
471        'default': '4'
472      },
473      {
474        'name': 'pack_row_length',
475        'type': 'GLint',
476        'enum': 'GL_PACK_ROW_LENGTH',
477        'default': '0',
478        'es3': True,
479        'manual': True,
480      },
481      {
482        'name': 'pack_skip_pixels',
483        'type': 'GLint',
484        'enum': 'GL_PACK_SKIP_PIXELS',
485        'default': '0',
486        'es3': True,
487        'manual': True,
488      },
489      {
490        'name': 'pack_skip_rows',
491        'type': 'GLint',
492        'enum': 'GL_PACK_SKIP_ROWS',
493        'default': '0',
494        'es3': True,
495        'manual': True,
496      },
497      {
498        'name': 'unpack_row_length',
499        'type': 'GLint',
500        'enum': 'GL_UNPACK_ROW_LENGTH',
501        'default': '0',
502        'es3': True,
503        'manual': True,
504      },
505      {
506        'name': 'unpack_image_height',
507        'type': 'GLint',
508        'enum': 'GL_UNPACK_IMAGE_HEIGHT',
509        'default': '0',
510        'es3': True,
511        'manual': True,
512      },
513      {
514        'name': 'unpack_skip_pixels',
515        'type': 'GLint',
516        'enum': 'GL_UNPACK_SKIP_PIXELS',
517        'default': '0',
518        'es3': True,
519        'manual': True,
520      },
521      {
522        'name': 'unpack_skip_rows',
523        'type': 'GLint',
524        'enum': 'GL_UNPACK_SKIP_ROWS',
525        'default': '0',
526        'es3': True,
527        'manual': True,
528      },
529      {
530        'name': 'unpack_skip_images',
531        'type': 'GLint',
532        'enum': 'GL_UNPACK_SKIP_IMAGES',
533        'default': '0',
534        'es3': True,
535        'manual': True,
536      }
537    ],
538  },
539  # TODO: Consider implemenenting these states
540  # GL_ACTIVE_TEXTURE
541  'LineWidth': {
542    'type': 'Normal',
543    'custom_function' : True,
544    'func': 'DoLineWidth',
545    'enum': 'GL_LINE_WIDTH',
546    'states': [
547      {
548        'name': 'line_width',
549        'type': 'GLfloat',
550        'default': '1.0f',
551        'range_checks': [{'check': "<= 0.0f", 'test_value': "0.0f"}],
552        'nan_check': True,
553      }],
554  },
555  'DepthMask': {
556    'type': 'Normal',
557    'func': 'DepthMask',
558    'enum': 'GL_DEPTH_WRITEMASK',
559    'states': [
560      {
561        'name': 'depth_mask',
562        'type': 'GLboolean',
563        'default': 'true',
564        'cached': True
565      },
566    ],
567    'on_change': 'framebuffer_state_.clear_state_dirty = true;',
568  },
569  'Scissor': {
570    'type': 'Normal',
571    'func': 'Scissor',
572    'enum': 'GL_SCISSOR_BOX',
573    'states': [
574      # NOTE: These defaults reset at GLES2DecoderImpl::Initialization.
575      {
576        'name': 'scissor_x',
577        'type': 'GLint',
578        'default': '0',
579      },
580      {
581        'name': 'scissor_y',
582        'type': 'GLint',
583        'default': '0',
584      },
585      {
586        'name': 'scissor_width',
587        'type': 'GLsizei',
588        'default': '1',
589        'expected': 'initial_size.width()',
590      },
591      {
592        'name': 'scissor_height',
593        'type': 'GLsizei',
594        'default': '1',
595        'expected': 'initial_size.height()',
596      },
597    ],
598  },
599  'Viewport': {
600    'type': 'Normal',
601    'func': 'Viewport',
602    'enum': 'GL_VIEWPORT',
603    'states': [
604      # NOTE: These defaults reset at GLES2DecoderImpl::Initialization.
605      {
606        'name': 'viewport_x',
607        'type': 'GLint',
608        'default': '0',
609      },
610      {
611        'name': 'viewport_y',
612        'type': 'GLint',
613        'default': '0',
614      },
615      {
616        'name': 'viewport_width',
617        'type': 'GLsizei',
618        'default': '1',
619        'expected': 'initial_size.width()',
620      },
621      {
622        'name': 'viewport_height',
623        'type': 'GLsizei',
624        'default': '1',
625        'expected': 'initial_size.height()',
626      },
627    ],
628  },
629  'WindowRectanglesEXT': {
630    'type': 'Normal',
631    'func': 'WindowRectanglesEXT',
632    'custom_function': True,
633    'extension_flag': 'ext_window_rectangles',
634    'no_init': True,
635    'states': [
636      {
637        'name': 'window_rectangles_mode',
638        'type': 'GLenum',
639        'enum': 'GL_WINDOW_RECTANGLE_MODE_EXT',
640        'default': 'GL_EXCLUSIVE_EXT',
641      },
642      {
643        'name': 'num_window_rectangles',
644        'type': 'GLint',
645        'enum': 'GL_NUM_WINDOW_RECTANGLES_EXT',
646        'default': '0',
647      },
648    ],
649  },
650}
651
652_prefix = None
653_upper_prefix = None
654_lower_prefix = None
655def InitializePrefix(mixed_case_prefix):
656  """Initialize prefix used for autogenerated code.
657
658  Must be called before autogenerating code. Prefixes are used by autogenerated
659  code in many places: class names, filenames, namespaces, constants,
660  defines. Given a single mixed case prefix suitable for a class name, we also
661  initialize lower and upper case prefixes for other uses (e.g. filenames and
662  #defines).
663  """
664  global _prefix
665  if _prefix:
666    raise AssertionError
667  _prefix = mixed_case_prefix
668
669  global _upper_prefix
670  _upper_prefix = mixed_case_prefix.upper()
671
672  global _lower_prefix
673  _lower_prefix = mixed_case_prefix.lower()
674
675
676def _Namespace():
677  if _lower_prefix != 'gles2':
678    return 'gles2::'
679  return ''
680
681
682def Grouper(n, iterable, fillvalue=None):
683  """Collect data into fixed-length chunks or blocks"""
684  args = [iter(iterable)] * n
685  return itertools.izip_longest(fillvalue=fillvalue, *args)
686
687
688def SplitWords(input_string):
689  """Split by '_' if found, otherwise split at uppercase/numeric chars.
690
691  Will split "some_TEXT" into ["some", "TEXT"], "CamelCase" into ["Camel",
692  "Case"], and "Vector3" into ["Vector", "3"].
693  """
694  if input_string.find('_') > -1:
695    # 'some_TEXT_' -> 'some TEXT'
696    return input_string.replace('_', ' ').strip().split()
697  else:
698    input_string = input_string.replace('::', ' ')
699    if re.search('[A-Z]', input_string) and re.search('[a-z]', input_string):
700      # mixed case.
701      # look for capitalization to cut input_strings
702      # 'SomeText' -> 'Some Text'
703      input_string = re.sub('([A-Z])', r' \1', input_string).strip()
704      # 'Vector3' -> 'Vector 3'
705      input_string = re.sub('([^0-9])([0-9])', r'\1 \2', input_string)
706    return input_string.split()
707
708def ToUnderscore(input_string):
709  """converts CamelCase to camel_case."""
710  words = SplitWords(input_string)
711  return '_'.join([word.lower() for word in words])
712
713def ValidatorClassName(type_name):
714  """Converts some::namespace::TypeName to SomeNamespaceTypeNameValidator."""
715  words = SplitWords(type_name)
716  prefix = ''.join([word.title() for word in words])
717  return '%sValidator' % prefix
718
719def CachedStateName(item):
720  if item.get('cached', False):
721    return 'cached_' + item['name']
722  return item['name']
723
724def GuardState(state, operation, feature_info):
725  if 'manual' in state:
726    assert state['manual']
727    return ""
728
729  result = []
730  result_end = []
731  if 'es3' in state:
732    assert state['es3']
733    result.append("  if (%s->IsES3Capable()) {\n" % feature_info);
734    result_end.append("  }\n")
735  if 'extension_flag' in state:
736    result.append("  if (%s->feature_flags().%s) {\n  " %
737                     (feature_info, state['extension_flag']))
738    result_end.append("  }\n")
739  if 'gl_version_flag' in state:
740    name = state['gl_version_flag']
741    inverted = ''
742    if name[0] == '!':
743      inverted = '!'
744      name = name[1:]
745    result.append("  if (%s%s->gl_version_info().%s) {\n" %
746                      (inverted, feature_info, name))
747    result_end.append("  }\n")
748
749  result.append(operation)
750  return ''.join(result + result_end)
751
752def ToGLExtensionString(extension_flag):
753  """Returns GL-type extension string of a extension flag."""
754  if extension_flag == "oes_compressed_etc1_rgb8_texture":
755    return "OES_compressed_ETC1_RGB8_texture" # Fixup inconsitency with rgb8,
756                                              # unfortunate.
757  uppercase_words = [ 'img', 'ext', 'arb', 'chromium', 'oes', 'amd', 'bgra8888',
758                      'egl', 'atc', 'etc1', 'angle']
759  parts = extension_flag.split('_')
760  return "_".join(
761    [part.upper() if part in uppercase_words else part for part in parts])
762
763def ToCamelCase(input_string):
764  """converts ABC_underscore_case to ABCUnderscoreCase."""
765  return ''.join(w[0].upper() + w[1:] for w in input_string.split('_'))
766
767def EnumsConflict(a, b):
768  """Returns true if the enums have different names (ignoring suffixes) and one
769  of them is a Chromium enum."""
770  if a == b:
771    return False
772
773  if b.endswith('_CHROMIUM'):
774    a, b = b, a
775
776  if not a.endswith('_CHROMIUM'):
777    return False
778
779  def removesuffix(string, suffix):
780    if not string.endswith(suffix):
781      return string
782    return string[:-len(suffix)]
783  b = removesuffix(b, "_NV")
784  b = removesuffix(b, "_EXT")
785  b = removesuffix(b, "_OES")
786  return removesuffix(a, "_CHROMIUM") != b
787
788def GetGLGetTypeConversion(result_type, value_type, value):
789  """Makes a gl compatible type conversion string for accessing state variables.
790
791   Useful when accessing state variables through glGetXXX calls.
792   glGet documetation (for example, the manual pages):
793   [...] If glGetIntegerv is called, [...] most floating-point values are
794   rounded to the nearest integer value. [...]
795
796  Args:
797   result_type: the gl type to be obtained
798   value_type: the GL type of the state variable
799   value: the name of the state variable
800
801  Returns:
802   String that converts the state variable to desired GL type according to GL
803   rules.
804  """
805
806  if result_type == 'GLint':
807    if value_type == 'GLfloat':
808      return 'static_cast<GLint>(round(%s))' % value
809  return 'static_cast<%s>(%s)' % (result_type, value)
810
811
812class CWriter(object):
813  """Context manager that creates a C source file.
814
815  To be used with the `with` statement. Returns a normal `file` type, open only
816  for writing - any existing files with that name will be overwritten. It will
817  automatically write the contents of `_LICENSE` and `_DO_NOT_EDIT_WARNING`
818  at the beginning.
819
820  Example:
821    with CWriter("file.cpp") as myfile:
822      myfile.write("hello")
823      # type(myfile) == file
824  """
825  def __init__(self, filename, year):
826    self.filename = filename
827    self._ENTER_MSG = _LICENSE % year + _DO_NOT_EDIT_WARNING % _lower_prefix
828    self._EXIT_MSG = ""
829    try:
830      os.makedirs(os.path.dirname(filename))
831    except OSError as e:
832      if e.errno == errno.EEXIST:
833        pass
834    self._file = open(filename, 'wb')
835
836  def __enter__(self):
837    self._file.write(self._ENTER_MSG)
838    return self._file
839
840  def __exit__(self, exc_type, exc_value, traceback):
841    self._file.write(self._EXIT_MSG)
842    self._file.close()
843
844
845class CHeaderWriter(CWriter):
846  """Context manager that creates a C header file.
847
848  Works the same way as CWriter, except it will also add the #ifdef guard
849  around it. If `file_comment` is set, it will write that before the #ifdef
850  guard.
851  """
852  def __init__(self, filename, year, file_comment=None):
853    super(CHeaderWriter, self).__init__(filename, year)
854    guard = self._get_guard()
855    if file_comment is None:
856      file_comment = ""
857    self._ENTER_MSG = self._ENTER_MSG + file_comment \
858                    + "#ifndef %s\n#define %s\n\n" % (guard, guard)
859    self._EXIT_MSG = self._EXIT_MSG + "#endif  // %s\n" % guard
860
861  def _get_guard(self):
862    non_alnum_re = re.compile(r'[^a-zA-Z0-9]')
863    assert self.filename.startswith("gpu/")
864    return non_alnum_re.sub('_', self.filename).upper() + '_'
865
866
867class TypeHandler(object):
868  """This class emits code for a particular type of function."""
869
870  _remove_expected_call_re = re.compile(r'  EXPECT_CALL.*?;\n', re.S)
871
872  def InitFunction(self, func):
873    """Add or adjust anything type specific for this function."""
874    if func.GetInfo('needs_size') and not func.name.endswith('Bucket'):
875      func.AddCmdArg(DataSizeArgument('data_size'))
876
877  def NeedsDataTransferFunction(self, func):
878    """Overriden from TypeHandler."""
879    return func.num_pointer_args >= 1
880
881  def WriteStruct(self, func, f):
882    """Writes a structure that matches the arguments to a function."""
883    comment = func.GetInfo('cmd_comment')
884    if not comment == None:
885      f.write(comment)
886    f.write("struct %s {\n" % func.name)
887    f.write("  typedef %s ValueType;\n" % func.name)
888    f.write("  static const CommandId kCmdId = k%s;\n" % func.name)
889    func.WriteCmdArgFlag(f)
890    func.WriteCmdFlag(f)
891    f.write("\n")
892    result = func.GetInfo('result')
893    if not result == None:
894      if len(result) == 1:
895        f.write("  typedef %s Result;\n\n" % result[0])
896      else:
897        f.write("  struct Result {\n")
898        for line in result:
899          f.write("    %s;\n" % line)
900        f.write("  };\n\n")
901
902    func.WriteCmdComputeSize(f)
903    func.WriteCmdSetHeader(f)
904    func.WriteCmdInit(f)
905    func.WriteCmdSet(f)
906    func.WriteArgAccessors(f)
907
908    f.write("  gpu::CommandHeader header;\n")
909    total_args = 0
910    args = func.GetCmdArgs()
911    for arg in args:
912      for cmd_type, name in arg.GetArgDecls():
913        f.write("  %s %s;\n" % (cmd_type, name))
914        total_args += 1
915    trace_queue = func.GetInfo('trace_queueing_flow', False)
916    if trace_queue:
917      f.write("  uint32_t trace_id;\n")
918      total_args += 1
919
920    consts = func.GetCmdConstants()
921    for const in consts:
922      const_decls = const.GetArgDecls()
923      assert(len(const_decls) == 1)
924      const_cmd_type, const_name = const_decls[0]
925      f.write("  static const %s %s = %s;\n" %
926                 (const_cmd_type, const_name, const.GetConstantValue()))
927
928    f.write("};\n")
929    f.write("\n")
930
931    size = total_args * _SIZE_OF_UINT32 + _SIZE_OF_COMMAND_HEADER
932    f.write("static_assert(sizeof(%s) == %d,\n" % (func.name, size))
933    f.write("              \"size of %s should be %d\");\n" %
934            (func.name, size))
935    f.write("static_assert(offsetof(%s, header) == 0,\n" % func.name)
936    f.write("              \"offset of %s header should be 0\");\n" %
937            func.name)
938    offset = _SIZE_OF_COMMAND_HEADER
939    for arg in args:
940      for _, name in arg.GetArgDecls():
941        f.write("static_assert(offsetof(%s, %s) == %d,\n" %
942                (func.name, name, offset))
943        f.write("              \"offset of %s %s should be %d\");\n" %
944                (func.name, name, offset))
945        offset += _SIZE_OF_UINT32
946    if not result == None and len(result) > 1:
947      offset = 0;
948      for line in result:
949        parts = line.split()
950        name = parts[-1]
951        check = """
952static_assert(offsetof(%(cmd_name)s::Result, %(field_name)s) == %(offset)d,
953              "offset of %(cmd_name)s Result %(field_name)s should be "
954              "%(offset)d");
955"""
956        f.write((check.strip() + "\n") % {
957              'cmd_name': func.name,
958              'field_name': name,
959              'offset': offset,
960            })
961        offset += _SIZE_OF_UINT32
962    f.write("\n")
963
964  def WriteHandlerImplementation(self, func, f):
965    """Writes the handler implementation for this command."""
966    args = []
967    for arg in func.GetOriginalArgs():
968      if arg.name.endswith("size") and arg.type == "GLsizei":
969        args.append("num_%s" % func.GetLastOriginalArg().name)
970      elif arg.name == "length":
971        args.append("nullptr")
972      else:
973        args.append(arg.name)
974
975    if func.GetInfo('type') == 'GETn' and func.name != 'GetSynciv':
976      args.append('num_values')
977
978    f.write("  %s(%s);\n" %
979               (func.GetGLFunctionName(), ", ".join(args)))
980
981  def WriteCmdSizeTest(self, _func, f):
982    """Writes the size test for a command."""
983    f.write("  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);\n")
984
985  def WriteFormatTest(self, func, f):
986    """Writes a format test for a command."""
987    f.write("TEST_F(%sFormatTest, %s) {\n" % (_prefix, func.name))
988    f.write("  cmds::%s& cmd = *GetBufferAs<cmds::%s>();\n" %
989               (func.name, func.name))
990    f.write("  void* next_cmd = cmd.Set(\n")
991    f.write("      &cmd")
992    args = func.GetCmdArgs()
993    for value, arg in enumerate(args):
994      f.write(",\n      static_cast<%s>(%d)" % (arg.type, value + 11))
995    f.write(");\n")
996    f.write("  EXPECT_EQ(static_cast<uint32_t>(cmds::%s::kCmdId),\n" %
997               func.name)
998    f.write("            cmd.header.command);\n")
999    func.type_handler.WriteCmdSizeTest(func, f)
1000    for value, arg in enumerate(args):
1001      f.write("  EXPECT_EQ(static_cast<%s>(%d), %s);\n" %
1002                 (arg.type, value + 11, arg.GetArgAccessor('cmd')))
1003    f.write("  CheckBytesWrittenMatchesExpectedSize(\n")
1004    f.write("      next_cmd, sizeof(cmd));\n")
1005    f.write("}\n")
1006    f.write("\n")
1007
1008  def WriteImmediateFormatTest(self, func, f):
1009    """Writes a format test for an immediate version of a command."""
1010    pass
1011
1012  def WriteGetDataSizeCode(self, func, arg, f):
1013    """Writes the code to set data_size used in validation"""
1014    pass
1015
1016  def WriteImmediateHandlerImplementation (self, func, f):
1017    """Writes the handler impl for the immediate version of a command."""
1018    f.write("  %s(%s);\n" %
1019               (func.GetGLFunctionName(), func.MakeOriginalArgString("")))
1020
1021  def WriteBucketHandlerImplementation (self, func, f):
1022    """Writes the handler impl for the bucket version of a command."""
1023    f.write("  %s(%s);\n" %
1024               (func.GetGLFunctionName(), func.MakeOriginalArgString("")))
1025
1026  def WriteServiceHandlerFunctionHeader(self, func, f):
1027    """Writes function header for service implementation handlers."""
1028    f.write("""error::Error %(prefix)sDecoderImpl::Handle%(name)s(
1029        uint32_t immediate_data_size, const volatile void* cmd_data) {
1030      """ % {'name': func.name, 'prefix' : _prefix})
1031    if func.IsES3():
1032      f.write("""if (!feature_info_->IsWebGL2OrES3OrHigherContext())
1033          return error::kUnknownCommand;
1034        """)
1035    if func.IsES31():
1036      f.write("""return error::kUnknownCommand;
1037        }
1038
1039        """)
1040      return
1041    if func.GetCmdArgs():
1042      f.write("""const volatile %(prefix)s::cmds::%(name)s& c =
1043            *static_cast<const volatile %(prefix)s::cmds::%(name)s*>(cmd_data);
1044        """ % {'name': func.name, 'prefix': _lower_prefix})
1045
1046  def WriteServiceHandlerArgGetCode(self, func, f):
1047    """Writes the argument unpack code for service handlers."""
1048    if len(func.GetOriginalArgs()) > 0:
1049      for arg in func.GetOriginalArgs():
1050        if not arg.IsPointer():
1051          arg.WriteGetCode(f)
1052
1053      # Write pointer arguments second. Sizes may be dependent on other args
1054      for arg in func.GetOriginalArgs():
1055        if arg.IsPointer():
1056          self.WriteGetDataSizeCode(func, arg, f)
1057          arg.WriteGetCode(f)
1058
1059  def WriteImmediateServiceHandlerArgGetCode(self, func, f):
1060    """Writes the argument unpack code for immediate service handlers."""
1061    for arg in func.GetOriginalArgs():
1062      if arg.IsPointer():
1063        self.WriteGetDataSizeCode(func, arg, f)
1064      arg.WriteGetCode(f)
1065
1066  def WriteBucketServiceHandlerArgGetCode(self, func, f):
1067    """Writes the argument unpack code for bucket service handlers."""
1068    for arg in func.GetCmdArgs():
1069      arg.WriteGetCode(f)
1070    for arg in func.GetOriginalArgs():
1071      if arg.IsConstant():
1072        arg.WriteGetCode(f)
1073    self.WriteGetDataSizeCode(func, arg, f)
1074
1075  def WriteServiceImplementation(self, func, f):
1076    """Writes the service implementation for a command."""
1077    self.WriteServiceHandlerFunctionHeader(func, f)
1078    if func.IsES31():
1079      return
1080    self.WriteHandlerExtensionCheck(func, f)
1081    self.WriteHandlerDeferReadWrite(func, f);
1082    self.WriteServiceHandlerArgGetCode(func, f)
1083    func.WriteHandlerValidation(f)
1084    func.WriteQueueTraceEvent(f)
1085    func.WriteHandlerImplementation(f)
1086    f.write("  return error::kNoError;\n")
1087    f.write("}\n")
1088    f.write("\n")
1089
1090  def WriteImmediateServiceImplementation(self, func, f):
1091    """Writes the service implementation for an immediate version of command."""
1092    self.WriteServiceHandlerFunctionHeader(func, f)
1093    if func.IsES31():
1094      return
1095    self.WriteHandlerExtensionCheck(func, f)
1096    self.WriteHandlerDeferReadWrite(func, f);
1097    self.WriteImmediateServiceHandlerArgGetCode(func, f)
1098    func.WriteHandlerValidation(f)
1099    func.WriteQueueTraceEvent(f)
1100    func.WriteHandlerImplementation(f)
1101    f.write("  return error::kNoError;\n")
1102    f.write("}\n")
1103    f.write("\n")
1104
1105  def WriteBucketServiceImplementation(self, func, f):
1106    """Writes the service implementation for a bucket version of command."""
1107    self.WriteServiceHandlerFunctionHeader(func, f)
1108    if func.IsES31():
1109      return
1110    self.WriteHandlerExtensionCheck(func, f)
1111    self.WriteHandlerDeferReadWrite(func, f);
1112    self.WriteBucketServiceHandlerArgGetCode(func, f)
1113    func.WriteHandlerValidation(f)
1114    func.WriteQueueTraceEvent(f)
1115    func.WriteHandlerImplementation(f)
1116    f.write("  return error::kNoError;\n")
1117    f.write("}\n")
1118    f.write("\n")
1119
1120  def WritePassthroughServiceFunctionHeader(self, func, f):
1121    """Writes function header for service passthrough handlers."""
1122    f.write("""error::Error GLES2DecoderPassthroughImpl::Handle%(name)s(
1123        uint32_t immediate_data_size, const volatile void* cmd_data) {
1124      """ % {'name': func.name})
1125    if func.IsES3():
1126      f.write("""if (!feature_info_->IsWebGL2OrES3OrHigherContext())
1127          return error::kUnknownCommand;
1128        """)
1129    if func.IsES31():
1130      f.write("""if (!feature_info_->IsWebGL2ComputeContext())
1131          return error::kUnknownCommand;
1132        """)
1133    if func.GetCmdArgs():
1134      f.write("""const volatile gles2::cmds::%(name)s& c =
1135            *static_cast<const volatile gles2::cmds::%(name)s*>(cmd_data);
1136        """ % {'name': func.name})
1137
1138  def WritePassthroughServiceFunctionDoerCall(self, func, f):
1139    """Writes the function call to the passthrough service doer."""
1140    f.write("""  error::Error error = Do%(name)s(%(args)s);
1141  if (error != error::kNoError) {
1142    return error;
1143  }""" % {'name': func.original_name,
1144          'args': func.MakePassthroughServiceDoerArgString("")})
1145
1146  def WritePassthroughServiceImplementation(self, func, f):
1147    """Writes the service implementation for a command."""
1148    self.WritePassthroughServiceFunctionHeader(func, f)
1149    self.WriteHandlerExtensionCheck(func, f)
1150    self.WriteServiceHandlerArgGetCode(func, f)
1151    func.WritePassthroughHandlerValidation(f)
1152    self.WritePassthroughServiceFunctionDoerCall(func, f)
1153    f.write("  return error::kNoError;\n")
1154    f.write("}\n")
1155    f.write("\n")
1156
1157  def WritePassthroughImmediateServiceImplementation(self, func, f):
1158    """Writes the service implementation for a command."""
1159    self.WritePassthroughServiceFunctionHeader(func, f)
1160    self.WriteHandlerExtensionCheck(func, f)
1161    self.WriteImmediateServiceHandlerArgGetCode(func, f)
1162    func.WritePassthroughHandlerValidation(f)
1163    self.WritePassthroughServiceFunctionDoerCall(func, f)
1164    f.write("  return error::kNoError;\n")
1165    f.write("}\n")
1166    f.write("\n")
1167
1168  def WritePassthroughBucketServiceImplementation(self, func, f):
1169    """Writes the service implementation for a command."""
1170    self.WritePassthroughServiceFunctionHeader(func, f)
1171    self.WriteHandlerExtensionCheck(func, f)
1172    self.WriteBucketServiceHandlerArgGetCode(func, f)
1173    func.WritePassthroughHandlerValidation(f)
1174    self.WritePassthroughServiceFunctionDoerCall(func, f)
1175    f.write("  return error::kNoError;\n")
1176    f.write("}\n")
1177    f.write("\n")
1178
1179  def WriteHandlerExtensionCheck(self, func, f):
1180    if func.GetInfo('extension_flag'):
1181      f.write("  if (!features().%s) {\n" % func.GetInfo('extension_flag'))
1182      f.write("    return error::kUnknownCommand;")
1183      f.write("  }\n\n")
1184
1185  def WriteHandlerDeferReadWrite(self, func, f):
1186    """Writes the code to handle deferring reads or writes."""
1187    defer_draws = func.GetInfo('defer_draws')
1188    defer_reads = func.GetInfo('defer_reads')
1189    if defer_draws or defer_reads:
1190      f.write("  error::Error error;\n")
1191    if defer_draws:
1192      f.write("  error = WillAccessBoundFramebufferForDraw();\n")
1193      f.write("  if (error != error::kNoError)\n")
1194      f.write("    return error;\n")
1195    if defer_reads:
1196      f.write("  error = WillAccessBoundFramebufferForRead();\n")
1197      f.write("  if (error != error::kNoError)\n")
1198      f.write("    return error;\n")
1199
1200  def WriteValidUnitTest(self, func, f, test, *extras):
1201    """Writes a valid unit test for the service implementation."""
1202    if not func.GetInfo('expectation', True):
1203      test = self._remove_expected_call_re.sub('', test)
1204    name = func.name
1205    arg_strings = [
1206      arg.GetValidArg(func) \
1207      for arg in func.GetOriginalArgs() if not arg.IsConstant()
1208    ]
1209    gl_arg_strings = [
1210      arg.GetValidGLArg(func) \
1211      for arg in func.GetOriginalArgs()
1212    ]
1213    gl_func_name = func.GetGLTestFunctionName()
1214    varz = {
1215      'name': name,
1216      'gl_func_name': gl_func_name,
1217      'args': ", ".join(arg_strings),
1218      'gl_args': ", ".join(gl_arg_strings),
1219    }
1220    for extra in extras:
1221      varz.update(extra)
1222    old_test = ""
1223    while (old_test != test):
1224      old_test = test
1225      test = test % varz
1226    f.write(test % varz)
1227
1228  def WriteInvalidUnitTest(self, func, f, test, *extras):
1229    """Writes an invalid unit test for the service implementation."""
1230    if func.IsES3():
1231      return
1232    for invalid_arg_index, invalid_arg in enumerate(func.GetOriginalArgs()):
1233      # Service implementation does not test constants, as they are not part of
1234      # the call in the service side.
1235      if invalid_arg.IsConstant():
1236        continue
1237
1238      num_invalid_values = invalid_arg.GetNumInvalidValues(func)
1239      for value_index in range(0, num_invalid_values):
1240        arg_strings = []
1241        parse_result = "kNoError"
1242        gl_error = None
1243        for arg in func.GetOriginalArgs():
1244          if arg.IsConstant():
1245            continue
1246          if invalid_arg is arg:
1247            (arg_string, parse_result, gl_error) = arg.GetInvalidArg(
1248                value_index)
1249          else:
1250            arg_string = arg.GetValidArg(func)
1251          arg_strings.append(arg_string)
1252        gl_arg_strings = []
1253        for arg in func.GetOriginalArgs():
1254          gl_arg_strings.append("_")
1255        gl_func_name = func.GetGLTestFunctionName()
1256        gl_error_test = ''
1257        if not gl_error == None:
1258          gl_error_test = '\n  EXPECT_EQ(%s, GetGLError());' % gl_error
1259
1260        varz = {
1261          'name': func.name,
1262          'arg_index': invalid_arg_index,
1263          'value_index': value_index,
1264          'gl_func_name': gl_func_name,
1265          'args': ", ".join(arg_strings),
1266          'all_but_last_args': ", ".join(arg_strings[:-1]),
1267          'gl_args': ", ".join(gl_arg_strings),
1268          'parse_result': parse_result,
1269          'gl_error_test': gl_error_test,
1270        }
1271        for extra in extras:
1272          varz.update(extra)
1273        f.write(test % varz)
1274
1275  def WriteServiceUnitTest(self, func, f, *extras):
1276    """Writes the service unit test for a command."""
1277
1278    if func.name == 'Enable':
1279      valid_test = """
1280TEST_P(%(test_name)s, %(name)sValidArgs) {
1281  SetupExpectationsForEnableDisable(%(gl_args)s, true);
1282  SpecializedSetup<cmds::%(name)s, 0>(true);
1283  cmds::%(name)s cmd;
1284  cmd.Init(%(args)s);"""
1285    elif func.name == 'Disable':
1286      valid_test = """
1287TEST_P(%(test_name)s, %(name)sValidArgs) {
1288  SetupExpectationsForEnableDisable(%(gl_args)s, false);
1289  SpecializedSetup<cmds::%(name)s, 0>(true);
1290  cmds::%(name)s cmd;
1291  cmd.Init(%(args)s);"""
1292    else:
1293      valid_test = """
1294TEST_P(%(test_name)s, %(name)sValidArgs) {
1295  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s));
1296  SpecializedSetup<cmds::%(name)s, 0>(true);
1297  cmds::%(name)s cmd;
1298  cmd.Init(%(args)s);"""
1299    valid_test += """
1300  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
1301  EXPECT_EQ(GL_NO_ERROR, GetGLError());
1302}
1303"""
1304    self.WriteValidUnitTest(func, f, valid_test, *extras)
1305
1306    if not func.IsES3():
1307      invalid_test = """
1308TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
1309  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)).Times(0);
1310  SpecializedSetup<cmds::%(name)s, 0>(false);
1311  cmds::%(name)s cmd;
1312  cmd.Init(%(args)s);
1313  EXPECT_EQ(error::%(parse_result)s, ExecuteCmd(cmd));%(gl_error_test)s
1314}
1315"""
1316      self.WriteInvalidUnitTest(func, f, invalid_test, *extras)
1317
1318  def WriteImmediateServiceUnitTest(self, func, f, *extras):
1319    """Writes the service unit test for an immediate command."""
1320    pass
1321
1322  def WriteImmediateValidationCode(self, func, f):
1323    """Writes the validation code for an immediate version of a command."""
1324    pass
1325
1326  def WriteBucketServiceUnitTest(self, func, f, *extras):
1327    """Writes the service unit test for a bucket command."""
1328    pass
1329
1330  def WriteGLES2ImplementationDeclaration(self, func, f):
1331    """Writes the GLES2 Implemention declaration."""
1332    f.write("%s %s(%s) override;\n" %
1333               (func.return_type, func.original_name,
1334                func.MakeTypedOriginalArgString("", add_default = True)))
1335    f.write("\n")
1336
1337  def WriteGLES2CLibImplementation(self, func, f):
1338    f.write("%s GL_APIENTRY GLES2%s(%s) {\n" %
1339               (func.return_type, func.name,
1340                func.MakeTypedOriginalArgString("")))
1341    result_string = "return "
1342    if func.return_type == "void":
1343      result_string = ""
1344    f.write("  %sgles2::GetGLContext()->%s(%s);\n" %
1345               (result_string, func.original_name,
1346                func.MakeOriginalArgString("")))
1347    f.write("}\n")
1348
1349  def WriteGLES2Header(self, func, f):
1350    """Writes a re-write macro for GLES"""
1351    f.write("#define gl%s GLES2_GET_FUN(%s)\n" %(func.name, func.name))
1352
1353  def WriteClientGLCallLog(self, func, f):
1354    """Writes a logging macro for the client side code."""
1355    comma = ""
1356    if len(func.GetOriginalArgs()):
1357      comma = " << "
1358    f.write(
1359        '  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] %s("%s%s << ")");\n' %
1360        (func.prefixed_name, comma, func.MakeLogArgString()))
1361
1362  def WriteClientGLReturnLog(self, func, f):
1363    """Writes the return value logging code."""
1364    if func.return_type != "void":
1365      f.write('  GPU_CLIENT_LOG("return:" << result)\n')
1366
1367  def WriteGLES2ImplementationHeader(self, func, f):
1368    """Writes the GLES2 Implemention."""
1369    self.WriteGLES2ImplementationDeclaration(func, f)
1370
1371  def WriteGLES2TraceImplementationHeader(self, func, f):
1372    """Writes the GLES2 Trace Implemention header."""
1373    f.write("%s %s(%s) override;\n" %
1374               (func.return_type, func.original_name,
1375                func.MakeTypedOriginalArgString("")))
1376
1377  def WriteGLES2TraceImplementation(self, func, f):
1378    """Writes the GLES2 Trace Implemention."""
1379    f.write("%s GLES2TraceImplementation::%s(%s) {\n" %
1380               (func.return_type, func.original_name,
1381                func.MakeTypedOriginalArgString("")))
1382    result_string = "return "
1383    if func.return_type == "void":
1384      result_string = ""
1385    f.write('  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::%s");\n' %
1386               func.name)
1387    f.write("  %sgl_->%s(%s);\n" %
1388               (result_string, func.name, func.MakeOriginalArgString("")))
1389    f.write("}\n")
1390    f.write("\n")
1391
1392  def WriteGLES2Implementation(self, func, f):
1393    """Writes the GLES2 Implemention."""
1394    impl_func = func.GetInfo('impl_func', True)
1395    if func.can_auto_generate and impl_func:
1396      f.write("%s %sImplementation::%s(%s) {\n" %
1397                 (func.return_type, _prefix,  func.original_name,
1398                  func.MakeTypedOriginalArgString("")))
1399      f.write("  GPU_CLIENT_SINGLE_THREAD_CHECK();\n")
1400      self.WriteClientGLCallLog(func, f)
1401      func.WriteDestinationInitalizationValidation(f)
1402      for arg in func.GetOriginalArgs():
1403        arg.WriteClientSideValidationCode(f, func)
1404      f.write("  helper_->%s(%s);\n" %
1405                 (func.name, func.MakeHelperArgString("")))
1406      if _prefix != 'WebGPU':
1407        f.write("  CheckGLError();\n")
1408      self.WriteClientGLReturnLog(func, f)
1409      f.write("}\n")
1410      f.write("\n")
1411
1412  def WriteGLES2InterfaceHeader(self, func, f):
1413    """Writes the GLES2 Interface."""
1414    f.write("virtual %s %s(%s) = 0;\n" %
1415               (func.return_type, func.original_name,
1416                func.MakeTypedOriginalArgString("", add_default = True)))
1417
1418  def WriteGLES2InterfaceStub(self, func, f):
1419    """Writes the GLES2 Interface stub declaration."""
1420    f.write("%s %s(%s) override;\n" %
1421               (func.return_type, func.original_name,
1422                func.MakeTypedOriginalArgString("")))
1423
1424  def WriteGLES2InterfaceStubImpl(self, func, f):
1425    """Writes the GLES2 Interface stub declaration."""
1426    args = func.GetOriginalArgs()
1427    arg_string = ", ".join(
1428        ["%s /* %s */" % (arg.type, arg.name) for arg in args])
1429    f.write("%s %sInterfaceStub::%s(%s) {\n" %
1430               (func.return_type, _prefix, func.original_name, arg_string))
1431    if func.return_type != "void":
1432      f.write("  return 0;\n")
1433    f.write("}\n")
1434
1435  def WriteGLES2ImplementationUnitTest(self, func, f):
1436    """Writes the GLES2 Implemention unit test."""
1437    client_test = func.GetInfo('client_test', True)
1438    if func.can_auto_generate and client_test:
1439      code = """
1440TEST_F(%(prefix)sImplementationTest, %(name)s) {
1441  struct Cmds {
1442    cmds::%(name)s cmd;
1443  };
1444  Cmds expected;
1445  expected.cmd.Init(%(cmd_args)s);
1446
1447  gl_->%(name)s(%(args)s);
1448  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1449}
1450"""
1451      cmd_arg_strings = [
1452        arg.GetValidClientSideCmdArg(func) for arg in func.GetCmdArgs()
1453      ]
1454
1455      gl_arg_strings = [
1456        arg.GetValidClientSideArg(func) for arg in func.GetOriginalArgs()
1457      ]
1458
1459      f.write(code % {
1460            'prefix' : _prefix,
1461            'name': func.name,
1462            'args': ", ".join(gl_arg_strings),
1463            'cmd_args': ", ".join(cmd_arg_strings),
1464          })
1465
1466      # Test constants for invalid values, as they are not tested by the
1467      # service.
1468      constants = [arg for arg in func.GetOriginalArgs() if arg.IsConstant()]
1469      if constants:
1470        code = """
1471TEST_F(%(prefix)sImplementationTest,
1472    %(name)sInvalidConstantArg%(invalid_index)d) {
1473  gl_->%(name)s(%(args)s);
1474  EXPECT_TRUE(NoCommandsWritten());
1475  EXPECT_EQ(%(gl_error)s, CheckError());
1476}
1477"""
1478        for invalid_arg in constants:
1479          gl_arg_strings = []
1480          invalid = invalid_arg.GetInvalidArg(func)
1481          for arg in func.GetOriginalArgs():
1482            if arg is invalid_arg:
1483              gl_arg_strings.append(invalid[0])
1484            else:
1485              gl_arg_strings.append(arg.GetValidClientSideArg(func))
1486
1487          f.write(code % {
1488            'prefix' : _prefix,
1489            'name': func.name,
1490            'invalid_index': func.GetOriginalArgs().index(invalid_arg),
1491            'args': ", ".join(gl_arg_strings),
1492            'gl_error': invalid[2],
1493          })
1494
1495  def WriteDestinationInitalizationValidation(self, func, f):
1496    """Writes the client side destintion initialization validation."""
1497    for arg in func.GetOriginalArgs():
1498      arg.WriteDestinationInitalizationValidation(f, func)
1499
1500  def WriteTraceEvent(self, func, f):
1501    f.write('  TRACE_EVENT0("gpu", "%sImplementation::%s");\n' %
1502               (_prefix, func.original_name))
1503
1504  def WriteImmediateCmdComputeSize(self, _func, f):
1505    """Writes the size computation code for the immediate version of a cmd."""
1506    f.write("  static uint32_t ComputeSize(uint32_t size_in_bytes) {\n")
1507    f.write("    return static_cast<uint32_t>(\n")
1508    f.write("        sizeof(ValueType) +  // NOLINT\n")
1509    f.write("        RoundSizeToMultipleOfEntries(size_in_bytes));\n")
1510    f.write("  }\n")
1511    f.write("\n")
1512
1513  def WriteImmediateCmdSetHeader(self, _func, f):
1514    """Writes the SetHeader function for the immediate version of a cmd."""
1515    f.write("  void SetHeader(uint32_t size_in_bytes) {\n")
1516    f.write("    header.SetCmdByTotalSize<ValueType>(size_in_bytes);\n")
1517    f.write("  }\n")
1518    f.write("\n")
1519
1520  def WriteImmediateCmdInit(self, func, f):
1521    """Writes the Init function for the immediate version of a command."""
1522    raise NotImplementedError(func.name)
1523
1524  def WriteImmediateCmdSet(self, func, f):
1525    """Writes the Set function for the immediate version of a command."""
1526    raise NotImplementedError(func.name)
1527
1528  def WriteCmdHelper(self, func, f):
1529    """Writes the cmd helper definition for a cmd."""
1530    code = """  void %(name)s(%(typed_args)s) {
1531    %(lp)s::cmds::%(name)s* c = GetCmdSpace<%(lp)s::cmds::%(name)s>();
1532    if (c) {
1533      c->Init(%(args)s);
1534    }
1535  }
1536
1537"""
1538    f.write(code % {
1539          "lp" : _lower_prefix,
1540          "name": func.name,
1541          "typed_args": func.MakeTypedCmdArgString(""),
1542          "args": func.MakeCmdArgString(""),
1543        })
1544
1545  def WriteImmediateCmdHelper(self, func, f):
1546    """Writes the cmd helper definition for the immediate version of a cmd."""
1547    code = """  void %(name)s(%(typed_args)s) {
1548    const uint32_t s = 0;
1549    %(lp)s::cmds::%(name)s* c =
1550        GetImmediateCmdSpaceTotalSize<%(lp)s::cmds::%(name)s>(s);
1551    if (c) {
1552      c->Init(%(args)s);
1553    }
1554  }
1555
1556"""
1557    f.write(code % {
1558           "lp" : _lower_prefix,
1559           "name": func.name,
1560           "typed_args": func.MakeTypedCmdArgString(""),
1561           "args": func.MakeCmdArgString(""),
1562        })
1563
1564
1565class StateSetHandler(TypeHandler):
1566  """Handler for commands that simply set state."""
1567
1568  def WriteHandlerImplementation(self, func, f):
1569    """Overrriden from TypeHandler."""
1570    state_name = func.GetInfo('state')
1571    state = _STATE_INFO[state_name]
1572    states = state['states']
1573    args = func.GetOriginalArgs()
1574    for ndx,item in enumerate(states):
1575      code = []
1576      if 'range_checks' in item:
1577        for range_check in item['range_checks']:
1578          code.append("%s %s" % (args[ndx].name, range_check['check']))
1579      if 'nan_check' in item:
1580        # Drivers might generate an INVALID_VALUE error when a value is set
1581        # to NaN. This is allowed behavior under GLES 3.0 section 2.1.1 or
1582        # OpenGL 4.5 section 2.3.4.1 - providing NaN allows undefined results.
1583        # Make this behavior consistent within Chromium, and avoid leaking GL
1584        # errors by generating the error in the command buffer instead of
1585        # letting the GL driver generate it.
1586        code.append("std::isnan(%s)" % args[ndx].name)
1587      if len(code):
1588        f.write("  if (%s) {\n" % " ||\n      ".join(code))
1589        f.write(
1590          '    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,'
1591          ' "%s", "%s out of range");\n' %
1592          (func.name, args[ndx].name))
1593        f.write("    return error::kNoError;\n")
1594        f.write("  }\n")
1595    code = []
1596    for ndx,item in enumerate(states):
1597      code.append("state_.%s != %s" % (item['name'], args[ndx].name))
1598    f.write("  if (%s) {\n" % " ||\n      ".join(code))
1599    for ndx,item in enumerate(states):
1600      f.write("    state_.%s = %s;\n" % (item['name'], args[ndx].name))
1601    if 'on_change' in state:
1602      f.write("    %s\n" % state['on_change'])
1603    if not func.GetInfo("no_gl"):
1604      for ndx,item in enumerate(states):
1605        if item.get('cached', False):
1606          f.write("    state_.%s = %s;\n" %
1607                     (CachedStateName(item), args[ndx].name))
1608      f.write("    %s(%s);\n" %
1609                 (func.GetGLFunctionName(), func.MakeOriginalArgString("")))
1610    f.write("  }\n")
1611
1612  def WriteServiceUnitTest(self, func, f, *extras):
1613    """Overrriden from TypeHandler."""
1614    TypeHandler.WriteServiceUnitTest(self, func, f, *extras)
1615    state_name = func.GetInfo('state')
1616    state = _STATE_INFO[state_name]
1617    states = state['states']
1618    for ndx,item in enumerate(states):
1619      if 'range_checks' in item:
1620        for check_ndx, range_check in enumerate(item['range_checks']):
1621          valid_test = """
1622TEST_P(%(test_name)s, %(name)sInvalidValue%(ndx)d_%(check_ndx)d) {
1623  SpecializedSetup<cmds::%(name)s, 0>(false);
1624  cmds::%(name)s cmd;
1625  cmd.Init(%(args)s);
1626  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
1627  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
1628}
1629"""
1630          name = func.name
1631          arg_strings = [
1632            arg.GetValidArg(func) \
1633            for arg in func.GetOriginalArgs() if not arg.IsConstant()
1634          ]
1635
1636          arg_strings[ndx] = range_check['test_value']
1637          varz = {
1638            'name': name,
1639            'ndx': ndx,
1640            'check_ndx': check_ndx,
1641            'args': ", ".join(arg_strings),
1642          }
1643          for extra in extras:
1644            varz.update(extra)
1645          f.write(valid_test % varz)
1646      if 'nan_check' in item:
1647        valid_test = """
1648TEST_P(%(test_name)s, %(name)sNaNValue%(ndx)d) {
1649  SpecializedSetup<cmds::%(name)s, 0>(false);
1650  cmds::%(name)s cmd;
1651  cmd.Init(%(args)s);
1652  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
1653  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
1654}
1655"""
1656        name = func.name
1657        arg_strings = [
1658          arg.GetValidArg(func) \
1659          for arg in func.GetOriginalArgs() if not arg.IsConstant()
1660        ]
1661
1662        arg_strings[ndx] = 'nanf("")'
1663        varz = {
1664          'name': name,
1665          'ndx': ndx,
1666          'args': ", ".join(arg_strings),
1667        }
1668        for extra in extras:
1669          varz.update(extra)
1670        f.write(valid_test % varz)
1671
1672  def WriteImmediateCmdInit(self, func, f):
1673    """Overrriden from TypeHandler."""
1674    pass
1675
1676  def WriteImmediateCmdSet(self, func, f):
1677    """Overrriden from TypeHandler."""
1678    pass
1679
1680
1681class StateSetRGBAlphaHandler(TypeHandler):
1682  """Handler for commands that simply set state that have rgb/alpha."""
1683
1684  def WriteHandlerImplementation(self, func, f):
1685    """Overrriden from TypeHandler."""
1686    state_name = func.GetInfo('state')
1687    state = _STATE_INFO[state_name]
1688    states = state['states']
1689    args = func.GetOriginalArgs()
1690    num_args = len(args)
1691    code = []
1692    for ndx,item in enumerate(states):
1693      code.append("state_.%s != %s" % (item['name'], args[ndx % num_args].name))
1694    f.write("  if (%s) {\n" % " ||\n      ".join(code))
1695    for ndx, item in enumerate(states):
1696      f.write("    state_.%s = %s;\n" %
1697                 (item['name'], args[ndx % num_args].name))
1698    if 'on_change' in state:
1699      f.write("    %s\n" % state['on_change'])
1700    if not func.GetInfo("no_gl"):
1701      f.write("    %s(%s);\n" %
1702                 (func.GetGLFunctionName(), func.MakeOriginalArgString("")))
1703      f.write("  }\n")
1704
1705  def WriteImmediateCmdInit(self, func, f):
1706    """Overrriden from TypeHandler."""
1707    pass
1708
1709  def WriteImmediateCmdSet(self, func, f):
1710    """Overrriden from TypeHandler."""
1711    pass
1712
1713
1714class StateSetFrontBackSeparateHandler(TypeHandler):
1715  """Handler for commands that simply set state that have front/back."""
1716
1717  def WriteHandlerImplementation(self, func, f):
1718    """Overrriden from TypeHandler."""
1719    state_name = func.GetInfo('state')
1720    state = _STATE_INFO[state_name]
1721    states = state['states']
1722    args = func.GetOriginalArgs()
1723    face = args[0].name
1724    num_args = len(args)
1725    f.write("  bool changed = false;\n")
1726    for group_ndx, group in enumerate(Grouper(num_args - 1, states)):
1727      f.write("  if (%s == %s || %s == GL_FRONT_AND_BACK) {\n" %
1728                 (face, ('GL_FRONT', 'GL_BACK')[group_ndx], face))
1729      code = []
1730      for ndx, item in enumerate(group):
1731        code.append("state_.%s != %s" % (item['name'], args[ndx + 1].name))
1732      f.write("    changed |= %s;\n" % " ||\n        ".join(code))
1733      f.write("  }\n")
1734    f.write("  if (changed) {\n")
1735    for group_ndx, group in enumerate(Grouper(num_args - 1, states)):
1736      f.write("    if (%s == %s || %s == GL_FRONT_AND_BACK) {\n" %
1737                 (face, ('GL_FRONT', 'GL_BACK')[group_ndx], face))
1738      for ndx, item in enumerate(group):
1739        f.write("      state_.%s = %s;\n" %
1740                   (item['name'], args[ndx + 1].name))
1741      f.write("    }\n")
1742    if 'on_change' in state:
1743      f.write("    %s\n" % state['on_change'])
1744    if not func.GetInfo("no_gl"):
1745      f.write("    %s(%s);\n" %
1746                 (func.GetGLFunctionName(), func.MakeOriginalArgString("")))
1747    f.write("  }\n")
1748
1749  def WriteImmediateCmdInit(self, func, f):
1750    """Overrriden from TypeHandler."""
1751    pass
1752
1753  def WriteImmediateCmdSet(self, func, f):
1754    """Overrriden from TypeHandler."""
1755    pass
1756
1757
1758class StateSetFrontBackHandler(TypeHandler):
1759  """Handler for commands that simply set state that set both front/back."""
1760
1761  def WriteHandlerImplementation(self, func, f):
1762    """Overrriden from TypeHandler."""
1763    state_name = func.GetInfo('state')
1764    state = _STATE_INFO[state_name]
1765    states = state['states']
1766    args = func.GetOriginalArgs()
1767    num_args = len(args)
1768    code = []
1769    for group in Grouper(num_args, states):
1770      for ndx, item in enumerate(group):
1771        code.append("state_.%s != %s" % (item['name'], args[ndx].name))
1772    f.write("  if (%s) {\n" % " ||\n      ".join(code))
1773    for group in Grouper(num_args, states):
1774      for ndx, item in enumerate(group):
1775        f.write("    state_.%s = %s;\n" % (item['name'], args[ndx].name))
1776    if 'on_change' in state:
1777      f.write("    %s\n" % state['on_change'])
1778    if not func.GetInfo("no_gl"):
1779      f.write("    %s(%s);\n" %
1780                 (func.GetGLFunctionName(), func.MakeOriginalArgString("")))
1781    f.write("  }\n")
1782
1783  def WriteImmediateCmdInit(self, func, f):
1784    """Overrriden from TypeHandler."""
1785    pass
1786
1787  def WriteImmediateCmdSet(self, func, f):
1788    """Overrriden from TypeHandler."""
1789    pass
1790
1791
1792class StateSetNamedParameter(TypeHandler):
1793  """Handler for commands that set a state chosen with an enum parameter."""
1794
1795  def WriteHandlerImplementation(self, func, f):
1796    """Overridden from TypeHandler."""
1797    state_name = func.GetInfo('state')
1798    state = _STATE_INFO[state_name]
1799    states = state['states']
1800    args = func.GetOriginalArgs()
1801    num_args = len(args)
1802    assert num_args == 2
1803    f.write("  switch (%s) {\n" % args[0].name)
1804    for state in states:
1805      f.write("    case %s:\n" % state['enum'])
1806      f.write("      if (state_.%s != %s) {\n" %
1807                 (state['name'], args[1].name))
1808      f.write("        state_.%s = %s;\n" % (state['name'], args[1].name))
1809      if not func.GetInfo("no_gl"):
1810        operation = "        %s(%s);\n" % \
1811                    (func.GetGLFunctionName(), func.MakeOriginalArgString(""))
1812        f.write(GuardState(state, operation, "feature_info_"))
1813      f.write("      }\n")
1814      f.write("      break;\n")
1815    f.write("    default:\n")
1816    f.write("      NOTREACHED();\n")
1817    f.write("  }\n")
1818
1819  def WriteImmediateCmdInit(self, func, f):
1820    """Overrriden from TypeHandler."""
1821    pass
1822
1823  def WriteImmediateCmdSet(self, func, f):
1824    """Overrriden from TypeHandler."""
1825    pass
1826
1827
1828class CustomHandler(TypeHandler):
1829  """Handler for commands that are auto-generated but require minor tweaks."""
1830
1831  def InitFunction(self, func):
1832    """Overrriden from TypeHandler."""
1833    if (func.name.startswith('CompressedTex') and func.name.endswith('Bucket')):
1834      # Remove imageSize argument, take the size from the bucket instead.
1835      func.cmd_args = [arg for arg in func.cmd_args if arg.name != 'imageSize']
1836      func.AddCmdArg(Argument('bucket_id', 'GLuint'))
1837    else:
1838      TypeHandler.InitFunction(self, func)
1839
1840  def WriteServiceImplementation(self, func, f):
1841    """Overrriden from TypeHandler."""
1842    if func.IsES31():
1843      TypeHandler.WriteServiceImplementation(self, func, f)
1844
1845  def WriteImmediateServiceImplementation(self, func, f):
1846    """Overrriden from TypeHandler."""
1847    if func.IsES31():
1848      TypeHandler.WriteImmediateServiceImplementation(self, func, f)
1849
1850  def WriteBucketServiceImplementation(self, func, f):
1851    """Overrriden from TypeHandler."""
1852    if func.IsES31():
1853      TypeHandler.WriteBucketServiceImplementation(self, func, f)
1854
1855  def WritePassthroughServiceImplementation(self, func, f):
1856    """Overrriden from TypeHandler."""
1857    pass
1858
1859  def WritePassthroughImmediateServiceImplementation(self, func, f):
1860    """Overrriden from TypeHandler."""
1861    pass
1862
1863  def WritePassthroughBucketServiceImplementation(self, func, f):
1864    """Overrriden from TypeHandler."""
1865    pass
1866
1867  def WriteServiceUnitTest(self, func, f, *extras):
1868    """Overrriden from TypeHandler."""
1869    pass
1870
1871  def WriteImmediateServiceUnitTest(self, func, f, *extras):
1872    """Overrriden from TypeHandler."""
1873    pass
1874
1875  def WriteImmediateCmdGetTotalSize(self, _func, f):
1876    """Overrriden from TypeHandler."""
1877    f.write(
1878        "    uint32_t total_size = 0;  // WARNING: compute correct size.\n")
1879
1880  def WriteImmediateCmdInit(self, func, f):
1881    """Overrriden from TypeHandler."""
1882    f.write("  void Init(%s) {\n" % func.MakeTypedCmdArgString("_"))
1883    self.WriteImmediateCmdGetTotalSize(func, f)
1884    f.write("    SetHeader(total_size);\n")
1885    args = func.GetCmdArgs()
1886    for arg in args:
1887      arg.WriteSetCode(f, 4, '_%s' % arg.name)
1888    f.write("  }\n")
1889    f.write("\n")
1890
1891  def WriteImmediateCmdSet(self, func, f):
1892    """Overrriden from TypeHandler."""
1893    copy_args = func.MakeCmdArgString("_", False)
1894    f.write("  void* Set(void* cmd%s) {\n" %
1895               func.MakeTypedCmdArgString("_", True))
1896    self.WriteImmediateCmdGetTotalSize(func, f)
1897    f.write("    static_cast<ValueType*>(cmd)->Init(%s);\n" % copy_args)
1898    f.write("    return NextImmediateCmdAddressTotalSize<ValueType>("
1899               "cmd, total_size);\n")
1900    f.write("  }\n")
1901    f.write("\n")
1902
1903
1904class NoCommandHandler(CustomHandler):
1905  """Handler for functions that don't use commands"""
1906
1907  def WriteGLES2Implementation(self, func, f):
1908    pass
1909
1910  def WriteGLES2ImplementationUnitTest(self, func, f):
1911    pass
1912
1913
1914class DataHandler(TypeHandler):
1915  """
1916  Handler for glBufferData, glBufferSubData, glTex{Sub}Image*D.
1917  """
1918
1919  def WriteGetDataSizeCode(self, func, arg, f):
1920    """Overrriden from TypeHandler."""
1921    # TODO: Move this data to _FUNCTION_INFO?
1922    name = func.name
1923    if name.endswith("Immediate"):
1924      name = name[0:-9]
1925    if arg.name in func.size_args:
1926      size = func.size_args[arg.name]
1927      f.write("  uint32_t %s = %s;\n" % (arg.GetReservedSizeId(), size))
1928    else:
1929      f.write("// uint32_t %s = 0;  // WARNING: compute correct size.\n" % (
1930              arg.GetReservedSizeId()))
1931
1932  def WriteImmediateCmdGetTotalSize(self, func, f):
1933    """Overrriden from TypeHandler."""
1934    pass
1935
1936  def WriteImmediateCmdInit(self, func, f):
1937    """Overrriden from TypeHandler."""
1938    f.write("  void Init(%s) {\n" % func.MakeTypedCmdArgString("_"))
1939    self.WriteImmediateCmdGetTotalSize(func, f)
1940    f.write("    SetHeader(total_size);\n")
1941    args = func.GetCmdArgs()
1942    for arg in args:
1943      f.write("    %s = _%s;\n" % (arg.name, arg.name))
1944    f.write("  }\n")
1945    f.write("\n")
1946
1947  def WriteImmediateCmdSet(self, func, f):
1948    """Overrriden from TypeHandler."""
1949    copy_args = func.MakeCmdArgString("_", False)
1950    f.write("  void* Set(void* cmd%s) {\n" %
1951               func.MakeTypedCmdArgString("_", True))
1952    self.WriteImmediateCmdGetTotalSize(func, f)
1953    f.write("    static_cast<ValueType*>(cmd)->Init(%s);\n" % copy_args)
1954    f.write("    return NextImmediateCmdAddressTotalSize<ValueType>("
1955               "cmd, total_size);\n")
1956    f.write("  }\n")
1957    f.write("\n")
1958
1959  def WriteImmediateFormatTest(self, func, f):
1960    """Overrriden from TypeHandler."""
1961    # TODO: Remove this exception.
1962    return
1963
1964  def WriteServiceUnitTest(self, func, f, *extras):
1965    """Overrriden from TypeHandler."""
1966    pass
1967
1968  def WriteImmediateServiceUnitTest(self, func, f, *extras):
1969    """Overrriden from TypeHandler."""
1970    pass
1971
1972  def WriteImmediateCmdInit(self, func, f):
1973    """Overrriden from TypeHandler."""
1974    pass
1975
1976  def WriteImmediateCmdSet(self, func, f):
1977    """Overrriden from TypeHandler."""
1978    pass
1979
1980
1981class BindHandler(TypeHandler):
1982  """Handler for glBind___ type functions."""
1983
1984  def WriteServiceUnitTest(self, func, f, *extras):
1985    """Overrriden from TypeHandler."""
1986
1987    if len(func.GetOriginalArgs()) == 1:
1988      valid_test = """
1989TEST_P(%(test_name)s, %(name)sValidArgs) {
1990  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s));
1991  SpecializedSetup<cmds::%(name)s, 0>(true);
1992  cmds::%(name)s cmd;
1993  cmd.Init(%(args)s);
1994  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
1995  EXPECT_EQ(GL_NO_ERROR, GetGLError());
1996}
1997"""
1998      if func.GetInfo("gen_func"):
1999          valid_test += """
2000TEST_P(%(test_name)s, %(name)sValidArgsNewId) {
2001  EXPECT_CALL(*gl_, %(gl_func_name)s(kNewServiceId));
2002  EXPECT_CALL(*gl_, %(gl_gen_func_name)s(1, _))
2003     .WillOnce(SetArgPointee<1>(kNewServiceId));
2004  SpecializedSetup<cmds::%(name)s, 0>(true);
2005  cmds::%(name)s cmd;
2006  cmd.Init(kNewClientId);
2007  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
2008  EXPECT_EQ(GL_NO_ERROR, GetGLError());
2009  EXPECT_TRUE(Get%(resource_type)s(kNewClientId) != nullptr);
2010}
2011"""
2012      self.WriteValidUnitTest(func, f, valid_test, {
2013          'resource_type': func.GetOriginalArgs()[0].resource_type,
2014          'gl_gen_func_name': func.GetInfo("gen_func"),
2015      }, *extras)
2016    else:
2017      valid_test = """
2018TEST_P(%(test_name)s, %(name)sValidArgs) {
2019  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s));
2020  SpecializedSetup<cmds::%(name)s, 0>(true);
2021  cmds::%(name)s cmd;
2022  cmd.Init(%(args)s);
2023  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
2024  EXPECT_EQ(GL_NO_ERROR, GetGLError());
2025}
2026"""
2027      if func.GetInfo("gen_func"):
2028        valid_test += """
2029TEST_P(%(test_name)s, %(name)sValidArgsNewId) {
2030  EXPECT_CALL(*gl_,
2031              %(gl_func_name)s(%(gl_args_with_new_id)s));
2032  EXPECT_CALL(*gl_, %(gl_gen_func_name)s(1, _))
2033     .WillOnce(SetArgPointee<1>(kNewServiceId));
2034  SpecializedSetup<cmds::%(name)s, 0>(true);
2035  cmds::%(name)s cmd;
2036  cmd.Init(%(args_with_new_id)s);
2037  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
2038  EXPECT_EQ(GL_NO_ERROR, GetGLError());
2039  EXPECT_TRUE(Get%(resource_type)s(kNewClientId) != nullptr);
2040}
2041"""
2042
2043      gl_args_with_new_id = []
2044      args_with_new_id = []
2045      for arg in func.GetOriginalArgs():
2046        if hasattr(arg, 'resource_type'):
2047          gl_args_with_new_id.append('kNewServiceId')
2048          args_with_new_id.append('kNewClientId')
2049        else:
2050          gl_args_with_new_id.append(arg.GetValidGLArg(func))
2051          args_with_new_id.append(arg.GetValidArg(func))
2052      self.WriteValidUnitTest(func, f, valid_test, {
2053          'args_with_new_id': ", ".join(args_with_new_id),
2054          'gl_args_with_new_id': ", ".join(gl_args_with_new_id),
2055          'resource_type': func.GetResourceIdArg().resource_type,
2056          'gl_gen_func_name': func.GetInfo("gen_func"),
2057      }, *extras)
2058
2059    invalid_test = """
2060TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
2061  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)).Times(0);
2062  SpecializedSetup<cmds::%(name)s, 0>(false);
2063  cmds::%(name)s cmd;
2064  cmd.Init(%(args)s);
2065  EXPECT_EQ(error::%(parse_result)s, ExecuteCmd(cmd));%(gl_error_test)s
2066}
2067"""
2068    self.WriteInvalidUnitTest(func, f, invalid_test, *extras)
2069
2070  def WriteGLES2Implementation(self, func, f):
2071    """Writes the GLES2 Implemention."""
2072
2073    impl_func = func.GetInfo('impl_func', True)
2074    if func.can_auto_generate and impl_func:
2075      f.write("%s %sImplementation::%s(%s) {\n" %
2076                 (func.return_type, _prefix, func.original_name,
2077                  func.MakeTypedOriginalArgString("")))
2078      f.write("  GPU_CLIENT_SINGLE_THREAD_CHECK();\n")
2079      func.WriteDestinationInitalizationValidation(f)
2080      self.WriteClientGLCallLog(func, f)
2081      for arg in func.GetOriginalArgs():
2082        arg.WriteClientSideValidationCode(f, func)
2083
2084      code = """  if (Is%(type)sReservedId(%(id)s)) {
2085    SetGLError(GL_INVALID_OPERATION, "%(name)s\", \"%(id)s reserved id");
2086    return;
2087  }
2088  %(name)sHelper(%(arg_string)s);
2089  CheckGLError();
2090}
2091
2092"""
2093      name_arg = func.GetResourceIdArg()
2094      f.write(code % {
2095          'name': func.name,
2096          'arg_string': func.MakeOriginalArgString(""),
2097          'id': name_arg.name,
2098          'type': name_arg.resource_type,
2099          'lc_type': name_arg.resource_type.lower(),
2100        })
2101
2102  def WriteGLES2ImplementationUnitTest(self, func, f):
2103    """Overrriden from TypeHandler."""
2104    client_test = func.GetInfo('client_test', True)
2105    if not client_test:
2106      return
2107    code = """
2108TEST_F(%(prefix)sImplementationTest, %(name)s) {
2109  struct Cmds {
2110    cmds::%(name)s cmd;
2111  };
2112  Cmds expected;
2113  expected.cmd.Init(%(cmd_args)s);
2114
2115  gl_->%(name)s(%(args)s);
2116  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));"""
2117    if not func.IsES3():
2118      code += """
2119  ClearCommands();
2120  gl_->%(name)s(%(args)s);
2121  EXPECT_TRUE(NoCommandsWritten());"""
2122    code += """
2123}
2124"""
2125    cmd_arg_strings = [
2126      arg.GetValidClientSideCmdArg(func) for arg in func.GetCmdArgs()
2127    ]
2128    gl_arg_strings = [
2129      arg.GetValidClientSideArg(func) for arg in func.GetOriginalArgs()
2130    ]
2131
2132    f.write(code % {
2133          'prefix' : _prefix,
2134          'name': func.name,
2135          'args': ", ".join(gl_arg_strings),
2136          'cmd_args': ", ".join(cmd_arg_strings),
2137        })
2138
2139  def WriteImmediateCmdInit(self, func, f):
2140    """Overrriden from TypeHandler."""
2141    pass
2142
2143  def WriteImmediateCmdSet(self, func, f):
2144    """Overrriden from TypeHandler."""
2145    pass
2146
2147
2148class GENnHandler(TypeHandler):
2149  """Handler for glGen___ type functions."""
2150
2151  def InitFunction(self, func):
2152    """Overrriden from TypeHandler."""
2153    pass
2154
2155  def WriteGetDataSizeCode(self, func, arg, f):
2156    """Overrriden from TypeHandler."""
2157    code = """  uint32_t %(data_size)s;
2158  if (!base::CheckMul(n, sizeof(GLuint)).AssignIfValid(&%(data_size)s)) {
2159    return error::kOutOfBounds;
2160  }
2161""" % {'data_size': arg.GetReservedSizeId()}
2162    f.write(code)
2163
2164  def WriteHandlerImplementation (self, func, f):
2165    """Overrriden from TypeHandler."""
2166    raise NotImplementedError("GENn functions are immediate")
2167
2168  def WriteImmediateHandlerImplementation(self, func, f):
2169    """Overrriden from TypeHandler."""
2170    param_name = func.GetLastOriginalArg().name
2171    f.write("  auto %(name)s_copy = std::make_unique<GLuint[]>(n);\n"
2172            "  GLuint* %(name)s_safe = %(name)s_copy.get();\n"
2173            "  std::copy(%(name)s, %(name)s + n, %(name)s_safe);\n"
2174            "  if (!%(ns)sCheckUniqueAndNonNullIds(n, %(name)s_safe) ||\n"
2175            "      !%(func)sHelper(n, %(name)s_safe)) {\n"
2176            "    return error::kInvalidArguments;\n"
2177            "  }\n" % {'name': param_name,
2178                       'func': func.original_name,
2179                       'ns': _Namespace()})
2180
2181  def WriteGLES2Implementation(self, func, f):
2182    """Overrriden from TypeHandler."""
2183    log_code = ("""  GPU_CLIENT_LOG_CODE_BLOCK({
2184    for (GLsizei i = 0; i < n; ++i) {
2185      GPU_CLIENT_LOG("  " << i << ": " << %s[i]);
2186    }
2187  });""" % func.GetOriginalArgs()[1].name)
2188    args = {
2189        'log_code': log_code,
2190        'return_type': func.return_type,
2191        'prefix' : _prefix,
2192        'name': func.original_name,
2193        'typed_args': func.MakeTypedOriginalArgString(""),
2194        'args': func.MakeOriginalArgString(""),
2195        'resource_types': func.GetInfo('resource_types'),
2196        'count_name': func.GetOriginalArgs()[0].name,
2197      }
2198    f.write(
2199        "%(return_type)s %(prefix)sImplementation::"
2200        "%(name)s(%(typed_args)s) {\n" %
2201        args)
2202    func.WriteDestinationInitalizationValidation(f)
2203    self.WriteClientGLCallLog(func, f)
2204    for arg in func.GetOriginalArgs():
2205      arg.WriteClientSideValidationCode(f, func)
2206    not_shared = func.GetInfo('not_shared')
2207    if not_shared:
2208      alloc_code = ("""\
2209      IdAllocator* id_allocator = GetIdAllocator(IdNamespaces::k%s);
2210      for (GLsizei ii = 0; ii < n; ++ii)
2211      %s[ii] = id_allocator->AllocateID();""" %
2212      (func.GetInfo('resource_types'), func.GetOriginalArgs()[1].name))
2213    else:
2214      alloc_code = ("""\
2215      GetIdHandler(SharedIdNamespaces::k%(resource_types)s)->
2216      MakeIds(this, 0, %(args)s);""" % args)
2217    args['alloc_code'] = alloc_code
2218
2219    code = """\
2220    GPU_CLIENT_SINGLE_THREAD_CHECK();
2221    %(alloc_code)s
2222    %(name)sHelper(%(args)s);
2223    helper_->%(name)sImmediate(%(args)s);
2224    """
2225    if not not_shared:
2226      code += """\
2227      if (share_group_->bind_generates_resource())
2228      helper_->CommandBufferHelper::Flush();
2229      """
2230    code += """\
2231    %(log_code)s
2232    CheckGLError();
2233    }
2234
2235    """
2236    f.write(code % args)
2237
2238  def WriteGLES2ImplementationUnitTest(self, func, f):
2239    """Overrriden from TypeHandler."""
2240    code = """
2241TEST_F(%(prefix)sImplementationTest, %(name)s) {
2242  GLuint ids[2] = { 0, };
2243  struct Cmds {
2244    cmds::%(name)sImmediate gen;
2245    GLuint data[2];
2246  };
2247  Cmds expected;
2248  expected.gen.Init(base::size(ids), &ids[0]);
2249  expected.data[0] = k%(types)sStartId;
2250  expected.data[1] = k%(types)sStartId + 1;
2251  gl_->%(name)s(base::size(ids), &ids[0]);
2252  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2253  EXPECT_EQ(k%(types)sStartId, ids[0]);
2254  EXPECT_EQ(k%(types)sStartId + 1, ids[1]);
2255}
2256"""
2257    f.write(code % {
2258          'prefix' : _prefix,
2259          'name': func.name,
2260          'types': func.GetInfo('resource_types'),
2261        })
2262
2263  def WriteServiceUnitTest(self, func, f, *extras):
2264    """Overrriden from TypeHandler."""
2265    raise NotImplementedError("GENn functions are immediate")
2266
2267  def WriteImmediateServiceUnitTest(self, func, f, *extras):
2268    """Overrriden from TypeHandler."""
2269    valid_test = """
2270TEST_P(%(test_name)s, %(name)sValidArgs) {
2271  EXPECT_CALL(*gl_, %(gl_func_name)s(1, _))
2272      .WillOnce(SetArgPointee<1>(kNewServiceId));
2273  cmds::%(name)s* cmd = GetImmediateAs<cmds::%(name)s>();
2274  GLuint temp = kNewClientId;
2275  SpecializedSetup<cmds::%(name)s, 0>(true);
2276  cmd->Init(1, &temp);
2277  EXPECT_EQ(error::kNoError,
2278            ExecuteImmediateCmd(*cmd, sizeof(temp)));
2279  EXPECT_EQ(GL_NO_ERROR, GetGLError());
2280  EXPECT_TRUE(Get%(resource_name)s(kNewClientId) != nullptr);
2281}
2282"""
2283    self.WriteValidUnitTest(func, f, valid_test, {
2284        'resource_name': func.GetInfo('resource_type'),
2285      }, *extras)
2286    duplicate_id_test = """
2287TEST_P(%(test_name)s, %(name)sDuplicateOrNullIds) {
2288  EXPECT_CALL(*gl_, %(gl_func_name)s(_, _)).Times(0);
2289  cmds::%(name)s* cmd = GetImmediateAs<cmds::%(name)s>();
2290  GLuint temp[3] = {kNewClientId, kNewClientId + 1, kNewClientId};
2291  SpecializedSetup<cmds::%(name)s, 1>(true);
2292  cmd->Init(3, temp);
2293  EXPECT_EQ(error::kInvalidArguments,
2294            ExecuteImmediateCmd(*cmd, sizeof(temp)));
2295  EXPECT_TRUE(Get%(resource_name)s(kNewClientId) == nullptr);
2296  EXPECT_TRUE(Get%(resource_name)s(kNewClientId + 1) == nullptr);
2297  GLuint null_id[2] = {kNewClientId, 0};
2298  cmd->Init(2, null_id);
2299  EXPECT_EQ(error::kInvalidArguments,
2300            ExecuteImmediateCmd(*cmd, sizeof(temp)));
2301  EXPECT_TRUE(Get%(resource_name)s(kNewClientId) == nullptr);
2302}
2303    """
2304    self.WriteValidUnitTest(func, f, duplicate_id_test, {
2305        'resource_name': func.GetInfo('resource_type'),
2306      }, *extras)
2307    invalid_test = """
2308TEST_P(%(test_name)s, %(name)sInvalidArgs) {
2309  EXPECT_CALL(*gl_, %(gl_func_name)s(_, _)).Times(0);
2310  cmds::%(name)s* cmd = GetImmediateAs<cmds::%(name)s>();
2311  SpecializedSetup<cmds::%(name)s, 0>(false);
2312  cmd->Init(1, &client_%(resource_name)s_id_);
2313  EXPECT_EQ(error::kInvalidArguments,
2314            ExecuteImmediateCmd(*cmd, sizeof(&client_%(resource_name)s_id_)));
2315}
2316"""
2317    self.WriteValidUnitTest(func, f, invalid_test, {
2318          'resource_name': func.GetInfo('resource_type').lower(),
2319        }, *extras)
2320
2321  def WriteImmediateCmdComputeSize(self, _func, f):
2322    """Overrriden from TypeHandler."""
2323    f.write("  static uint32_t ComputeDataSize(GLsizei _n) {\n")
2324    f.write(
2325        "    return static_cast<uint32_t>(sizeof(GLuint) * _n);  // NOLINT\n")
2326    f.write("  }\n")
2327    f.write("\n")
2328    f.write("  static uint32_t ComputeSize(GLsizei _n) {\n")
2329    f.write("    return static_cast<uint32_t>(\n")
2330    f.write("        sizeof(ValueType) + ComputeDataSize(_n));  // NOLINT\n")
2331    f.write("  }\n")
2332    f.write("\n")
2333
2334  def WriteImmediateCmdSetHeader(self, _func, f):
2335    """Overrriden from TypeHandler."""
2336    f.write("  void SetHeader(GLsizei _n) {\n")
2337    f.write("    header.SetCmdByTotalSize<ValueType>(ComputeSize(_n));\n")
2338    f.write("  }\n")
2339    f.write("\n")
2340
2341  def WriteImmediateCmdInit(self, func, f):
2342    """Overrriden from TypeHandler."""
2343    last_arg = func.GetLastOriginalArg()
2344    f.write("  void Init(%s, %s _%s) {\n" %
2345               (func.MakeTypedCmdArgString("_"),
2346                last_arg.type, last_arg.name))
2347    f.write("    SetHeader(_n);\n")
2348    args = func.GetCmdArgs()
2349    for arg in args:
2350      f.write("    %s = _%s;\n" % (arg.name, arg.name))
2351    f.write("    memcpy(ImmediateDataAddress(this),\n")
2352    f.write("           _%s, ComputeDataSize(_n));\n" % last_arg.name)
2353    f.write("  }\n")
2354    f.write("\n")
2355
2356  def WriteImmediateCmdSet(self, func, f):
2357    """Overrriden from TypeHandler."""
2358    last_arg = func.GetLastOriginalArg()
2359    copy_args = func.MakeCmdArgString("_", False)
2360    f.write("  void* Set(void* cmd%s, %s _%s) {\n" %
2361               (func.MakeTypedCmdArgString("_", True),
2362                last_arg.type, last_arg.name))
2363    f.write("    static_cast<ValueType*>(cmd)->Init(%s, _%s);\n" %
2364               (copy_args, last_arg.name))
2365    f.write("    const uint32_t size = ComputeSize(_n);\n")
2366    f.write("    return NextImmediateCmdAddressTotalSize<ValueType>("
2367               "cmd, size);\n")
2368    f.write("  }\n")
2369    f.write("\n")
2370
2371  def WriteImmediateCmdHelper(self, func, f):
2372    """Overrriden from TypeHandler."""
2373    code = """  void %(name)s(%(typed_args)s) {
2374    const uint32_t size = %(lp)s::cmds::%(name)s::ComputeSize(n);
2375    %(lp)s::cmds::%(name)s* c =
2376        GetImmediateCmdSpaceTotalSize<%(lp)s::cmds::%(name)s>(size);
2377    if (c) {
2378      c->Init(%(args)s);
2379    }
2380  }
2381
2382"""
2383    f.write(code % {
2384          "lp" : _lower_prefix,
2385          "name": func.name,
2386          "typed_args": func.MakeTypedOriginalArgString(""),
2387          "args": func.MakeOriginalArgString(""),
2388        })
2389
2390  def WriteImmediateFormatTest(self, func, f):
2391    """Overrriden from TypeHandler."""
2392    f.write("TEST_F(%sFormatTest, %s) {\n" % (_prefix, func.name))
2393    f.write("  static GLuint ids[] = { 12, 23, 34, };\n")
2394    f.write("  cmds::%s& cmd = *GetBufferAs<cmds::%s>();\n" %
2395               (func.name, func.name))
2396    f.write("  void* next_cmd = cmd.Set(\n")
2397    f.write("      &cmd, static_cast<GLsizei>(base::size(ids)), ids);\n")
2398    f.write("  EXPECT_EQ(static_cast<uint32_t>(cmds::%s::kCmdId),\n" %
2399               func.name)
2400    f.write("            cmd.header.command);\n")
2401    f.write("  EXPECT_EQ(sizeof(cmd) +\n")
2402    f.write("            RoundSizeToMultipleOfEntries(cmd.n * 4u),\n")
2403    f.write("            cmd.header.size * 4u);\n")
2404    f.write("  EXPECT_EQ(static_cast<GLsizei>(base::size(ids)), cmd.n);\n");
2405    f.write("  CheckBytesWrittenMatchesExpectedSize(\n")
2406    f.write("      next_cmd, sizeof(cmd) +\n")
2407    f.write("      RoundSizeToMultipleOfEntries(base::size(ids) * 4u));\n")
2408    f.write("  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd),\n")
2409    f.write("                      sizeof(ids)));\n")
2410    f.write("}\n")
2411    f.write("\n")
2412
2413
2414class CreateHandler(TypeHandler):
2415  """Handler for glCreate___ type functions."""
2416
2417  def InitFunction(self, func):
2418    """Overrriden from TypeHandler."""
2419    func.AddCmdArg(Argument("client_id", 'uint32_t'))
2420
2421  def __GetResourceType(self, func):
2422    if func.return_type == "GLsync":
2423      return "Sync"
2424    else:
2425      return func.name[6:]  # Create*
2426
2427  def WriteServiceUnitTest(self, func, f, *extras):
2428    """Overrriden from TypeHandler."""
2429    valid_test = """
2430TEST_P(%(test_name)s, %(name)sValidArgs) {
2431  %(id_type_cast)sEXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s))
2432      .WillOnce(Return(%(const_service_id)s));
2433  SpecializedSetup<cmds::%(name)s, 0>(true);
2434  cmds::%(name)s cmd;
2435  cmd.Init(%(args)s%(comma)skNewClientId);
2436  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
2437  EXPECT_EQ(GL_NO_ERROR, GetGLError());"""
2438    if func.IsES3():
2439      valid_test += """
2440  %(return_type)s service_id = 0;
2441  EXPECT_TRUE(Get%(resource_type)sServiceId(kNewClientId, &service_id));
2442  EXPECT_EQ(%(const_service_id)s, service_id);
2443}
2444"""
2445    else:
2446      valid_test += """
2447  EXPECT_TRUE(Get%(resource_type)s(kNewClientId));
2448}
2449"""
2450    comma = ""
2451    cmd_arg_count = 0
2452    for arg in func.GetOriginalArgs():
2453      if not arg.IsConstant():
2454        cmd_arg_count += 1
2455    if cmd_arg_count:
2456      comma = ", "
2457    if func.return_type == 'GLsync':
2458      id_type_cast = ("const GLsync kNewServiceIdGLuint = reinterpret_cast"
2459                      "<GLsync>(kNewServiceId);\n  ")
2460      const_service_id = "kNewServiceIdGLuint"
2461    else:
2462      id_type_cast = ""
2463      const_service_id = "kNewServiceId"
2464    self.WriteValidUnitTest(func, f, valid_test, {
2465          'comma': comma,
2466          'resource_type': self.__GetResourceType(func),
2467          'return_type': func.return_type,
2468          'id_type_cast': id_type_cast,
2469          'const_service_id': const_service_id,
2470        }, *extras)
2471    invalid_test = """
2472TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
2473  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)).Times(0);
2474  SpecializedSetup<cmds::%(name)s, 0>(false);
2475  cmds::%(name)s cmd;
2476  cmd.Init(%(args)s%(comma)skNewClientId);
2477  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));%(gl_error_test)s
2478}
2479"""
2480    self.WriteInvalidUnitTest(func, f, invalid_test, {
2481          'comma': comma,
2482        }, *extras)
2483
2484  def WriteHandlerImplementation (self, func, f):
2485    """Overrriden from TypeHandler."""
2486    if func.IsES3():
2487      code = """  uint32_t client_id = c.client_id;
2488  %(return_type)s service_id = 0;
2489  if (group_->Get%(resource_name)sServiceId(client_id, &service_id)) {
2490    return error::kInvalidArguments;
2491  }
2492  service_id = %(gl_func_name)s(%(gl_args)s);
2493  if (service_id) {
2494    group_->Add%(resource_name)sId(client_id, service_id);
2495  }
2496"""
2497    else:
2498      code = """  uint32_t client_id = c.client_id;
2499  if (Get%(resource_name)s(client_id)) {
2500    return error::kInvalidArguments;
2501  }
2502  %(return_type)s service_id = %(gl_func_name)s(%(gl_args)s);
2503  if (service_id) {
2504    Create%(resource_name)s(client_id, service_id%(gl_args_with_comma)s);
2505  }
2506"""
2507    f.write(code % {
2508        'resource_name': self.__GetResourceType(func),
2509        'return_type': func.return_type,
2510        'gl_func_name': func.GetGLFunctionName(),
2511        'gl_args': func.MakeOriginalArgString(""),
2512        'gl_args_with_comma': func.MakeOriginalArgString("", True) })
2513
2514  def WriteGLES2Implementation(self, func, f):
2515    """Overrriden from TypeHandler."""
2516    f.write("%s %sImplementation::%s(%s) {\n" %
2517               (func.return_type, _prefix, func.original_name,
2518                func.MakeTypedOriginalArgString("")))
2519    f.write("  GPU_CLIENT_SINGLE_THREAD_CHECK();\n")
2520    func.WriteDestinationInitalizationValidation(f)
2521    self.WriteClientGLCallLog(func, f)
2522    for arg in func.GetOriginalArgs():
2523      arg.WriteClientSideValidationCode(f, func)
2524    f.write("  GLuint client_id;\n")
2525    not_shared = func.GetInfo('not_shared')
2526    if not_shared:
2527      f.write('IdAllocator* id_allocator = GetIdAllocator(IdNamespaces::k%s);' %
2528              func.GetInfo('resource_types'))
2529      f.write('client_id = id_allocator->AllocateID();')
2530    else:
2531      if func.return_type == "GLsync":
2532        f.write(
2533            "  GetIdHandler(SharedIdNamespaces::kSyncs)->\n")
2534      else:
2535        f.write(
2536            "  GetIdHandler(SharedIdNamespaces::kProgramsAndShaders)->\n")
2537      f.write("      MakeIds(this, 0, 1, &client_id);\n")
2538    f.write("  helper_->%s(%s);\n" %
2539               (func.name, func.MakeCmdArgString("")))
2540    f.write('  GPU_CLIENT_LOG("returned " << client_id);\n')
2541    f.write("  CheckGLError();\n")
2542    if func.return_type == "GLsync":
2543      f.write("  return reinterpret_cast<GLsync>(client_id);\n")
2544    else:
2545      f.write("  return client_id;\n")
2546    f.write("}\n")
2547    f.write("\n")
2548
2549  def WritePassthroughServiceImplementation(self, func, f):
2550    """Overrriden from TypeHandler."""
2551    pass
2552
2553  def WriteImmediateCmdInit(self, func, f):
2554    """Overrriden from TypeHandler."""
2555    pass
2556
2557  def WriteImmediateCmdSet(self, func, f):
2558    """Overrriden from TypeHandler."""
2559    pass
2560
2561
2562class DeleteHandler(TypeHandler):
2563  """Handler for glDelete___ single resource type functions."""
2564
2565  def WriteServiceImplementation(self, func, f):
2566    """Overrriden from TypeHandler."""
2567    if func.IsES3() or func.IsES31():
2568      TypeHandler.WriteServiceImplementation(self, func, f)
2569    # HandleDeleteShader and HandleDeleteProgram are manually written.
2570
2571  def WriteGLES2Implementation(self, func, f):
2572    """Overrriden from TypeHandler."""
2573    f.write("%s %sImplementation::%s(%s) {\n" %
2574               (func.return_type, _prefix, func.original_name,
2575                func.MakeTypedOriginalArgString("")))
2576    f.write("  GPU_CLIENT_SINGLE_THREAD_CHECK();\n")
2577    func.WriteDestinationInitalizationValidation(f)
2578    self.WriteClientGLCallLog(func, f)
2579    for arg in func.GetOriginalArgs():
2580      arg.WriteClientSideValidationCode(f, func)
2581    f.write(
2582        "  if (%s == 0)\n    return;" % func.GetOriginalArgs()[-1].name);
2583    f.write("  %sHelper(%s);\n" %
2584               (func.original_name, func.GetOriginalArgs()[-1].name))
2585    f.write("  CheckGLError();\n")
2586    f.write("}\n")
2587    f.write("\n")
2588
2589  def WriteHandlerImplementation (self, func, f):
2590    """Overrriden from TypeHandler."""
2591    assert len(func.GetOriginalArgs()) == 1
2592    arg = func.GetOriginalArgs()[0]
2593    f.write("  %sHelper(%s);\n" % (func.original_name, arg.name))
2594
2595  def WriteImmediateCmdInit(self, func, f):
2596    """Overrriden from TypeHandler."""
2597    pass
2598
2599  def WriteImmediateCmdSet(self, func, f):
2600    """Overrriden from TypeHandler."""
2601    pass
2602
2603
2604class DELnHandler(TypeHandler):
2605  """Handler for glDelete___ type functions."""
2606
2607  def WriteGetDataSizeCode(self, func, arg, f):
2608    """Overrriden from TypeHandler."""
2609    code = """  uint32_t %(data_size)s;
2610  if (!base::CheckMul(n, sizeof(GLuint)).AssignIfValid(&%(data_size)s)) {
2611    return error::kOutOfBounds;
2612  }
2613""" % {'data_size': arg.GetReservedSizeId()}
2614    f.write(code)
2615
2616  def WriteGLES2ImplementationUnitTest(self, func, f):
2617    """Overrriden from TypeHandler."""
2618    code = """
2619TEST_F(%(prefix)sImplementationTest, %(name)s) {
2620  GLuint ids[2] = { k%(types)sStartId, k%(types)sStartId + 1 };
2621  struct Cmds {
2622    cmds::%(name)sImmediate del;
2623    GLuint data[2];
2624  };
2625  Cmds expected;
2626  expected.del.Init(base::size(ids), &ids[0]);
2627  expected.data[0] = k%(types)sStartId;
2628  expected.data[1] = k%(types)sStartId + 1;
2629  gl_->%(name)s(base::size(ids), &ids[0]);
2630  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2631}
2632"""
2633    f.write(code % {
2634          'prefix' : _prefix,
2635          'name': func.name,
2636          'types': func.GetInfo('resource_types'),
2637        })
2638
2639  def WriteServiceUnitTest(self, func, f, *extras):
2640    """Overrriden from TypeHandler."""
2641    valid_test = """
2642TEST_P(%(test_name)s, %(name)sValidArgs) {
2643  EXPECT_CALL(
2644      *gl_,
2645      %(gl_func_name)s(1, Pointee(kService%(upper_resource_name)sId)))
2646      .Times(1);
2647  GetSharedMemoryAs<GLuint*>()[0] = client_%(resource_name)s_id_;
2648  SpecializedSetup<cmds::%(name)s, 0>(true);
2649  cmds::%(name)s cmd;
2650  cmd.Init(%(args)s);
2651  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
2652  EXPECT_EQ(GL_NO_ERROR, GetGLError());
2653  EXPECT_TRUE(
2654      Get%(upper_resource_name)s(client_%(resource_name)s_id_) == nullptr);
2655}
2656"""
2657    self.WriteValidUnitTest(func, f, valid_test, {
2658          'resource_name': func.GetInfo('resource_type').lower(),
2659          'upper_resource_name': func.GetInfo('resource_type'),
2660        }, *extras)
2661    invalid_test = """
2662TEST_P(%(test_name)s, %(name)sInvalidArgs) {
2663  GetSharedMemoryAs<GLuint*>()[0] = kInvalidClientId;
2664  SpecializedSetup<cmds::%(name)s, 0>(false);
2665  cmds::%(name)s cmd;
2666  cmd.Init(%(args)s);
2667  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
2668}
2669"""
2670    self.WriteValidUnitTest(func, f, invalid_test, *extras)
2671
2672  def WriteImmediateServiceUnitTest(self, func, f, *extras):
2673    """Overrriden from TypeHandler."""
2674    valid_test = """
2675TEST_P(%(test_name)s, %(name)sValidArgs) {
2676  EXPECT_CALL(
2677      *gl_,
2678      %(gl_func_name)s(1, Pointee(kService%(upper_resource_name)sId)))
2679      .Times(1);
2680  cmds::%(name)s& cmd = *GetImmediateAs<cmds::%(name)s>();
2681  SpecializedSetup<cmds::%(name)s, 0>(true);
2682  cmd.Init(1, &client_%(resource_name)s_id_);
2683  EXPECT_EQ(error::kNoError,
2684            ExecuteImmediateCmd(cmd, sizeof(client_%(resource_name)s_id_)));
2685  EXPECT_EQ(GL_NO_ERROR, GetGLError());
2686  EXPECT_TRUE(
2687      Get%(upper_resource_name)s(client_%(resource_name)s_id_) == nullptr);
2688}
2689"""
2690    self.WriteValidUnitTest(func, f, valid_test, {
2691          'resource_name': func.GetInfo('resource_type').lower(),
2692          'upper_resource_name': func.GetInfo('resource_type'),
2693        }, *extras)
2694    invalid_test = """
2695TEST_P(%(test_name)s, %(name)sInvalidArgs) {
2696  cmds::%(name)s& cmd = *GetImmediateAs<cmds::%(name)s>();
2697  SpecializedSetup<cmds::%(name)s, 0>(false);
2698  GLuint temp = kInvalidClientId;
2699  cmd.Init(1, &temp);
2700  EXPECT_EQ(error::kNoError,
2701            ExecuteImmediateCmd(cmd, sizeof(temp)));
2702}
2703"""
2704    self.WriteValidUnitTest(func, f, invalid_test, *extras)
2705
2706  def WriteHandlerImplementation (self, func, f):
2707    """Overrriden from TypeHandler."""
2708    f.write("  %sHelper(n, %s);\n" %
2709               (func.name, func.GetLastOriginalArg().name))
2710
2711  def WriteImmediateHandlerImplementation (self, func, f):
2712    """Overrriden from TypeHandler."""
2713    f.write("  %sHelper(n, %s);\n" %
2714            (func.original_name, func.GetLastOriginalArg().name))
2715
2716  def WriteGLES2Implementation(self, func, f):
2717    """Overrriden from TypeHandler."""
2718    impl_func = func.GetInfo('impl_func', True)
2719    if impl_func:
2720      args = {
2721          'return_type': func.return_type,
2722          'prefix' : _prefix,
2723          'name': func.original_name,
2724          'typed_args': func.MakeTypedOriginalArgString(""),
2725          'args': func.MakeOriginalArgString(""),
2726          'resource_type': func.GetInfo('resource_type').lower(),
2727          'count_name': func.GetOriginalArgs()[0].name,
2728        }
2729      f.write(
2730          "%(return_type)s %(prefix)sImplementation::"
2731          "%(name)s(%(typed_args)s) {\n" %
2732          args)
2733      f.write("  GPU_CLIENT_SINGLE_THREAD_CHECK();\n")
2734      func.WriteDestinationInitalizationValidation(f)
2735      self.WriteClientGLCallLog(func, f)
2736      f.write("""  GPU_CLIENT_LOG_CODE_BLOCK({
2737    for (GLsizei i = 0; i < n; ++i) {
2738      GPU_CLIENT_LOG("  " << i << ": " << %s[i]);
2739    }
2740  });
2741""" % func.GetOriginalArgs()[1].name)
2742      f.write("""  GPU_CLIENT_DCHECK_CODE_BLOCK({
2743    for (GLsizei i = 0; i < n; ++i) {
2744      DCHECK(%s[i] != 0);
2745    }
2746  });
2747""" % func.GetOriginalArgs()[1].name)
2748      for arg in func.GetOriginalArgs():
2749        arg.WriteClientSideValidationCode(f, func)
2750      code = """  %(name)sHelper(%(args)s);
2751  CheckGLError();
2752}
2753
2754"""
2755      f.write(code % args)
2756
2757  def WriteImmediateCmdComputeSize(self, _func, f):
2758    """Overrriden from TypeHandler."""
2759    f.write("  static uint32_t ComputeDataSize(GLsizei _n) {\n")
2760    f.write(
2761        "    return static_cast<uint32_t>(sizeof(GLuint) * _n);  // NOLINT\n")
2762    f.write("  }\n")
2763    f.write("\n")
2764    f.write("  static uint32_t ComputeSize(GLsizei _n) {\n")
2765    f.write("    return static_cast<uint32_t>(\n")
2766    f.write("        sizeof(ValueType) + ComputeDataSize(_n));  // NOLINT\n")
2767    f.write("  }\n")
2768    f.write("\n")
2769
2770  def WriteImmediateCmdSetHeader(self, _func, f):
2771    """Overrriden from TypeHandler."""
2772    f.write("  void SetHeader(GLsizei _n) {\n")
2773    f.write("    header.SetCmdByTotalSize<ValueType>(ComputeSize(_n));\n")
2774    f.write("  }\n")
2775    f.write("\n")
2776
2777  def WriteImmediateCmdInit(self, func, f):
2778    """Overrriden from TypeHandler."""
2779    last_arg = func.GetLastOriginalArg()
2780    f.write("  void Init(%s, %s _%s) {\n" %
2781               (func.MakeTypedCmdArgString("_"),
2782                last_arg.type, last_arg.name))
2783    f.write("    SetHeader(_n);\n")
2784    args = func.GetCmdArgs()
2785    for arg in args:
2786      f.write("    %s = _%s;\n" % (arg.name, arg.name))
2787    f.write("    memcpy(ImmediateDataAddress(this),\n")
2788    f.write("           _%s, ComputeDataSize(_n));\n" % last_arg.name)
2789    f.write("  }\n")
2790    f.write("\n")
2791
2792  def WriteImmediateCmdSet(self, func, f):
2793    """Overrriden from TypeHandler."""
2794    last_arg = func.GetLastOriginalArg()
2795    copy_args = func.MakeCmdArgString("_", False)
2796    f.write("  void* Set(void* cmd%s, %s _%s) {\n" %
2797               (func.MakeTypedCmdArgString("_", True),
2798                last_arg.type, last_arg.name))
2799    f.write("    static_cast<ValueType*>(cmd)->Init(%s, _%s);\n" %
2800               (copy_args, last_arg.name))
2801    f.write("    const uint32_t size = ComputeSize(_n);\n")
2802    f.write("    return NextImmediateCmdAddressTotalSize<ValueType>("
2803               "cmd, size);\n")
2804    f.write("  }\n")
2805    f.write("\n")
2806
2807  def WriteImmediateCmdHelper(self, func, f):
2808    """Overrriden from TypeHandler."""
2809    code = """  void %(name)s(%(typed_args)s) {
2810    const uint32_t size = %(lp)s::cmds::%(name)s::ComputeSize(n);
2811    %(lp)s::cmds::%(name)s* c =
2812        GetImmediateCmdSpaceTotalSize<%(lp)s::cmds::%(name)s>(size);
2813    if (c) {
2814      c->Init(%(args)s);
2815    }
2816  }
2817
2818"""
2819    f.write(code % {
2820          "lp" : _lower_prefix,
2821          "name": func.name,
2822          "typed_args": func.MakeTypedOriginalArgString(""),
2823          "args": func.MakeOriginalArgString(""),
2824        })
2825
2826  def WriteImmediateFormatTest(self, func, f):
2827    """Overrriden from TypeHandler."""
2828    f.write("TEST_F(%sFormatTest, %s) {\n" % (_prefix, func.name))
2829    f.write("  static GLuint ids[] = { 12, 23, 34, };\n")
2830    f.write("  cmds::%s& cmd = *GetBufferAs<cmds::%s>();\n" %
2831               (func.name, func.name))
2832    f.write("  void* next_cmd = cmd.Set(\n")
2833    f.write("      &cmd, static_cast<GLsizei>(base::size(ids)), ids);\n")
2834    f.write("  EXPECT_EQ(static_cast<uint32_t>(cmds::%s::kCmdId),\n" %
2835               func.name)
2836    f.write("            cmd.header.command);\n")
2837    f.write("  EXPECT_EQ(sizeof(cmd) +\n")
2838    f.write("            RoundSizeToMultipleOfEntries(cmd.n * 4u),\n")
2839    f.write("            cmd.header.size * 4u);\n")
2840    f.write("  EXPECT_EQ(static_cast<GLsizei>(base::size(ids)), cmd.n);\n");
2841    f.write("  CheckBytesWrittenMatchesExpectedSize(\n")
2842    f.write("      next_cmd, sizeof(cmd) +\n")
2843    f.write("      RoundSizeToMultipleOfEntries(base::size(ids) * 4u));\n")
2844    f.write("  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd),\n")
2845    f.write("                      sizeof(ids)));\n")
2846    f.write("}\n")
2847    f.write("\n")
2848
2849
2850class GETnHandler(TypeHandler):
2851  """Handler for GETn for glGetBooleanv, glGetFloatv, ... type functions."""
2852
2853  def InitFunction(self, func):
2854    """Overrriden from TypeHandler."""
2855    TypeHandler.InitFunction(self, func)
2856
2857    if func.name == 'GetSynciv':
2858      return
2859
2860    arg_insert_point = len(func.passthrough_service_doer_args) - 1;
2861    func.passthrough_service_doer_args.insert(
2862        arg_insert_point, Argument('length', 'GLsizei*'))
2863    func.passthrough_service_doer_args.insert(
2864        arg_insert_point, Argument('bufsize', 'GLsizei'))
2865
2866  def NeedsDataTransferFunction(self, func):
2867    """Overriden from TypeHandler."""
2868    return False
2869
2870  def WriteServiceImplementation(self, func, f):
2871    """Overrriden from TypeHandler."""
2872    self.WriteServiceHandlerFunctionHeader(func, f)
2873    if func.IsES31():
2874      return
2875    last_arg = func.GetLastOriginalArg()
2876    # All except shm_id and shm_offset.
2877    all_but_last_args = func.GetCmdArgs()[:-2]
2878    for arg in all_but_last_args:
2879      arg.WriteGetCode(f)
2880
2881    code = """  typedef cmds::%(func_name)s::Result Result;
2882  GLsizei num_values = 0;
2883  if (!GetNumValuesReturnedForGLGet(pname, &num_values)) {
2884    LOCAL_SET_GL_ERROR_INVALID_ENUM(":%(func_name)s", pname, "pname");
2885    return error::kNoError;
2886  }
2887  uint32_t checked_size = 0;
2888  if (!Result::ComputeSize(num_values).AssignIfValid(&checked_size)) {
2889    return error::kOutOfBounds;
2890  }
2891  Result* result = GetSharedMemoryAs<Result*>(
2892      c.%(last_arg_name)s_shm_id, c.%(last_arg_name)s_shm_offset,
2893      checked_size);
2894  %(last_arg_type)s %(last_arg_name)s = result ? result->GetData() : nullptr;
2895"""
2896    f.write(code % {
2897        'last_arg_type': last_arg.type,
2898        'last_arg_name': last_arg.name,
2899        'func_name': func.name,
2900      })
2901    func.WriteHandlerValidation(f)
2902    code = """  // Check that the client initialized the result.
2903  if (result->size != 0) {
2904    return error::kInvalidArguments;
2905  }
2906"""
2907    shadowed = func.GetInfo('shadowed')
2908    if not shadowed:
2909      f.write('  LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("%s");\n' % func.name)
2910    f.write(code)
2911    func.WriteHandlerImplementation(f)
2912    if shadowed:
2913      code = """  result->SetNumResults(num_values);
2914  return error::kNoError;
2915}
2916"""
2917    else:
2918     code = """  GLenum error = LOCAL_PEEK_GL_ERROR("%(func_name)s");
2919  if (error == GL_NO_ERROR) {
2920    result->SetNumResults(num_values);
2921  }
2922  return error::kNoError;
2923}
2924
2925"""
2926    f.write(code % {'func_name': func.name})
2927
2928  def WritePassthroughServiceImplementation(self, func, f):
2929    """Overrriden from TypeHandler."""
2930    self.WritePassthroughServiceFunctionHeader(func, f)
2931    last_arg = func.GetLastOriginalArg()
2932    # All except shm_id and shm_offset.
2933    all_but_last_args = func.GetCmdArgs()[:-2]
2934    for arg in all_but_last_args:
2935      arg.WriteGetCode(f)
2936
2937    code = """  unsigned int buffer_size = 0;
2938  typedef cmds::%(func_name)s::Result Result;
2939  Result* result = GetSharedMemoryAndSizeAs<Result*>(
2940      c.%(last_arg_name)s_shm_id, c.%(last_arg_name)s_shm_offset,
2941      sizeof(Result), &buffer_size);
2942  %(last_arg_type)s %(last_arg_name)s = result ? result->GetData() : nullptr;
2943  if (%(last_arg_name)s == nullptr) {
2944    return error::kOutOfBounds;
2945  }
2946  GLsizei bufsize = Result::ComputeMaxResults(buffer_size);
2947  GLsizei written_values = 0;
2948  GLsizei* length = &written_values;
2949"""
2950    f.write(code % {
2951        'last_arg_type': last_arg.type,
2952        'last_arg_name': last_arg.name,
2953        'func_name': func.name,
2954      })
2955
2956    self.WritePassthroughServiceFunctionDoerCall(func, f)
2957
2958    code = """  if (written_values > bufsize) {
2959    return error::kOutOfBounds;
2960  }
2961  result->SetNumResults(written_values);
2962  return error::kNoError;
2963}
2964
2965"""
2966    f.write(code % {'func_name': func.name})
2967
2968  def WriteGLES2Implementation(self, func, f):
2969    """Overrriden from TypeHandler."""
2970    impl_func = func.GetInfo('impl_func', True)
2971    if impl_func:
2972      f.write("%s %sImplementation::%s(%s) {\n" %
2973                 (func.return_type, _prefix, func.original_name,
2974                  func.MakeTypedOriginalArgString("")))
2975      f.write("  GPU_CLIENT_SINGLE_THREAD_CHECK();\n")
2976      func.WriteDestinationInitalizationValidation(f)
2977      self.WriteClientGLCallLog(func, f)
2978      for arg in func.GetOriginalArgs():
2979        arg.WriteClientSideValidationCode(f, func)
2980      all_but_last_args = func.GetOriginalArgs()[:-1]
2981      args = []
2982      has_length_arg = False
2983      for arg in all_but_last_args:
2984        if arg.type == 'GLsync':
2985          args.append('ToGLuint(%s)' % arg.name)
2986        elif arg.name.endswith('size') and arg.type == 'GLsizei':
2987          continue
2988        elif arg.name == 'length':
2989          has_length_arg = True
2990          continue
2991        else:
2992          args.append(arg.name)
2993      arg_string = ", ".join(args)
2994      all_arg_string = (
2995          ", ".join([
2996            "%s" % arg.name
2997              for arg in func.GetOriginalArgs() if not arg.IsConstant()]))
2998      self.WriteTraceEvent(func, f)
2999      code = """  if (%(func_name)sHelper(%(all_arg_string)s)) {
3000    return;
3001  }
3002  typedef cmds::%(func_name)s::Result Result;
3003  ScopedResultPtr<Result> result = GetResultAs<Result>();
3004  if (!result) {
3005    return;
3006  }
3007  result->SetNumResults(0);
3008  helper_->%(func_name)s(%(arg_string)s,
3009      GetResultShmId(), result.offset());
3010  WaitForCmd();
3011  result->CopyResult(%(last_arg_name)s);
3012  GPU_CLIENT_LOG_CODE_BLOCK({
3013    for (int32_t i = 0; i < result->GetNumResults(); ++i) {
3014      GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
3015    }
3016  });"""
3017      if has_length_arg:
3018        code += """
3019  if (length) {
3020    *length = result->GetNumResults();
3021  }"""
3022      code += """
3023  CheckGLError();
3024}
3025"""
3026      f.write(code % {
3027          'func_name': func.name,
3028          'arg_string': arg_string,
3029          'all_arg_string': all_arg_string,
3030          'last_arg_name': func.GetLastOriginalArg().name,
3031        })
3032
3033  def WriteGLES2ImplementationUnitTest(self, func, f):
3034    """Writes the GLES2 Implemention unit test."""
3035    code = """
3036TEST_F(%(prefix)sImplementationTest, %(name)s) {
3037  struct Cmds {
3038    cmds::%(name)s cmd;
3039  };
3040  typedef cmds::%(name)s::Result::Type ResultType;
3041  ResultType result = 0;
3042  Cmds expected;
3043  ExpectedMemoryInfo result1 = GetExpectedResultMemory(
3044      sizeof(uint32_t) + sizeof(ResultType));
3045  expected.cmd.Init(%(cmd_args)s, result1.id, result1.offset);
3046  EXPECT_CALL(*command_buffer(), OnFlush())
3047      .WillOnce(SetMemory(result1.ptr, SizedResultHelper<ResultType>(1)))
3048      .RetiresOnSaturation();
3049  gl_->%(name)s(%(args)s, &result);
3050  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3051  EXPECT_EQ(static_cast<ResultType>(1), result);
3052}
3053"""
3054    first_cmd_arg = func.GetCmdArgs()[0].GetValidNonCachedClientSideCmdArg(func)
3055    if not first_cmd_arg:
3056      return
3057
3058    first_gl_arg = func.GetOriginalArgs()[0].GetValidNonCachedClientSideArg(
3059        func)
3060
3061    cmd_arg_strings = [first_cmd_arg]
3062    for arg in func.GetCmdArgs()[1:-2]:
3063      cmd_arg_strings.append(arg.GetValidClientSideCmdArg(func))
3064    gl_arg_strings = [first_gl_arg]
3065    for arg in func.GetOriginalArgs()[1:-1]:
3066      gl_arg_strings.append(arg.GetValidClientSideArg(func))
3067
3068    f.write(code % {
3069          'prefix' : _prefix,
3070          'name': func.name,
3071          'args': ", ".join(gl_arg_strings),
3072          'cmd_args': ", ".join(cmd_arg_strings),
3073        })
3074
3075  def WriteServiceUnitTest(self, func, f, *extras):
3076    """Overrriden from TypeHandler."""
3077    valid_test = """
3078TEST_P(%(test_name)s, %(name)sValidArgs) {
3079  EXPECT_CALL(*gl_, GetError())
3080      .WillRepeatedly(Return(GL_NO_ERROR));
3081  SpecializedSetup<cmds::%(name)s, 0>(true);
3082  typedef cmds::%(name)s::Result Result;
3083  Result* result = static_cast<Result*>(shared_memory_address_);
3084  EXPECT_CALL(*gl_, %(gl_func_name)s(%(local_gl_args)s));
3085  result->size = 0;
3086  cmds::%(name)s cmd;
3087  cmd.Init(%(cmd_args)s);
3088  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
3089  EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(
3090                %(valid_pname)s),
3091            result->GetNumResults());
3092  EXPECT_EQ(GL_NO_ERROR, GetGLError());
3093}
3094"""
3095    gl_arg_strings = []
3096    cmd_arg_strings = []
3097    valid_pname = ''
3098    for arg in func.GetOriginalArgs()[:-1]:
3099      if arg.name == 'length':
3100        gl_arg_value = 'nullptr'
3101      elif arg.name.endswith('size'):
3102        gl_arg_value = ("decoder_->GetGLES2Util()->GLGetNumValuesReturned(%s)" %
3103            valid_pname)
3104      elif arg.type == 'GLsync':
3105        gl_arg_value = 'reinterpret_cast<GLsync>(kServiceSyncId)'
3106      else:
3107        gl_arg_value = arg.GetValidGLArg(func)
3108      gl_arg_strings.append(gl_arg_value)
3109      if arg.name == 'pname':
3110        valid_pname = gl_arg_value
3111      if arg.name.endswith('size') or arg.name == 'length':
3112        continue
3113      if arg.type == 'GLsync':
3114        arg_value = 'client_sync_id_'
3115      else:
3116        arg_value = arg.GetValidArg(func)
3117      cmd_arg_strings.append(arg_value)
3118    if func.GetInfo('gl_test_func') == 'glGetIntegerv':
3119      gl_arg_strings.append("_")
3120    else:
3121      gl_arg_strings.append("result->GetData()")
3122    cmd_arg_strings.append("shared_memory_id_")
3123    cmd_arg_strings.append("shared_memory_offset_")
3124
3125    self.WriteValidUnitTest(func, f, valid_test, {
3126        'local_gl_args': ", ".join(gl_arg_strings),
3127        'cmd_args': ", ".join(cmd_arg_strings),
3128        'valid_pname': valid_pname,
3129      }, *extras)
3130
3131    if not func.IsES3():
3132      invalid_test = """
3133TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
3134  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)).Times(0);
3135  SpecializedSetup<cmds::%(name)s, 0>(false);
3136  cmds::%(name)s::Result* result =
3137      static_cast<cmds::%(name)s::Result*>(shared_memory_address_);
3138  result->size = 0;
3139  cmds::%(name)s cmd;
3140  cmd.Init(%(args)s);
3141  EXPECT_EQ(error::%(parse_result)s, ExecuteCmd(cmd));
3142  EXPECT_EQ(0u, result->size);%(gl_error_test)s
3143}
3144"""
3145      self.WriteInvalidUnitTest(func, f, invalid_test, *extras)
3146
3147  def WriteImmediateCmdInit(self, func, f):
3148    """Overrriden from TypeHandler."""
3149    pass
3150
3151  def WriteImmediateCmdSet(self, func, f):
3152    """Overrriden from TypeHandler."""
3153    pass
3154
3155
3156class ArrayArgTypeHandler(TypeHandler):
3157  """Base class for type handlers that handle args that are arrays"""
3158
3159  def GetArrayType(self, func):
3160    """Returns the type of the element in the element array being PUT to."""
3161    for arg in func.GetOriginalArgs():
3162      if arg.IsPointer():
3163        element_type = arg.GetPointedType()
3164        return element_type
3165
3166    # Special case: array type handler is used for a function that is forwarded
3167    # to the actual array type implementation
3168    element_type = func.GetOriginalArgs()[-1].type
3169    assert all(arg.type == element_type \
3170               for arg in func.GetOriginalArgs()[-self.GetArrayCount(func):])
3171    return element_type
3172
3173  def GetArrayCount(self, func):
3174    """Returns the count of the elements in the array being PUT to."""
3175    return func.GetInfo('count')
3176
3177  def WriteImmediateCmdInit(self, func, f):
3178    """Overrriden from TypeHandler."""
3179    pass
3180
3181  def WriteImmediateCmdSet(self, func, f):
3182    """Overrriden from TypeHandler."""
3183    pass
3184
3185
3186class PUTHandler(ArrayArgTypeHandler):
3187  """Handler for glTexParameter_v, glVertexAttrib_v functions."""
3188
3189  def WriteServiceUnitTest(self, func, f, *extras):
3190    """Writes the service unit test for a command."""
3191    expected_call = "EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s));"
3192    if func.GetInfo("first_element_only"):
3193      gl_arg_strings = [
3194        arg.GetValidGLArg(func) for arg in func.GetOriginalArgs()
3195      ]
3196      gl_arg_strings[-1] = "*" + gl_arg_strings[-1]
3197      expected_call = ("EXPECT_CALL(*gl_, %%(gl_func_name)s(%s));" %
3198          ", ".join(gl_arg_strings))
3199    valid_test = """
3200TEST_P(%(test_name)s, %(name)sValidArgs) {
3201  SpecializedSetup<cmds::%(name)s, 0>(true);
3202  cmds::%(name)s cmd;
3203  cmd.Init(%(args)s);
3204  GetSharedMemoryAs<%(data_type)s*>()[0] = %(data_value)s;
3205  %(expected_call)s
3206  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
3207  EXPECT_EQ(GL_NO_ERROR, GetGLError());
3208}
3209"""
3210    extra = {
3211      'data_type': self.GetArrayType(func),
3212      'data_value': func.GetInfo('data_value') or '0',
3213      'expected_call': expected_call,
3214    }
3215    self.WriteValidUnitTest(func, f, valid_test, extra, *extras)
3216
3217    invalid_test = """
3218TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
3219  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)).Times(0);
3220  SpecializedSetup<cmds::%(name)s, 0>(false);
3221  cmds::%(name)s cmd;
3222  cmd.Init(%(args)s);
3223  GetSharedMemoryAs<%(data_type)s*>()[0] = %(data_value)s;
3224  EXPECT_EQ(error::%(parse_result)s, ExecuteCmd(cmd));%(gl_error_test)s
3225}
3226"""
3227    self.WriteInvalidUnitTest(func, f, invalid_test, extra, *extras)
3228
3229  def WriteImmediateServiceUnitTest(self, func, f, *extras):
3230    """Writes the service unit test for a command."""
3231    valid_test = """
3232TEST_P(%(test_name)s, %(name)sValidArgs) {
3233  cmds::%(name)s& cmd = *GetImmediateAs<cmds::%(name)s>();
3234  SpecializedSetup<cmds::%(name)s, 0>(true);
3235  %(data_type)s temp[%(data_count)s] = { %(data_value)s, };
3236  cmd.Init(%(gl_client_args)s, &temp[0]);
3237  EXPECT_CALL(
3238      *gl_,
3239      %(gl_func_name)s(%(gl_args)s, %(expectation)s));
3240  EXPECT_EQ(error::kNoError,
3241            ExecuteImmediateCmd(cmd, sizeof(temp)));
3242  EXPECT_EQ(GL_NO_ERROR, GetGLError());
3243}
3244"""
3245    gl_client_arg_strings = [
3246      arg.GetValidArg(func) for arg in func.GetOriginalArgs()[0:-1]
3247    ]
3248    gl_arg_strings = [
3249      arg.GetValidGLArg(func) for arg in func.GetOriginalArgs()[0:-1]
3250    ]
3251    gl_any_strings = ["_"] * len(gl_arg_strings)
3252    data_count = self.GetArrayCount(func)
3253    if func.GetInfo('first_element_only'):
3254      expectation = "temp[0]"
3255    else:
3256      expectation = "PointsToArray(temp, %s)" % data_count
3257
3258    extra = {
3259      'expectation': expectation,
3260      'data_type': self.GetArrayType(func),
3261      'data_count': data_count,
3262      'data_value': func.GetInfo('data_value') or '0',
3263      'gl_client_args': ", ".join(gl_client_arg_strings),
3264      'gl_args': ", ".join(gl_arg_strings),
3265      'gl_any_args': ", ".join(gl_any_strings),
3266    }
3267    self.WriteValidUnitTest(func, f, valid_test, extra, *extras)
3268
3269    invalid_test = """
3270TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
3271  cmds::%(name)s& cmd = *GetImmediateAs<cmds::%(name)s>();"""
3272    if func.IsES3():
3273      invalid_test += """
3274  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_any_args)s, _)).Times(1);
3275"""
3276    else:
3277      invalid_test += """
3278  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_any_args)s, _)).Times(0);
3279"""
3280    invalid_test += """
3281  SpecializedSetup<cmds::%(name)s, 0>(false);
3282  %(data_type)s temp[%(data_count)s] = { %(data_value)s, };
3283  cmd.Init(%(all_but_last_args)s, &temp[0]);
3284  EXPECT_EQ(error::%(parse_result)s,
3285            ExecuteImmediateCmd(cmd, sizeof(temp)));
3286  %(gl_error_test)s
3287}
3288"""
3289    self.WriteInvalidUnitTest(func, f, invalid_test, extra, *extras)
3290
3291  def WriteGetDataSizeCode(self, func, arg, f):
3292    """Overrriden from TypeHandler."""
3293    code = ("""  uint32_t %(data_size)s;
3294  if (!%(namespace)sGLES2Util::""" +
3295"""ComputeDataSize<%(arrayType)s, %(arrayCount)d>(1, &%(data_size)s)) {
3296    return error::kOutOfBounds;
3297  }
3298""")
3299    f.write(code % {'data_size': arg.GetReservedSizeId(),
3300                    'namespace': _Namespace(),
3301                    'arrayType': self.GetArrayType(func),
3302                    'arrayCount': self.GetArrayCount(func)})
3303    if func.IsImmediate():
3304      f.write("  if (%s > immediate_data_size) {\n" % arg.GetReservedSizeId())
3305      f.write("    return error::kOutOfBounds;\n")
3306      f.write("  }\n")
3307
3308  def __NeedsToCalcDataCount(self, func):
3309    use_count_func = func.GetInfo('use_count_func')
3310    return use_count_func != None and use_count_func != False
3311
3312  def WriteGLES2Implementation(self, func, f):
3313    """Overrriden from TypeHandler."""
3314    impl_func = func.GetInfo('impl_func')
3315    if (impl_func != None and impl_func != True):
3316      return;
3317    f.write("%s %sImplementation::%s(%s) {\n" %
3318               (func.return_type, _prefix, func.original_name,
3319                func.MakeTypedOriginalArgString("")))
3320    f.write("  GPU_CLIENT_SINGLE_THREAD_CHECK();\n")
3321    func.WriteDestinationInitalizationValidation(f)
3322    self.WriteClientGLCallLog(func, f)
3323
3324    if self.__NeedsToCalcDataCount(func):
3325      f.write("  uint32_t count = %sGLES2Util::Calc%sDataCount(%s);\n" %
3326                 (_Namespace(), func.name, func.GetOriginalArgs()[0].name))
3327      f.write("  DCHECK_LE(count, %du);\n" % self.GetArrayCount(func))
3328      f.write("  if (count == 0) {\n")
3329      f.write("    SetGLErrorInvalidEnum(\"%s\", %s, \"%s\");\n" %
3330                 (func.prefixed_name, func.GetOriginalArgs()[0].name,
3331                  func.GetOriginalArgs()[0].name))
3332      f.write("    return;\n")
3333      f.write("  }\n")
3334    else:
3335      f.write("  uint32_t count = %d;" % self.GetArrayCount(func))
3336    f.write("  for (uint32_t ii = 0; ii < count; ++ii)\n")
3337    f.write('    GPU_CLIENT_LOG("value[" << ii << "]: " << %s[ii]);\n' %
3338               func.GetLastOriginalArg().name)
3339    for arg in func.GetOriginalArgs():
3340      arg.WriteClientSideValidationCode(f, func)
3341    f.write("  helper_->%sImmediate(%s);\n" %
3342               (func.name, func.MakeOriginalArgString("")))
3343    f.write("  CheckGLError();\n")
3344    f.write("}\n")
3345    f.write("\n")
3346
3347  def WriteGLES2ImplementationUnitTest(self, func, f):
3348    """Writes the GLES2 Implemention unit test."""
3349    client_test = func.GetInfo('client_test', True)
3350    if not client_test:
3351      return;
3352    code = """
3353TEST_F(%(prefix)sImplementationTest, %(name)s) {
3354  %(type)s data[%(count)d] = {0};
3355  struct Cmds {
3356    cmds::%(name)sImmediate cmd;
3357    %(type)s data[%(count)d];
3358  };
3359
3360  for (int jj = 0; jj < %(count)d; ++jj) {
3361    data[jj] = static_cast<%(type)s>(jj);
3362  }
3363  Cmds expected;
3364  expected.cmd.Init(%(cmd_args)s, &data[0]);
3365  gl_->%(name)s(%(args)s, &data[0]);
3366  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3367}
3368"""
3369    cmd_arg_strings = [
3370      arg.GetValidClientSideCmdArg(func) for arg in func.GetCmdArgs()[0:-2]
3371    ]
3372    gl_arg_strings = [
3373      arg.GetValidClientSideArg(func) for arg in func.GetOriginalArgs()[0:-1]
3374    ]
3375
3376    f.write(code % {
3377          'prefix' : _prefix,
3378          'name': func.name,
3379          'type': self.GetArrayType(func),
3380          'count': self.GetArrayCount(func),
3381          'args': ", ".join(gl_arg_strings),
3382          'cmd_args': ", ".join(cmd_arg_strings),
3383        })
3384
3385  def WriteImmediateCmdComputeSize(self, func, f):
3386    """Overrriden from TypeHandler."""
3387    f.write("  static uint32_t ComputeDataSize() {\n")
3388    f.write("    return static_cast<uint32_t>(\n")
3389    f.write("        sizeof(%s) * %d);\n" %
3390               (self.GetArrayType(func), self.GetArrayCount(func)))
3391    f.write("  }\n")
3392    f.write("\n")
3393    if self.__NeedsToCalcDataCount(func):
3394      f.write("  static uint32_t ComputeEffectiveDataSize(%s %s) {\n" %
3395                 (func.GetOriginalArgs()[0].type,
3396                  func.GetOriginalArgs()[0].name))
3397      f.write("    return static_cast<uint32_t>(\n")
3398      f.write("        sizeof(%s) * %sGLES2Util::Calc%sDataCount(%s));\n" %
3399                 (self.GetArrayType(func), _Namespace(), func.original_name,
3400                  func.GetOriginalArgs()[0].name))
3401      f.write("  }\n")
3402      f.write("\n")
3403    f.write("  static uint32_t ComputeSize() {\n")
3404    f.write("    return static_cast<uint32_t>(\n")
3405    f.write(
3406        "        sizeof(ValueType) + ComputeDataSize());\n")
3407    f.write("  }\n")
3408    f.write("\n")
3409
3410  def WriteImmediateCmdSetHeader(self, _func, f):
3411    """Overrriden from TypeHandler."""
3412    f.write("  void SetHeader() {\n")
3413    f.write(
3414        "    header.SetCmdByTotalSize<ValueType>(ComputeSize());\n")
3415    f.write("  }\n")
3416    f.write("\n")
3417
3418  def WriteImmediateCmdInit(self, func, f):
3419    """Overrriden from TypeHandler."""
3420    last_arg = func.GetLastOriginalArg()
3421    f.write("  void Init(%s, %s _%s) {\n" %
3422               (func.MakeTypedCmdArgString("_"),
3423                last_arg.type, last_arg.name))
3424    f.write("    SetHeader();\n")
3425    args = func.GetCmdArgs()
3426    for arg in args:
3427      arg.WriteSetCode(f, 4, "_%s" % arg.name)
3428    f.write("    memcpy(ImmediateDataAddress(this),\n")
3429    if self.__NeedsToCalcDataCount(func):
3430      f.write("           _%s, ComputeEffectiveDataSize(%s));" %
3431                 (last_arg.name, func.GetOriginalArgs()[0].name))
3432      f.write("""
3433    DCHECK_GE(ComputeDataSize(), ComputeEffectiveDataSize(%(arg)s));
3434    char* pointer = reinterpret_cast<char*>(ImmediateDataAddress(this)) +
3435        ComputeEffectiveDataSize(%(arg)s);
3436    memset(pointer, 0, ComputeDataSize() - ComputeEffectiveDataSize(%(arg)s));
3437""" % { 'arg': func.GetOriginalArgs()[0].name, })
3438    else:
3439      f.write("           _%s, ComputeDataSize());\n" % last_arg.name)
3440    f.write("  }\n")
3441    f.write("\n")
3442
3443  def WriteImmediateCmdSet(self, func, f):
3444    """Overrriden from TypeHandler."""
3445    last_arg = func.GetLastOriginalArg()
3446    copy_args = func.MakeCmdArgString("_", False)
3447    f.write("  void* Set(void* cmd%s, %s _%s) {\n" %
3448               (func.MakeTypedCmdArgString("_", True),
3449                last_arg.type, last_arg.name))
3450    f.write("    static_cast<ValueType*>(cmd)->Init(%s, _%s);\n" %
3451               (copy_args, last_arg.name))
3452    f.write("    const uint32_t size = ComputeSize();\n")
3453    f.write("    return NextImmediateCmdAddressTotalSize<ValueType>("
3454               "cmd, size);\n")
3455    f.write("  }\n")
3456    f.write("\n")
3457
3458  def WriteImmediateCmdHelper(self, func, f):
3459    """Overrriden from TypeHandler."""
3460    code = """  void %(name)s(%(typed_args)s) {
3461    const uint32_t size = %(lp)s::cmds::%(name)s::ComputeSize();
3462    %(lp)s::cmds::%(name)s* c =
3463        GetImmediateCmdSpaceTotalSize<%(lp)s::cmds::%(name)s>(size);
3464    if (c) {
3465      c->Init(%(args)s);
3466    }
3467  }
3468
3469"""
3470    f.write(code % {
3471          "lp" : _lower_prefix,
3472          "name": func.name,
3473          "typed_args": func.MakeTypedOriginalArgString(""),
3474          "args": func.MakeOriginalArgString(""),
3475        })
3476
3477  def WriteImmediateFormatTest(self, func, f):
3478    """Overrriden from TypeHandler."""
3479    f.write("TEST_F(%sFormatTest, %s) {\n" % (_prefix, func.name))
3480    f.write("  const int kSomeBaseValueToTestWith = 51;\n")
3481    f.write("  static %s data[] = {\n" % self.GetArrayType(func))
3482    for v in range(0, self.GetArrayCount(func)):
3483      f.write("    static_cast<%s>(kSomeBaseValueToTestWith + %d),\n" %
3484                 (self.GetArrayType(func), v))
3485    f.write("  };\n")
3486    f.write("  cmds::%s& cmd = *GetBufferAs<cmds::%s>();\n" %
3487               (func.name, func.name))
3488    f.write("  void* next_cmd = cmd.Set(\n")
3489    f.write("      &cmd")
3490    args = func.GetCmdArgs()
3491    for value, arg in enumerate(args):
3492      f.write(",\n      static_cast<%s>(%d)" % (arg.type, value + 11))
3493    f.write(",\n      data);\n")
3494    args = func.GetCmdArgs()
3495    f.write("  EXPECT_EQ(static_cast<uint32_t>(cmds::%s::kCmdId),\n"
3496               % func.name)
3497    f.write("            cmd.header.command);\n")
3498    f.write("  EXPECT_EQ(sizeof(cmd) +\n")
3499    f.write("            RoundSizeToMultipleOfEntries(sizeof(data)),\n")
3500    f.write("            cmd.header.size * 4u);\n")
3501    for value, arg in enumerate(args):
3502      f.write("  EXPECT_EQ(static_cast<%s>(%d), %s);\n" %
3503                 (arg.type, value + 11, arg.GetArgAccessor('cmd')))
3504    f.write("  CheckBytesWrittenMatchesExpectedSize(\n")
3505    f.write("      next_cmd, sizeof(cmd) +\n")
3506    f.write("      RoundSizeToMultipleOfEntries(sizeof(data)));\n")
3507    # TODO: Check that data was inserted
3508    f.write("}\n")
3509    f.write("\n")
3510
3511
3512class PUTnHandler(ArrayArgTypeHandler):
3513  """Handler for PUTn 'glUniform__v' type functions."""
3514
3515  def WriteServiceUnitTest(self, func, f, *extras):
3516    """Overridden from TypeHandler."""
3517    ArrayArgTypeHandler.WriteServiceUnitTest(self, func, f, *extras)
3518
3519    valid_test = """
3520TEST_P(%(test_name)s, %(name)sValidArgsCountTooLarge) {
3521  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s));
3522  SpecializedSetup<cmds::%(name)s, 0>(true);
3523  cmds::%(name)s cmd;
3524  cmd.Init(%(args)s);
3525  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
3526  EXPECT_EQ(GL_NO_ERROR, GetGLError());
3527}
3528"""
3529    gl_arg_strings = []
3530    arg_strings = []
3531    for count, arg in enumerate(func.GetOriginalArgs()):
3532      # hardcoded to match unit tests.
3533      if count == 0:
3534        # the location of the second element of the 2nd uniform.
3535        # defined in GLES2DecoderBase::SetupShaderForUniform
3536        gl_arg_strings.append("3")
3537        arg_strings.append("ProgramManager::MakeFakeLocation(1, 1)")
3538      elif count == 1:
3539        # the number of elements that gl will be called with.
3540        gl_arg_strings.append("3")
3541        # the number of elements requested in the command.
3542        arg_strings.append("5")
3543      else:
3544        gl_arg_strings.append(arg.GetValidGLArg(func))
3545        if not arg.IsConstant():
3546          arg_strings.append(arg.GetValidArg(func))
3547    extra = {
3548      'gl_args': ", ".join(gl_arg_strings),
3549      'args': ", ".join(arg_strings),
3550    }
3551    self.WriteValidUnitTest(func, f, valid_test, extra, *extras)
3552
3553  def WriteImmediateServiceUnitTest(self, func, f, *extras):
3554    """Overridden from TypeHandler."""
3555    valid_test = """
3556TEST_P(%(test_name)s, %(name)sValidArgs) {
3557  cmds::%(name)s& cmd = *GetImmediateAs<cmds::%(name)s>();
3558  SpecializedSetup<cmds::%(name)s, 0>(true);
3559  %(data_type)s temp[%(data_count)s * 2] = { 0, };
3560  EXPECT_CALL(
3561      *gl_,
3562      %(gl_func_name)s(%(gl_args)s,
3563          PointsToArray(temp, %(data_count)s)));
3564  cmd.Init(%(args)s, &temp[0]);
3565  EXPECT_EQ(error::kNoError,
3566            ExecuteImmediateCmd(cmd, sizeof(temp)));
3567  EXPECT_EQ(GL_NO_ERROR, GetGLError());
3568}
3569"""
3570    gl_arg_strings = []
3571    gl_any_strings = []
3572    arg_strings = []
3573    for arg in func.GetOriginalArgs()[0:-1]:
3574      gl_arg_strings.append(arg.GetValidGLArg(func))
3575      gl_any_strings.append("_")
3576      if not arg.IsConstant():
3577        arg_strings.append(arg.GetValidArg(func))
3578    extra = {
3579      'data_type': self.GetArrayType(func),
3580      'data_count': self.GetArrayCount(func),
3581      'args': ", ".join(arg_strings),
3582      'gl_args': ", ".join(gl_arg_strings),
3583      'gl_any_args': ", ".join(gl_any_strings),
3584    }
3585    self.WriteValidUnitTest(func, f, valid_test, extra, *extras)
3586
3587    invalid_test = """
3588TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
3589  cmds::%(name)s& cmd = *GetImmediateAs<cmds::%(name)s>();
3590  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_any_args)s, _)).Times(0);
3591  SpecializedSetup<cmds::%(name)s, 0>(false);
3592  %(data_type)s temp[%(data_count)s * 2] = { 0, };
3593  cmd.Init(%(all_but_last_args)s, &temp[0]);
3594  EXPECT_EQ(error::%(parse_result)s,
3595            ExecuteImmediateCmd(cmd, sizeof(temp)));%(gl_error_test)s
3596}
3597"""
3598    self.WriteInvalidUnitTest(func, f, invalid_test, extra, *extras)
3599
3600  def WriteGetDataSizeCode(self, func, arg, f):
3601    """Overrriden from TypeHandler."""
3602    code = ("""  uint32_t %(data_size)s = 0;
3603  if (count >= 0 && !%(namespace)sGLES2Util::""" +
3604"""ComputeDataSize<%(arrayType)s, %(arrayCount)d>(count, &%(data_size)s)) {
3605    return error::kOutOfBounds;
3606  }
3607""")
3608    f.write(code % {'data_size': arg.GetReservedSizeId(),
3609                    'namespace': _Namespace(),
3610                    'arrayType': self.GetArrayType(func),
3611                    'arrayCount': self.GetArrayCount(func)})
3612    if func.IsImmediate():
3613      f.write("  if (%s > immediate_data_size) {\n" % arg.GetReservedSizeId())
3614      f.write("    return error::kOutOfBounds;\n")
3615      f.write("  }\n")
3616
3617  def WriteGLES2Implementation(self, func, f):
3618    """Overrriden from TypeHandler."""
3619    impl_func = func.GetInfo('impl_func')
3620    if (impl_func != None and impl_func != True):
3621      return;
3622    f.write("%s %sImplementation::%s(%s) {\n" %
3623               (func.return_type, _prefix, func.original_name,
3624                func.MakeTypedOriginalArgString("")))
3625    f.write("  GPU_CLIENT_SINGLE_THREAD_CHECK();\n")
3626    func.WriteDestinationInitalizationValidation(f)
3627    self.WriteClientGLCallLog(func, f)
3628    last_pointer_name = func.GetLastOriginalPointerArg().name
3629    f.write("""  GPU_CLIENT_LOG_CODE_BLOCK({
3630    for (GLsizei i = 0; i < count; ++i) {
3631""")
3632    values_str = ' << ", " << '.join(
3633        ["%s[%d + i * %d]" % (
3634            last_pointer_name, ndx, self.GetArrayCount(func)) for ndx in range(
3635                0, self.GetArrayCount(func))])
3636    f.write('       GPU_CLIENT_LOG("  " << i << ": " << %s);\n' % values_str)
3637    f.write("    }\n  });\n")
3638    for arg in func.GetOriginalArgs():
3639      arg.WriteClientSideValidationCode(f, func)
3640    f.write("  helper_->%sImmediate(%s);\n" %
3641               (func.name, func.MakeInitString("")))
3642    f.write("  CheckGLError();\n")
3643    f.write("}\n")
3644    f.write("\n")
3645
3646  def WriteGLES2ImplementationUnitTest(self, func, f):
3647    """Writes the GLES2 Implemention unit test."""
3648    client_test = func.GetInfo('client_test', True)
3649    if not client_test:
3650      return;
3651
3652    code = """
3653TEST_F(%(prefix)sImplementationTest, %(name)s) {
3654  %(type)s data[%(count_param)d][%(count)d] = {{0}};
3655  struct Cmds {
3656    cmds::%(name)sImmediate cmd;
3657    %(type)s data[%(count_param)d][%(count)d];
3658  };
3659
3660  Cmds expected;
3661  for (int ii = 0; ii < %(count_param)d; ++ii) {
3662    for (int jj = 0; jj < %(count)d; ++jj) {
3663      data[ii][jj] = static_cast<%(type)s>(ii * %(count)d + jj);
3664    }
3665  }
3666  expected.cmd.Init(%(cmd_args)s);
3667  gl_->%(name)s(%(args)s);
3668  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3669}
3670"""
3671    cmd_arg_strings = []
3672    for arg in func.GetCmdArgs():
3673      if arg.name.endswith("_shm_id"):
3674        cmd_arg_strings.append("&data[0][0]")
3675      elif arg.name.endswith("_shm_offset"):
3676        continue
3677      else:
3678        cmd_arg_strings.append(arg.GetValidClientSideCmdArg(func))
3679    gl_arg_strings = []
3680    count_param = 0
3681    for arg in func.GetOriginalArgs():
3682      if arg.IsPointer():
3683        valid_value = "&data[0][0]"
3684      else:
3685        valid_value = arg.GetValidClientSideArg(func)
3686      gl_arg_strings.append(valid_value)
3687      if arg.name == "count":
3688        count_param = int(valid_value)
3689    f.write(code % {
3690          'prefix' : _prefix,
3691          'name': func.name,
3692          'type': self.GetArrayType(func),
3693          'count': self.GetArrayCount(func),
3694          'args': ", ".join(gl_arg_strings),
3695          'cmd_args': ", ".join(cmd_arg_strings),
3696          'count_param': count_param,
3697        })
3698
3699    # Test constants for invalid values, as they are not tested by the
3700    # service.
3701    constants = [
3702      arg for arg in func.GetOriginalArgs()[0:-1] if arg.IsConstant()
3703    ]
3704    if not constants:
3705      return
3706
3707    code = """
3708TEST_F(%(prefix)sImplementationTest,
3709       %(name)sInvalidConstantArg%(invalid_index)d) {
3710  %(type)s data[%(count_param)d][%(count)d] = {{0}};
3711  for (int ii = 0; ii < %(count_param)d; ++ii) {
3712    for (int jj = 0; jj < %(count)d; ++jj) {
3713      data[ii][jj] = static_cast<%(type)s>(ii * %(count)d + jj);
3714    }
3715  }
3716  gl_->%(name)s(%(args)s);
3717  EXPECT_TRUE(NoCommandsWritten());
3718  EXPECT_EQ(%(gl_error)s, CheckError());
3719}
3720"""
3721    for invalid_arg in constants:
3722      gl_arg_strings = []
3723      invalid = invalid_arg.GetInvalidArg(func)
3724      for arg in func.GetOriginalArgs():
3725        if arg is invalid_arg:
3726          gl_arg_strings.append(invalid[0])
3727        elif arg.IsPointer():
3728          gl_arg_strings.append("&data[0][0]")
3729        else:
3730          valid_value = arg.GetValidClientSideArg(func)
3731          gl_arg_strings.append(valid_value)
3732          if arg.name == "count":
3733            count_param = int(valid_value)
3734
3735      f.write(code % {
3736        'prefix' : _prefix,
3737        'name': func.name,
3738        'invalid_index': func.GetOriginalArgs().index(invalid_arg),
3739        'type': self.GetArrayType(func),
3740        'count': self.GetArrayCount(func),
3741        'args': ", ".join(gl_arg_strings),
3742        'gl_error': invalid[2],
3743        'count_param': count_param,
3744      })
3745
3746
3747  def WriteImmediateCmdComputeSize(self, func, f):
3748    """Overrriden from TypeHandler."""
3749    f.write("  static uint32_t ComputeDataSize(GLsizei _n) {\n")
3750    f.write("    return static_cast<uint32_t>(\n")
3751    f.write("        sizeof(%s) * %d * _n);  // NOLINT\n" %
3752               (self.GetArrayType(func), self.GetArrayCount(func)))
3753    f.write("  }\n")
3754    f.write("\n")
3755    f.write("  static uint32_t ComputeSize(GLsizei _n) {\n")
3756    f.write("    return static_cast<uint32_t>(\n")
3757    f.write(
3758        "        sizeof(ValueType) + ComputeDataSize(_n));  // NOLINT\n")
3759    f.write("  }\n")
3760    f.write("\n")
3761
3762  def WriteImmediateCmdSetHeader(self, _func, f):
3763    """Overrriden from TypeHandler."""
3764    f.write("  void SetHeader(GLsizei _n) {\n")
3765    f.write(
3766        "    header.SetCmdByTotalSize<ValueType>(ComputeSize(_n));\n")
3767    f.write("  }\n")
3768    f.write("\n")
3769
3770  def WriteImmediateCmdInit(self, func, f):
3771    """Overrriden from TypeHandler."""
3772    f.write("  void Init(%s) {\n" %
3773               func.MakeTypedInitString("_"))
3774    f.write("    SetHeader(_count);\n")
3775    args = func.GetCmdArgs()
3776    for arg in args:
3777      arg.WriteSetCode(f, 4, "_%s" % arg.name)
3778    f.write("    memcpy(ImmediateDataAddress(this),\n")
3779    pointer_arg = func.GetLastOriginalPointerArg()
3780    f.write("           _%s, ComputeDataSize(_count));\n" % pointer_arg.name)
3781    f.write("  }\n")
3782    f.write("\n")
3783
3784  def WriteImmediateCmdSet(self, func, f):
3785    """Overrriden from TypeHandler."""
3786    f.write("  void* Set(void* cmd%s) {\n" %
3787               func.MakeTypedInitString("_", True))
3788    f.write("    static_cast<ValueType*>(cmd)->Init(%s);\n" %
3789               func.MakeInitString("_"))
3790    f.write("    const uint32_t size = ComputeSize(_count);\n")
3791    f.write("    return NextImmediateCmdAddressTotalSize<ValueType>("
3792               "cmd, size);\n")
3793    f.write("  }\n")
3794    f.write("\n")
3795
3796  def WriteImmediateCmdHelper(self, func, f):
3797    """Overrriden from TypeHandler."""
3798    code = """  void %(name)s(%(typed_args)s) {
3799    const uint32_t size = %(lp)s::cmds::%(name)s::ComputeSize(count);
3800    %(lp)s::cmds::%(name)s* c =
3801        GetImmediateCmdSpaceTotalSize<%(lp)s::cmds::%(name)s>(size);
3802    if (c) {
3803      c->Init(%(args)s);
3804    }
3805  }
3806
3807"""
3808    f.write(code % {
3809          "lp" : _lower_prefix,
3810          "name": func.name,
3811          "typed_args": func.MakeTypedInitString(""),
3812          "args": func.MakeInitString("")
3813        })
3814
3815  def WriteImmediateFormatTest(self, func, f):
3816    """Overrriden from TypeHandler."""
3817    args = func.GetOriginalArgs()
3818    count_param = 0
3819    for arg in args:
3820      if arg.name == "count":
3821        count_param = int(arg.GetValidClientSideCmdArg(func))
3822    f.write("TEST_F(%sFormatTest, %s) {\n" % (_prefix, func.name))
3823    f.write("  const int kSomeBaseValueToTestWith = 51;\n")
3824    f.write("  static %s data[] = {\n" % self.GetArrayType(func))
3825    for v in range(0, self.GetArrayCount(func) * count_param):
3826      f.write("    static_cast<%s>(kSomeBaseValueToTestWith + %d),\n" %
3827                 (self.GetArrayType(func), v))
3828    f.write("  };\n")
3829    f.write("  cmds::%s& cmd = *GetBufferAs<cmds::%s>();\n" %
3830               (func.name, func.name))
3831    f.write("  const GLsizei kNumElements = %d;\n" % count_param)
3832    f.write("  const size_t kExpectedCmdSize =\n")
3833    f.write("      sizeof(cmd) + kNumElements * sizeof(%s) * %d;\n" %
3834               (self.GetArrayType(func), self.GetArrayCount(func)))
3835    f.write("  void* next_cmd = cmd.Set(\n")
3836    f.write("      &cmd")
3837    for value, arg in enumerate(args):
3838      if arg.IsPointer():
3839        f.write(",\n      data")
3840      elif arg.IsConstant():
3841        continue
3842      else:
3843        f.write(",\n      static_cast<%s>(%d)" % (arg.type, value + 1))
3844    f.write(");\n")
3845    f.write("  EXPECT_EQ(static_cast<uint32_t>(cmds::%s::kCmdId),\n" %
3846               func.name)
3847    f.write("            cmd.header.command);\n")
3848    f.write("  EXPECT_EQ(kExpectedCmdSize, cmd.header.size * 4u);\n")
3849    for value, arg in enumerate(args):
3850      if arg.IsPointer() or arg.IsConstant():
3851        continue
3852      f.write("  EXPECT_EQ(static_cast<%s>(%d), %s);\n" %
3853                 (arg.type, value + 1, arg.GetArgAccessor('cmd')))
3854    f.write("  CheckBytesWrittenMatchesExpectedSize(\n")
3855    f.write("      next_cmd, sizeof(cmd) +\n")
3856    f.write("      RoundSizeToMultipleOfEntries(sizeof(data)));\n")
3857    # TODO: Check that data was inserted
3858    f.write("}\n")
3859    f.write("\n")
3860
3861class PUTSTRHandler(ArrayArgTypeHandler):
3862  """Handler for functions that pass a string array."""
3863
3864  def __GetDataArg(self, func):
3865    """Return the argument that points to the 2D char arrays"""
3866    for arg in func.GetOriginalArgs():
3867      if arg.IsPointer2D():
3868        return arg
3869    return None
3870
3871  def __GetLengthArg(self, func):
3872    """Return the argument that holds length for each char array"""
3873    for arg in func.GetOriginalArgs():
3874      if arg.IsPointer() and not arg.IsPointer2D():
3875        return arg
3876    return None
3877
3878  def WriteGLES2Implementation(self, func, f):
3879    """Overrriden from TypeHandler."""
3880    f.write("%s %sImplementation::%s(%s) {\n" %
3881               (func.return_type, _prefix, func.original_name,
3882                func.MakeTypedOriginalArgString("")))
3883    f.write("  GPU_CLIENT_SINGLE_THREAD_CHECK();\n")
3884    func.WriteDestinationInitalizationValidation(f)
3885    self.WriteClientGLCallLog(func, f)
3886    data_arg = self.__GetDataArg(func)
3887    length_arg = self.__GetLengthArg(func)
3888    log_code_block = """  GPU_CLIENT_LOG_CODE_BLOCK({
3889    for (GLsizei ii = 0; ii < count; ++ii) {
3890      if (%(data)s[ii]) {"""
3891    if length_arg == None:
3892      log_code_block += """
3893        GPU_CLIENT_LOG("  " << ii << ": ---\\n" << %(data)s[ii] << "\\n---");"""
3894    else:
3895      log_code_block += """
3896        if (%(length)s && %(length)s[ii] >= 0) {
3897          const std::string my_str(%(data)s[ii], %(length)s[ii]);
3898          GPU_CLIENT_LOG("  " << ii << ": ---\\n" << my_str << "\\n---");
3899        } else {
3900          GPU_CLIENT_LOG("  " << ii << ": ---\\n" << %(data)s[ii] << "\\n---");
3901        }"""
3902    log_code_block += """
3903      } else {
3904        GPU_CLIENT_LOG("  " << ii << ": NULL");
3905      }
3906    }
3907  });
3908"""
3909    f.write(log_code_block % {
3910          'data': data_arg.name,
3911          'length': length_arg.name if not length_arg == None else ''
3912      })
3913    for arg in func.GetOriginalArgs():
3914      arg.WriteClientSideValidationCode(f, func)
3915
3916    bucket_args = []
3917    for arg in func.GetOriginalArgs():
3918      if arg.name == 'count' or arg == self.__GetLengthArg(func):
3919        continue
3920      if arg == self.__GetDataArg(func):
3921        bucket_args.append('kResultBucketId')
3922      else:
3923        bucket_args.append(arg.name)
3924    code_block = """
3925  if (!PackStringsToBucket(count, %(data)s, %(length)s, "gl%(func_name)s")) {
3926    return;
3927  }
3928  helper_->%(func_name)sBucket(%(bucket_args)s);
3929  helper_->SetBucketSize(kResultBucketId, 0);
3930  CheckGLError();
3931}
3932
3933"""
3934    f.write(code_block % {
3935        'data': data_arg.name,
3936        'length': length_arg.name if not length_arg == None else 'nullptr',
3937        'func_name': func.name,
3938        'bucket_args': ', '.join(bucket_args),
3939      })
3940
3941  def WriteGLES2ImplementationUnitTest(self, func, f):
3942    """Overrriden from TypeHandler."""
3943    code = """
3944TEST_F(%(prefix)sImplementationTest, %(name)s) {
3945  const uint32_t kBucketId = %(prefix)sImplementation::kResultBucketId;
3946  const char* kString1 = "happy";
3947  const char* kString2 = "ending";
3948  const size_t kString1Size = ::strlen(kString1) + 1;
3949  const size_t kString2Size = ::strlen(kString2) + 1;
3950  const size_t kHeaderSize = sizeof(GLint) * 3;
3951  const size_t kSourceSize = kHeaderSize + kString1Size + kString2Size;
3952  const size_t kPaddedHeaderSize =
3953      transfer_buffer_->RoundToAlignment(kHeaderSize);
3954  const size_t kPaddedString1Size =
3955      transfer_buffer_->RoundToAlignment(kString1Size);
3956  const size_t kPaddedString2Size =
3957      transfer_buffer_->RoundToAlignment(kString2Size);
3958  struct Cmds {
3959    cmd::SetBucketSize set_bucket_size;
3960    cmd::SetBucketData set_bucket_header;
3961    cmd::SetToken set_token1;
3962    cmd::SetBucketData set_bucket_data1;
3963    cmd::SetToken set_token2;
3964    cmd::SetBucketData set_bucket_data2;
3965    cmd::SetToken set_token3;
3966    cmds::%(name)sBucket cmd_bucket;
3967    cmd::SetBucketSize clear_bucket_size;
3968  };
3969
3970  ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize);
3971  ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size);
3972  ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size);
3973
3974  Cmds expected;
3975  expected.set_bucket_size.Init(kBucketId, kSourceSize);
3976  expected.set_bucket_header.Init(
3977      kBucketId, 0, kHeaderSize, mem0.id, mem0.offset);
3978  expected.set_token1.Init(GetNextToken());
3979  expected.set_bucket_data1.Init(
3980      kBucketId, kHeaderSize, kString1Size, mem1.id, mem1.offset);
3981  expected.set_token2.Init(GetNextToken());
3982  expected.set_bucket_data2.Init(
3983      kBucketId, kHeaderSize + kString1Size, kString2Size, mem2.id,
3984      mem2.offset);
3985  expected.set_token3.Init(GetNextToken());
3986  expected.cmd_bucket.Init(%(bucket_args)s);
3987  expected.clear_bucket_size.Init(kBucketId, 0);
3988  const char* kStrings[] = { kString1, kString2 };
3989  gl_->%(name)s(%(gl_args)s);
3990  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3991}
3992"""
3993    gl_args = []
3994    bucket_args = []
3995    for arg in func.GetOriginalArgs():
3996      if arg == self.__GetDataArg(func):
3997        gl_args.append('kStrings')
3998        bucket_args.append('kBucketId')
3999      elif arg == self.__GetLengthArg(func):
4000        gl_args.append('nullptr')
4001      elif arg.name == 'count':
4002        gl_args.append('2')
4003      else:
4004        gl_args.append(arg.GetValidClientSideArg(func))
4005        bucket_args.append(arg.GetValidClientSideArg(func))
4006    f.write(code % {
4007        'prefix' : _prefix,
4008        'name': func.name,
4009        'gl_args': ", ".join(gl_args),
4010        'bucket_args': ", ".join(bucket_args),
4011      })
4012
4013    if self.__GetLengthArg(func) == None:
4014      return
4015    code = """
4016TEST_F(%(prefix)sImplementationTest, %(name)sWithLength) {
4017  const uint32_t kBucketId = %(prefix)sImplementation::kResultBucketId;
4018  const char* kString = "foobar******";
4019  const size_t kStringSize = 6;  // We only need "foobar".
4020  const size_t kHeaderSize = sizeof(GLint) * 2;
4021  const size_t kSourceSize = kHeaderSize + kStringSize + 1;
4022  const size_t kPaddedHeaderSize =
4023      transfer_buffer_->RoundToAlignment(kHeaderSize);
4024  const size_t kPaddedStringSize =
4025      transfer_buffer_->RoundToAlignment(kStringSize + 1);
4026  struct Cmds {
4027    cmd::SetBucketSize set_bucket_size;
4028    cmd::SetBucketData set_bucket_header;
4029    cmd::SetToken set_token1;
4030    cmd::SetBucketData set_bucket_data;
4031    cmd::SetToken set_token2;
4032    cmds::ShaderSourceBucket shader_source_bucket;
4033    cmd::SetBucketSize clear_bucket_size;
4034  };
4035
4036  ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize);
4037  ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedStringSize);
4038
4039  Cmds expected;
4040  expected.set_bucket_size.Init(kBucketId, kSourceSize);
4041  expected.set_bucket_header.Init(
4042      kBucketId, 0, kHeaderSize, mem0.id, mem0.offset);
4043  expected.set_token1.Init(GetNextToken());
4044  expected.set_bucket_data.Init(
4045      kBucketId, kHeaderSize, kStringSize + 1, mem1.id, mem1.offset);
4046  expected.set_token2.Init(GetNextToken());
4047  expected.shader_source_bucket.Init(%(bucket_args)s);
4048  expected.clear_bucket_size.Init(kBucketId, 0);
4049  const char* kStrings[] = { kString };
4050  const GLint kLength[] = { kStringSize };
4051  gl_->%(name)s(%(gl_args)s);
4052  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
4053}
4054"""
4055    gl_args = []
4056    for arg in func.GetOriginalArgs():
4057      if arg == self.__GetDataArg(func):
4058        gl_args.append('kStrings')
4059      elif arg == self.__GetLengthArg(func):
4060        gl_args.append('kLength')
4061      elif arg.name == 'count':
4062        gl_args.append('1')
4063      else:
4064        gl_args.append(arg.GetValidClientSideArg(func))
4065    f.write(code % {
4066        'prefix' : _prefix,
4067        'name': func.name,
4068        'gl_args': ", ".join(gl_args),
4069        'bucket_args': ", ".join(bucket_args),
4070      })
4071
4072  def WriteBucketServiceUnitTest(self, func, f, *extras):
4073    """Overrriden from TypeHandler."""
4074    cmd_args = []
4075    cmd_args_with_invalid_id = []
4076    gl_args = []
4077    for index, arg in enumerate(func.GetOriginalArgs()):
4078      if arg == self.__GetLengthArg(func):
4079        gl_args.append('_')
4080      elif arg.name == 'count':
4081        gl_args.append('1')
4082      elif arg == self.__GetDataArg(func):
4083        cmd_args.append('kBucketId')
4084        cmd_args_with_invalid_id.append('kBucketId')
4085        gl_args.append('_')
4086      elif index == 0:  # Resource ID arg
4087        cmd_args.append(arg.GetValidArg(func))
4088        cmd_args_with_invalid_id.append('kInvalidClientId')
4089        gl_args.append(arg.GetValidGLArg(func))
4090      else:
4091        cmd_args.append(arg.GetValidArg(func))
4092        cmd_args_with_invalid_id.append(arg.GetValidArg(func))
4093        gl_args.append(arg.GetValidGLArg(func))
4094
4095    test = """
4096TEST_P(%(test_name)s, %(name)sValidArgs) {
4097  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s));
4098  const uint32_t kBucketId = 123;
4099  const char kSource0[] = "hello";
4100  const char* kSource[] = { kSource0 };
4101  const char kValidStrEnd = 0;
4102  SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd);
4103  cmds::%(name)s cmd;
4104  cmd.Init(%(cmd_args)s);
4105  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));"""
4106    test += """
4107}
4108"""
4109    self.WriteValidUnitTest(func, f, test, {
4110        'cmd_args': ", ".join(cmd_args),
4111        'gl_args': ", ".join(gl_args),
4112      }, *extras)
4113
4114    test = """
4115TEST_P(%(test_name)s, %(name)sInvalidArgs) {
4116  const uint32_t kBucketId = 123;
4117  const char kSource0[] = "hello";
4118  const char* kSource[] = { kSource0 };
4119  const char kValidStrEnd = 0;
4120  cmds::%(name)s cmd;
4121  // Test no bucket.
4122  cmd.Init(%(cmd_args)s);
4123  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
4124  // Test invalid client.
4125  SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd);
4126  cmd.Init(%(cmd_args_with_invalid_id)s);
4127  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
4128  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
4129}
4130"""
4131    self.WriteValidUnitTest(func, f, test, {
4132        'cmd_args': ", ".join(cmd_args),
4133        'cmd_args_with_invalid_id': ", ".join(cmd_args_with_invalid_id),
4134      }, *extras)
4135
4136    test = """
4137TEST_P(%(test_name)s, %(name)sInvalidHeader) {
4138  const uint32_t kBucketId = 123;
4139  const char kSource0[] = "hello";
4140  const char* kSource[] = { kSource0 };
4141  const char kValidStrEnd = 0;
4142  const GLsizei kCount = static_cast<GLsizei>(base::size(kSource));
4143  const GLsizei kTests[] = {
4144      kCount + 1,
4145      0,
4146      std::numeric_limits<GLsizei>::max(),
4147      -1,
4148  };
4149  for (size_t ii = 0; ii < base::size(kTests); ++ii) {
4150    SetBucketAsCStrings(kBucketId, 1, kSource, kTests[ii], kValidStrEnd);
4151    cmds::%(name)s cmd;
4152    cmd.Init(%(cmd_args)s);
4153    EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd));
4154  }
4155}
4156"""
4157    self.WriteValidUnitTest(func, f, test, {
4158        'cmd_args': ", ".join(cmd_args),
4159      }, *extras)
4160
4161    test = """
4162TEST_P(%(test_name)s, %(name)sInvalidStringEnding) {
4163  const uint32_t kBucketId = 123;
4164  const char kSource0[] = "hello";
4165  const char* kSource[] = { kSource0 };
4166  const char kInvalidStrEnd = '*';
4167  SetBucketAsCStrings(kBucketId, 1, kSource, 1, kInvalidStrEnd);
4168  cmds::%(name)s cmd;
4169  cmd.Init(%(cmd_args)s);
4170  EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd));
4171}
4172"""
4173    self.WriteValidUnitTest(func, f, test, {
4174        'cmd_args': ", ".join(cmd_args),
4175      }, *extras)
4176
4177
4178class PUTXnHandler(ArrayArgTypeHandler):
4179  """Handler for glUniform?f functions."""
4180
4181  def WriteHandlerImplementation(self, func, f):
4182    """Overrriden from TypeHandler."""
4183    code = """  %(type)s temp[%(count)s] = { %(values)s};
4184  Do%(name)sv(%(location)s, 1, &temp[0]);
4185"""
4186    values = ""
4187    args = func.GetOriginalArgs()
4188    count = int(self.GetArrayCount(func))
4189    for ii in range(count):
4190      values += "%s, " % args[len(args) - count + ii].name
4191
4192    f.write(code % {
4193        'name': func.name,
4194        'count': self.GetArrayCount(func),
4195        'type': self.GetArrayType(func),
4196        'location': args[0].name,
4197        'args': func.MakeOriginalArgString(""),
4198        'values': values,
4199      })
4200
4201  def WriteServiceUnitTest(self, func, f, *extras):
4202    """Overrriden from TypeHandler."""
4203    valid_test = """
4204TEST_P(%(test_name)s, %(name)sValidArgs) {
4205  EXPECT_CALL(*gl_, %(name)sv(%(local_args)s));
4206  SpecializedSetup<cmds::%(name)s, 0>(true);
4207  cmds::%(name)s cmd;
4208  cmd.Init(%(args)s);
4209  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
4210  EXPECT_EQ(GL_NO_ERROR, GetGLError());
4211}
4212"""
4213    args = func.GetOriginalArgs()
4214    local_args = "%s, 1, _" % args[0].GetValidGLArg(func)
4215    self.WriteValidUnitTest(func, f, valid_test, {
4216        'name': func.name,
4217        'count': self.GetArrayCount(func),
4218        'local_args': local_args,
4219      }, *extras)
4220
4221    invalid_test = """
4222TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
4223  EXPECT_CALL(*gl_, %(name)sv(_, _, _).Times(0);
4224  SpecializedSetup<cmds::%(name)s, 0>(false);
4225  cmds::%(name)s cmd;
4226  cmd.Init(%(args)s);
4227  EXPECT_EQ(error::%(parse_result)s, ExecuteCmd(cmd));%(gl_error_test)s
4228}
4229"""
4230    self.WriteInvalidUnitTest(func, f, invalid_test, {
4231        'name': func.GetInfo('name'),
4232        'count': self.GetArrayCount(func),
4233      })
4234
4235
4236class GLcharHandler(CustomHandler):
4237  """Handler for functions that pass a single string ."""
4238
4239  def WriteImmediateCmdComputeSize(self, _func, f):
4240    """Overrriden from TypeHandler."""
4241    f.write("  static uint32_t ComputeSize(uint32_t data_size) {\n")
4242    f.write("    return static_cast<uint32_t>(\n")
4243    f.write("        sizeof(ValueType) + data_size);  // NOLINT\n")
4244    f.write("  }\n")
4245
4246  def WriteImmediateCmdSetHeader(self, _func, f):
4247    """Overrriden from TypeHandler."""
4248    code = """
4249  void SetHeader(uint32_t data_size) {
4250    header.SetCmdBySize<ValueType>(data_size);
4251  }
4252"""
4253    f.write(code)
4254
4255  def WriteImmediateCmdInit(self, func, f):
4256    """Overrriden from TypeHandler."""
4257    last_arg = func.GetLastOriginalArg()
4258    args = func.GetCmdArgs()
4259    code = """
4260  void Init(%s, uint32_t _data_size) {
4261    SetHeader(_data_size);
4262"""
4263    f.write(code % func.MakeTypedArgString("_"))
4264    for arg in args:
4265      arg.WriteSetCode(f, 4, "_%s" % arg.name)
4266    code = """
4267    memcpy(ImmediateDataAddress(this), _%s, _data_size);
4268  }
4269
4270"""
4271    f.write(code % last_arg.name)
4272
4273  def WriteImmediateCmdSet(self, func, f):
4274    """Overrriden from TypeHandler."""
4275    f.write("  void* Set(void* cmd%s, uint32_t _data_size) {\n" %
4276               func.MakeTypedCmdArgString("_", True))
4277    f.write("    static_cast<ValueType*>(cmd)->Init(%s, _data_size);\n" %
4278               func.MakeCmdArgString("_"))
4279    f.write("    return NextImmediateCmdAddress<ValueType>("
4280               "cmd, _data_size);\n")
4281    f.write("  }\n")
4282    f.write("\n")
4283
4284  def WriteImmediateCmdHelper(self, func, f):
4285    """Overrriden from TypeHandler."""
4286    code = """  void %(name)s(%(typed_args)s) {
4287    const uint32_t data_size = strlen(name);
4288    %(lp)s::cmds::%(name)s* c =
4289        GetImmediateCmdSpace<%(lp)s::cmds::%(name)s>(data_size);
4290    if (c) {
4291      c->Init(%(args)s, data_size);
4292    }
4293  }
4294
4295"""
4296    f.write(code % {
4297          "lp" : _lower_prefix,
4298          "name": func.name,
4299          "typed_args": func.MakeTypedOriginalArgString(""),
4300          "args": func.MakeOriginalArgString(""),
4301        })
4302
4303
4304  def WriteImmediateFormatTest(self, func, f):
4305    """Overrriden from TypeHandler."""
4306    init_code = []
4307    check_code = []
4308    all_but_last_arg = func.GetCmdArgs()[:-1]
4309    for value, arg in enumerate(all_but_last_arg):
4310      init_code.append("      static_cast<%s>(%d)," % (arg.type, value + 11))
4311    for value, arg in enumerate(all_but_last_arg):
4312      check_code.append("  EXPECT_EQ(static_cast<%s>(%d), %s);" %
4313                        (arg.type, value + 11, arg.GetArgAccessor('cmd')))
4314    code = """
4315TEST_F(%(prefix)sFormatTest, %(func_name)s) {
4316  cmds::%(func_name)s& cmd = *GetBufferAs<cmds::%(func_name)s>();
4317  static const char* const test_str = \"test string\";
4318  void* next_cmd = cmd.Set(
4319      &cmd,
4320%(init_code)s
4321      test_str,
4322      strlen(test_str));
4323  EXPECT_EQ(static_cast<uint32_t>(cmds::%(func_name)s::kCmdId),
4324            cmd.header.command);
4325  EXPECT_EQ(sizeof(cmd) +
4326            RoundSizeToMultipleOfEntries(strlen(test_str)),
4327            cmd.header.size * 4u);
4328  EXPECT_EQ(static_cast<char*>(next_cmd),
4329            reinterpret_cast<char*>(&cmd) + sizeof(cmd) +
4330                RoundSizeToMultipleOfEntries(strlen(test_str)));
4331%(check_code)s
4332  EXPECT_EQ(static_cast<uint32_t>(strlen(test_str)), cmd.data_size);
4333  EXPECT_EQ(0, memcmp(test_str, ImmediateDataAddress(&cmd), strlen(test_str)));
4334  CheckBytesWritten(
4335      next_cmd,
4336      sizeof(cmd) + RoundSizeToMultipleOfEntries(strlen(test_str)),
4337      sizeof(cmd) + strlen(test_str));
4338}
4339
4340"""
4341    f.write(code % {
4342          'prefix': _prefix,
4343          'func_name': func.name,
4344          'init_code': "\n".join(init_code),
4345          'check_code': "\n".join(check_code),
4346        })
4347
4348
4349class GLcharNHandler(CustomHandler):
4350  """Handler for functions that pass a single string with an optional len."""
4351
4352  def InitFunction(self, func):
4353    """Overrriden from TypeHandler."""
4354    func.cmd_args = []
4355    func.AddCmdArg(Argument('bucket_id', 'GLuint'))
4356
4357  def NeedsDataTransferFunction(self, func):
4358    """Overriden from TypeHandler."""
4359    return False
4360
4361  def WriteServiceImplementation(self, func, f):
4362    """Overrriden from TypeHandler."""
4363    self.WriteServiceHandlerFunctionHeader(func, f)
4364    if func.IsES31():
4365      return
4366    f.write("""
4367  GLuint bucket_id = static_cast<GLuint>(c.%(bucket_id)s);
4368  Bucket* bucket = GetBucket(bucket_id);
4369  if (!bucket || bucket->size() == 0) {
4370    return error::kInvalidArguments;
4371  }
4372  std::string str;
4373  if (!bucket->GetAsString(&str)) {
4374    return error::kInvalidArguments;
4375  }
4376  %(gl_func_name)s(0, str.c_str());
4377  return error::kNoError;
4378}
4379
4380""" % {
4381    'gl_func_name': func.GetGLFunctionName(),
4382    'bucket_id': func.cmd_args[0].name,
4383  })
4384
4385
4386class IsHandler(TypeHandler):
4387  """Handler for glIs____ type and glGetError functions."""
4388
4389  def InitFunction(self, func):
4390    """Overrriden from TypeHandler."""
4391    func.AddCmdArg(Argument("result_shm_id", 'uint32_t'))
4392    func.AddCmdArg(Argument("result_shm_offset", 'uint32_t'))
4393    if func.GetInfo('result') == None:
4394      func.AddInfo('result', ['uint32_t'])
4395    func.passthrough_service_doer_args.append(Argument('result', 'uint32_t*'))
4396
4397  def WriteServiceUnitTest(self, func, f, *extras):
4398    """Overrriden from TypeHandler."""
4399    valid_test = """
4400TEST_P(%(test_name)s, %(name)sValidArgs) {
4401  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s));
4402  SpecializedSetup<cmds::%(name)s, 0>(true);
4403  cmds::%(name)s cmd;
4404  cmd.Init(%(args)s%(comma)sshared_memory_id_, shared_memory_offset_);
4405  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
4406  EXPECT_EQ(GL_NO_ERROR, GetGLError());
4407}
4408"""
4409    comma = ""
4410    if len(func.GetOriginalArgs()):
4411      comma =", "
4412    self.WriteValidUnitTest(func, f, valid_test, {
4413          'comma': comma,
4414        }, *extras)
4415
4416    invalid_test = """
4417TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
4418  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)).Times(0);
4419  SpecializedSetup<cmds::%(name)s, 0>(false);
4420  cmds::%(name)s cmd;
4421  cmd.Init(%(args)s%(comma)sshared_memory_id_, shared_memory_offset_);
4422  EXPECT_EQ(error::%(parse_result)s, ExecuteCmd(cmd));%(gl_error_test)s
4423}
4424"""
4425    self.WriteInvalidUnitTest(func, f, invalid_test, {
4426          'comma': comma,
4427        }, *extras)
4428
4429    invalid_test = """
4430TEST_P(%(test_name)s, %(name)sInvalidArgsBadSharedMemoryId) {
4431  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)).Times(0);
4432  SpecializedSetup<cmds::%(name)s, 0>(false);
4433  cmds::%(name)s cmd;
4434  cmd.Init(%(args)s%(comma)skInvalidSharedMemoryId, shared_memory_offset_);
4435  EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
4436  cmd.Init(%(args)s%(comma)sshared_memory_id_, kInvalidSharedMemoryOffset);
4437  EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
4438}
4439"""
4440    self.WriteValidUnitTest(func, f, invalid_test, {
4441          'comma': comma,
4442        }, *extras)
4443
4444  def WriteServiceImplementation(self, func, f):
4445    """Overrriden from TypeHandler."""
4446    self.WriteServiceHandlerFunctionHeader(func, f)
4447    if func.IsES31():
4448      return
4449    self.WriteHandlerExtensionCheck(func, f)
4450    args = func.GetOriginalArgs()
4451    for arg in args:
4452      arg.WriteGetCode(f)
4453
4454    code = """  typedef cmds::%(func_name)s::Result Result;
4455  Result* result_dst = GetSharedMemoryAs<Result*>(
4456      c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
4457  if (!result_dst) {
4458    return error::kOutOfBounds;
4459  }
4460"""
4461    f.write(code % {'func_name': func.name})
4462    func.WriteHandlerValidation(f)
4463    f.write("  *result_dst = %s(%s);\n" %
4464            (func.GetGLFunctionName(), func.MakeOriginalArgString("")))
4465    f.write("  return error::kNoError;\n")
4466    f.write("}\n")
4467    f.write("\n")
4468
4469  def WritePassthroughServiceImplementation(self, func, f):
4470    """Overrriden from TypeHandler."""
4471    self.WritePassthroughServiceFunctionHeader(func, f)
4472    self.WriteHandlerExtensionCheck(func, f)
4473    self.WriteServiceHandlerArgGetCode(func, f)
4474
4475    code = """  typedef cmds::%(func_name)s::Result Result;
4476  Result* result = GetSharedMemoryAs<Result*>(
4477      c.result_shm_id, c.result_shm_offset, sizeof(*result));
4478  if (!result) {
4479    return error::kOutOfBounds;
4480  }
4481"""
4482    f.write(code % {'func_name': func.name})
4483    self.WritePassthroughServiceFunctionDoerCall(func, f)
4484    f.write("  return error::kNoError;\n")
4485    f.write("}\n")
4486    f.write("\n")
4487
4488  def WriteGLES2Implementation(self, func, f):
4489    """Overrriden from TypeHandler."""
4490    impl_func = func.GetInfo('impl_func', True)
4491    if impl_func:
4492      error_value = func.GetInfo("error_value") or "GL_FALSE"
4493      f.write("%s %sImplementation::%s(%s) {\n" %
4494                 (func.return_type, _prefix, func.original_name,
4495                  func.MakeTypedOriginalArgString("")))
4496      f.write("  GPU_CLIENT_SINGLE_THREAD_CHECK();\n")
4497      self.WriteTraceEvent(func, f)
4498      func.WriteDestinationInitalizationValidation(f)
4499      self.WriteClientGLCallLog(func, f)
4500      f.write("  typedef cmds::%s::Result Result;\n" % func.name)
4501      f.write("  ScopedResultPtr<Result> result = GetResultAs<Result>();\n")
4502      f.write("  if (!result) {\n")
4503      f.write("    return %s;\n" % error_value)
4504      f.write("  }\n")
4505      f.write("  *result = 0;\n")
4506      assert len(func.GetOriginalArgs()) == 1
4507      id_arg = func.GetOriginalArgs()[0]
4508      if id_arg.type == 'GLsync':
4509        arg_string = "ToGLuint(%s)" % func.MakeOriginalArgString("")
4510      else:
4511        arg_string = func.MakeOriginalArgString("")
4512      f.write(
4513          "  helper_->%s(%s, GetResultShmId(), result.offset());\n" %
4514              (func.name, arg_string))
4515      f.write("  WaitForCmd();\n")
4516      f.write("  %s result_value = *result" % func.return_type)
4517      if func.return_type == "GLboolean":
4518        f.write(" != 0")
4519      f.write(';\n  GPU_CLIENT_LOG("returned " << result_value);\n')
4520      f.write("  CheckGLError();\n")
4521      f.write("  return result_value;\n")
4522      f.write("}\n")
4523      f.write("\n")
4524
4525  def WriteGLES2ImplementationUnitTest(self, func, f):
4526    """Overrriden from TypeHandler."""
4527    client_test = func.GetInfo('client_test', True)
4528    if client_test:
4529      code = """
4530TEST_F(%(prefix)sImplementationTest, %(name)s) {
4531  struct Cmds {
4532    cmds::%(name)s cmd;
4533  };
4534
4535  Cmds expected;
4536  ExpectedMemoryInfo result1 =
4537      GetExpectedResultMemory(sizeof(cmds::%(name)s::Result));
4538  expected.cmd.Init(%(cmd_id_value)s, result1.id, result1.offset);
4539
4540  EXPECT_CALL(*command_buffer(), OnFlush())
4541      .WillOnce(SetMemory(result1.ptr, uint32_t(GL_TRUE)))
4542      .RetiresOnSaturation();
4543
4544  GLboolean result = gl_->%(name)s(%(gl_id_value)s);
4545  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
4546  EXPECT_TRUE(result);
4547}
4548"""
4549      args = func.GetOriginalArgs()
4550      assert len(args) == 1
4551      f.write(code % {
4552          'prefix' : _prefix,
4553          'name': func.name,
4554          'cmd_id_value': args[0].GetValidClientSideCmdArg(func),
4555          'gl_id_value': args[0].GetValidClientSideArg(func) })
4556
4557  def WriteImmediateCmdInit(self, func, f):
4558    """Overrriden from TypeHandler."""
4559    pass
4560
4561  def WriteImmediateCmdSet(self, func, f):
4562    """Overrriden from TypeHandler."""
4563    pass
4564
4565
4566class STRnHandler(TypeHandler):
4567  """Handler for GetProgramInfoLog, GetShaderInfoLog, GetShaderSource, and
4568  GetTranslatedShaderSourceANGLE."""
4569
4570  def InitFunction(self, func):
4571    """Overrriden from TypeHandler."""
4572    # remove all but the first cmd args.
4573    cmd_args = func.GetCmdArgs()
4574    func.ClearCmdArgs()
4575    func.AddCmdArg(cmd_args[0])
4576    # add on a bucket id.
4577    func.AddCmdArg(Argument('bucket_id', 'uint32_t'))
4578
4579  def WriteGLES2Implementation(self, func, f):
4580    """Overrriden from TypeHandler."""
4581    code_1 = """%(return_type)s %(prefix)sImplementation::%(func_name)s(
4582    %(args)s) {
4583  GPU_CLIENT_SINGLE_THREAD_CHECK();
4584"""
4585    code_2 = """  GPU_CLIENT_LOG("[" << GetLogPrefix()
4586      << "] gl%(func_name)s" << "("
4587      << %(arg0)s << ", "
4588      << %(arg1)s << ", "
4589      << static_cast<void*>(%(arg2)s) << ", "
4590      << static_cast<void*>(%(arg3)s) << ")");
4591  helper_->SetBucketSize(kResultBucketId, 0);
4592  helper_->%(func_name)s(%(id_name)s, kResultBucketId);
4593  std::string str;
4594  GLsizei max_size = 0;
4595  if (GetBucketAsString(kResultBucketId, &str)) {
4596    if (bufsize > 0) {
4597      max_size =
4598          std::min(static_cast<size_t>(%(bufsize_name)s) - 1, str.size());
4599      memcpy(%(dest_name)s, str.c_str(), max_size);
4600      %(dest_name)s[max_size] = '\\0';
4601      GPU_CLIENT_LOG("------\\n" << %(dest_name)s << "\\n------");
4602    }
4603  }
4604  if (%(length_name)s != nullptr) {
4605    *%(length_name)s = max_size;
4606  }
4607  CheckGLError();
4608}
4609"""
4610    args = func.GetOriginalArgs()
4611    str_args = {
4612      'prefix' : _prefix,
4613      'return_type': func.return_type,
4614      'func_name': func.original_name,
4615      'args': func.MakeTypedOriginalArgString(""),
4616      'id_name': args[0].name,
4617      'bufsize_name': args[1].name,
4618      'length_name': args[2].name,
4619      'dest_name': args[3].name,
4620      'arg0': args[0].name,
4621      'arg1': args[1].name,
4622      'arg2': args[2].name,
4623      'arg3': args[3].name,
4624    }
4625    f.write(code_1 % str_args)
4626    func.WriteDestinationInitalizationValidation(f)
4627    f.write(code_2 % str_args)
4628
4629  def WriteServiceUnitTest(self, func, f, *extras):
4630    """Overrriden from TypeHandler."""
4631    valid_test = """
4632TEST_P(%(test_name)s, %(name)sValidArgs) {
4633  const char* kInfo = "hello";
4634  const uint32_t kBucketId = 123;
4635  SpecializedSetup<cmds::%(name)s, 0>(true);
4636%(expect_len_code)s
4637  EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s))
4638      .WillOnce(DoAll(SetArgPointee<2>(strlen(kInfo)),
4639                      SetArrayArgument<3>(kInfo, kInfo + strlen(kInfo) + 1)));
4640  cmds::%(name)s cmd;
4641  cmd.Init(%(args)s);
4642  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
4643  CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
4644  ASSERT_TRUE(bucket != nullptr);
4645  EXPECT_EQ(strlen(kInfo) + 1, bucket->size());
4646  EXPECT_EQ(0, memcmp(bucket->GetData(0, bucket->size()), kInfo,
4647                      bucket->size()));
4648  EXPECT_EQ(GL_NO_ERROR, GetGLError());
4649}
4650"""
4651    args = func.GetOriginalArgs()
4652    id_name = args[0].GetValidGLArg(func)
4653    get_len_func = func.GetInfo('get_len_func')
4654    get_len_enum = func.GetInfo('get_len_enum')
4655    sub = {
4656        'id_name': id_name,
4657        'get_len_func': get_len_func,
4658        'get_len_enum': get_len_enum,
4659        'gl_args': '%s, strlen(kInfo) + 1, _, _' %
4660             args[0].GetValidGLArg(func),
4661        'args': '%s, kBucketId' % args[0].GetValidArg(func),
4662        'expect_len_code': '',
4663    }
4664    if get_len_func and get_len_func[0:2] == 'gl':
4665      sub['expect_len_code'] = (
4666        "  EXPECT_CALL(*gl_, %s(%s, %s, _))\n"
4667        "      .WillOnce(SetArgPointee<2>(strlen(kInfo) + 1));") % (
4668            get_len_func[2:], id_name, get_len_enum)
4669    self.WriteValidUnitTest(func, f, valid_test, sub, *extras)
4670
4671    invalid_test = """
4672TEST_P(%(test_name)s, %(name)sInvalidArgs) {
4673  const uint32_t kBucketId = 123;
4674  EXPECT_CALL(*gl_, %(gl_func_name)s(_, _, _, _))
4675      .Times(0);
4676  cmds::%(name)s cmd;
4677  cmd.Init(kInvalidClientId, kBucketId);
4678  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
4679  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
4680}
4681"""
4682    self.WriteValidUnitTest(func, f, invalid_test, *extras)
4683
4684  def WriteServiceImplementation(self, func, f):
4685    """Overrriden from TypeHandler."""
4686    if func.IsES31():
4687      TypeHandler.WriteServiceImplementation(self, func, f)
4688
4689  def WritePassthroughServiceImplementation(self, func, f):
4690    """Overrriden from TypeHandler."""
4691    pass
4692
4693  def WriteImmediateCmdInit(self, func, f):
4694    """Overrriden from TypeHandler."""
4695    pass
4696
4697  def WriteImmediateCmdSet(self, func, f):
4698    """Overrriden from TypeHandler."""
4699    pass
4700
4701
4702class NamedType(object):
4703  """A class that represents a type of an argument in a client function.
4704
4705  A type of an argument that is to be passed through in the command buffer
4706  command. Currently used only for the arguments that are specificly named in
4707  the 'cmd_buffer_functions.txt' f, mostly enums.
4708  """
4709
4710  def __init__(self, info):
4711    assert not 'is_complete' in info or info['is_complete'] == True
4712    self.info = info
4713    self.valid = info['valid']
4714    if 'invalid' in info:
4715      self.invalid = info['invalid']
4716    else:
4717      self.invalid = []
4718    if 'valid_es3' in info:
4719      self.valid_es3 = info['valid_es3']
4720    else:
4721      self.valid_es3 = []
4722    if 'deprecated_es3' in info:
4723      self.deprecated_es3 = info['deprecated_es3']
4724    else:
4725      self.deprecated_es3 = []
4726    self.create_validator = info.get('validator', True)
4727    self.is_complete = info.get('is_complete', False)
4728
4729  def GetType(self):
4730    return self.info['type']
4731
4732  def GetInvalidValues(self):
4733    return self.invalid
4734
4735  def GetValidValues(self):
4736    return self.valid
4737
4738  def GetValidValuesES3(self):
4739    return self.valid_es3
4740
4741  def GetDeprecatedValuesES3(self):
4742    return self.deprecated_es3
4743
4744  def HasES3Values(self):
4745    return self.valid_es3 or self.deprecated_es3
4746
4747  def IsConstant(self):
4748    return self.is_complete and len(self.GetValidValues()) == 1
4749
4750  def IsComplete(self):
4751    return self.is_complete
4752
4753  def CreateValidator(self):
4754    return self.create_validator and not self.IsConstant()
4755
4756  def GetConstantValue(self):
4757    return self.GetValidValues()[0]
4758
4759class Argument(object):
4760  """A class that represents a function argument."""
4761
4762  cmd_type_map_ = {
4763    'GLenum': ['uint32_t'],
4764    'GLint': ['int32_t'],
4765    'GLintptr': ['int32_t'],
4766    'GLsizei': ['int32_t'],
4767    'GLsizeiptr': ['int32_t'],
4768    'GLfloat': ['float'],
4769    'GLclampf': ['float'],
4770    'GLuint64': ['uint32_t', 'uint32_t'],
4771  }
4772  need_validation_ = ['GLsizei*', 'GLboolean*', 'GLenum*', 'GLint*']
4773
4774  def __init__(self, name, arg_type, arg_default = None):
4775    self.name = name
4776    self.optional = arg_type.endswith("Optional*")
4777    if self.optional:
4778      arg_type = arg_type[:-len("Optional*")] + "*"
4779    self.type = arg_type
4780    self.default = arg_default
4781
4782    if arg_type in self.cmd_type_map_:
4783      self.cmd_type = self.cmd_type_map_[arg_type]
4784    else:
4785      self.cmd_type = ['uint32_t']
4786
4787  def IsPointer(self):
4788    """Returns true if argument is a pointer."""
4789    return False
4790
4791  def IsPointer2D(self):
4792    """Returns true if argument is a 2D pointer."""
4793    return False
4794
4795  def IsConstant(self):
4796    """Returns true if the argument has only one valid value."""
4797    return False
4798
4799  def AddCmdArgs(self, args):
4800    """Adds command arguments for this argument to the given list."""
4801    if not self.IsConstant():
4802      return args.append(self)
4803
4804  def AddInitArgs(self, args):
4805    """Adds init arguments for this argument to the given list."""
4806    if not self.IsConstant():
4807      return args.append(self)
4808
4809  def GetValidArg(self, func):
4810    """Gets a valid value for this argument."""
4811    valid_arg = func.GetValidArg(self)
4812    if valid_arg != None:
4813      return valid_arg
4814
4815    index = func.GetOriginalArgs().index(self)
4816    return str(index + 1)
4817
4818  def GetArgDecls(self):
4819    if len(self.cmd_type) == 1:
4820      return [(self.cmd_type[0], self.name)]
4821    else:
4822      return [(cmd_type, self.name + '_%d' % i)
4823              for i, cmd_type
4824              in enumerate(self.cmd_type)]
4825
4826  def GetReservedSizeId(self):
4827    """Gets a special identifier name for the data size of this argument"""
4828    return "%s_size" % self.name
4829
4830  def GetValidClientSideArg(self, func):
4831    """Gets a valid value for this argument."""
4832    valid_arg = func.GetValidArg(self)
4833    if valid_arg != None:
4834      return valid_arg
4835
4836    if self.IsPointer():
4837      return 'nullptr'
4838    index = func.GetOriginalArgs().index(self)
4839    if self.type == 'GLsync':
4840      return ("reinterpret_cast<GLsync>(%d)" % (index + 1))
4841    return str(index + 1)
4842
4843  def GetValidClientSideCmdArg(self, func):
4844    """Gets a valid value for this argument."""
4845    valid_arg = func.GetValidArg(self)
4846    if valid_arg != None:
4847      return valid_arg
4848    try:
4849      index = func.GetOriginalArgs().index(self)
4850      return str(index + 1)
4851    except ValueError:
4852      pass
4853    index = func.GetCmdArgs().index(self)
4854    return str(index + 1)
4855
4856  def GetValidGLArg(self, func):
4857    """Gets a valid GL value for this argument."""
4858    value = self.GetValidArg(func)
4859    if self.type == 'GLsync':
4860      return ("reinterpret_cast<GLsync>(%s)" % value)
4861    return value
4862
4863  def GetValidNonCachedClientSideArg(self, _func):
4864    """Returns a valid value for this argument in a GL call.
4865    Using the value will produce a command buffer service invocation.
4866    Returns None if there is no such value."""
4867    value = '123'
4868    if self.type == 'GLsync':
4869      return ("reinterpret_cast<GLsync>(%s)" % value)
4870    return value
4871
4872  def GetValidNonCachedClientSideCmdArg(self, _func):
4873    """Returns a valid value for this argument in a command buffer command.
4874    Calling the GL function with the value returned by
4875    GetValidNonCachedClientSideArg will result in a command buffer command
4876    that contains the value returned by this function. """
4877    return '123'
4878
4879  def GetNumInvalidValues(self, _func):
4880    """returns the number of invalid values to be tested."""
4881    return 0
4882
4883  def GetInvalidArg(self, _index):
4884    """returns an invalid value and expected parse result by index."""
4885    return ("---ERROR0---", "---ERROR2---", None)
4886
4887  def GetArgAccessor(self, cmd_struct_name):
4888    """Returns the name of the accessor for the argument within the struct."""
4889    return '%s.%s' % (cmd_struct_name, self.name)
4890
4891  def GetLogArg(self):
4892    """Get argument appropriate for LOG macro."""
4893    if self.type == 'GLboolean':
4894      return '%sGLES2Util::GetStringBool(%s)' % (_Namespace(), self.name)
4895    if self.type == 'GLenum':
4896      return '%sGLES2Util::GetStringEnum(%s)' % (_Namespace(), self.name)
4897    return self.name
4898
4899  def WriteGetCode(self, f):
4900    """Writes the code to get an argument from a command structure."""
4901    if self.type == 'GLsync':
4902      my_type = 'GLuint'
4903    else:
4904      my_type = self.type
4905    f.write("  %s %s = static_cast<%s>(c.%s);\n" %
4906               (my_type, self.name, my_type, self.name))
4907
4908  def WriteSetCode(self, f, indent, var):
4909    f.write("%s%s = %s;\n" % (' ' * indent, self.name, var))
4910
4911  def WriteArgAccessor(self, f):
4912    """Writes specialized accessor for argument."""
4913    pass
4914
4915  def WriteValidationCode(self, f, func):
4916    """Writes the validation code for an argument."""
4917    pass
4918
4919  def WritePassthroughValidationCode(self, f, func):
4920    """Writes the passthrough validation code for an argument."""
4921    pass
4922
4923  def WriteClientSideValidationCode(self, f, func):
4924    """Writes the validation code for an argument."""
4925    pass
4926
4927  def WriteDestinationInitalizationValidation(self, f, func):
4928    """Writes the client side destintion initialization validation."""
4929    pass
4930
4931  def WriteDestinationInitalizationValidatationIfNeeded(self, f, _func):
4932    """Writes the client side destintion initialization validation if needed."""
4933    parts = self.type.split(" ")
4934    if len(parts) > 1:
4935      return
4936    if parts[0] in self.need_validation_:
4937      f.write(
4938          "  GPU_CLIENT_VALIDATE_DESTINATION_%sINITALIZATION(%s, %s);\n" %
4939          ("OPTIONAL_" if self.optional else "", self.type[:-1], self.name))
4940
4941  def GetImmediateVersion(self):
4942    """Gets the immediate version of this argument."""
4943    return self
4944
4945  def GetBucketVersion(self):
4946    """Gets the bucket version of this argument."""
4947    return self
4948
4949
4950class BoolArgument(Argument):
4951  """class for C++ bool"""
4952
4953  def __init__(self, name, _type, arg_default):
4954    Argument.__init__(self, name, _type, arg_default)
4955
4956  def GetValidArg(self, func):
4957    """Gets a valid value for this argument."""
4958    return 'true'
4959
4960  def GetValidClientSideArg(self, func):
4961    """Gets a valid value for this argument."""
4962    return 'true'
4963
4964  def GetValidClientSideCmdArg(self, func):
4965    """Gets a valid value for this argument."""
4966    return 'true'
4967
4968  def GetValidGLArg(self, func):
4969    """Gets a valid GL value for this argument."""
4970    return 'true'
4971
4972  def GetArgAccessor(self, struct_name):
4973    """Returns the name of the accessor for the argument within the struct."""
4974    return 'static_cast<bool>(%s.%s)' % (struct_name, self.name)
4975
4976
4977class GLBooleanArgument(Argument):
4978  """class for GLboolean"""
4979
4980  def __init__(self, name, _type, arg_default):
4981    Argument.__init__(self, name, 'GLboolean', arg_default)
4982
4983  def GetValidArg(self, func):
4984    """Gets a valid value for this argument."""
4985    return 'true'
4986
4987  def GetValidClientSideArg(self, func):
4988    """Gets a valid value for this argument."""
4989    return 'true'
4990
4991  def GetValidClientSideCmdArg(self, func):
4992    """Gets a valid value for this argument."""
4993    return 'true'
4994
4995  def GetValidGLArg(self, func):
4996    """Gets a valid GL value for this argument."""
4997    return 'true'
4998
4999
5000class UniformLocationArgument(Argument):
5001  """class for uniform locations."""
5002
5003  def __init__(self, name, arg_default):
5004    Argument.__init__(self, name, "GLint", arg_default)
5005
5006  def WriteGetCode(self, f):
5007    """Writes the code to get an argument from a command structure."""
5008    code = """  %s %s = static_cast<%s>(c.%s);
5009"""
5010    f.write(code % (self.type, self.name, self.type, self.name))
5011
5012class DataSizeArgument(Argument):
5013  """class for data_size which Bucket commands do not need."""
5014
5015  def __init__(self, name):
5016    Argument.__init__(self, name, "uint32_t")
5017
5018  def GetBucketVersion(self):
5019    return None
5020
5021
5022class SizeArgument(Argument):
5023  """class for GLsizei and GLsizeiptr."""
5024
5025  def GetNumInvalidValues(self, func):
5026    """overridden from Argument."""
5027    if func.IsImmediate():
5028      return 0
5029    return 1
5030
5031  def GetInvalidArg(self, _index):
5032    """overridden from Argument."""
5033    return ("-1", "kNoError", "GL_INVALID_VALUE")
5034
5035  def WriteValidationCode(self, f, func):
5036    """overridden from Argument."""
5037    code = """  if (%(var_name)s < 0) {
5038    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "gl%(func_name)s", "%(var_name)s < 0");
5039    return error::kNoError;
5040  }
5041"""
5042    f.write(code % {
5043        "var_name": self.name,
5044        "func_name": func.original_name,
5045      })
5046
5047  def WriteClientSideValidationCode(self, f, func):
5048    """overridden from Argument."""
5049    code = """  if (%(var_name)s < 0) {
5050    SetGLError(GL_INVALID_VALUE, "gl%(func_name)s", "%(var_name)s < 0");
5051    return;
5052  }
5053"""
5054    f.write(code % {
5055        "var_name": self.name,
5056        "func_name": func.original_name,
5057      })
5058
5059
5060class SizeNotNegativeArgument(SizeArgument):
5061  """class for GLsizeiNotNegative. It's NEVER allowed to be negative"""
5062
5063  def GetInvalidArg(self, _index):
5064    """overridden from SizeArgument."""
5065    return ("-1", "kOutOfBounds", "GL_NO_ERROR")
5066
5067  def WriteValidationCode(self, f, func):
5068    """overridden from SizeArgument."""
5069    pass
5070
5071
5072class EnumBaseArgument(Argument):
5073  """Base class for EnumArgument, IntArgument, and BitfieldArgument."""
5074
5075  def __init__(self, name, gl_type, type_name, arg_type, gl_error,
5076               named_type_info, arg_default):
5077    Argument.__init__(self, name, gl_type, arg_default)
5078
5079    self.gl_error = gl_error
5080    self.type_name = type_name
5081    self.named_type = NamedType(named_type_info[type_name])
5082
5083  def IsConstant(self):
5084    return self.named_type.IsConstant()
5085
5086  def GetConstantValue(self):
5087    return self.named_type.GetConstantValue()
5088
5089  def WriteValidationCode(self, f, func):
5090    if self.named_type.IsConstant():
5091      return
5092    f.write("  if (!validators_->%s.IsValid(%s)) {\n" %
5093               (ToUnderscore(self.type_name), self.name))
5094    if self.gl_error == "GL_INVALID_ENUM":
5095      f.write(
5096          "    LOCAL_SET_GL_ERROR_INVALID_ENUM(\"gl%s\", %s, \"%s\");\n" %
5097          (func.original_name, self.name, self.name))
5098    else:
5099      f.write(
5100          "    LOCAL_SET_GL_ERROR(%s, \"gl%s\", \"%s %s\");\n" %
5101          (self.gl_error, func.original_name, self.name, self.gl_error))
5102    f.write("    return error::kNoError;\n")
5103    f.write("  }\n")
5104
5105  def WriteClientSideValidationCode(self, f, func):
5106    if not self.named_type.IsConstant():
5107      return
5108    f.write("  if (%s != %s) {" % (self.name,
5109                                      self.GetConstantValue()))
5110    f.write(
5111      "    SetGLError(%s, \"gl%s\", \"%s %s\");\n" %
5112      (self.gl_error, func.original_name, self.name, self.gl_error))
5113    if func.return_type == "void":
5114      f.write("    return;\n")
5115    else:
5116      f.write("    return %s;\n" % func.GetErrorReturnString())
5117    f.write("  }\n")
5118
5119  def GetValidArg(self, func):
5120    valid_arg = func.GetValidArg(self)
5121    if valid_arg != None:
5122      return valid_arg
5123    valid = self.named_type.GetValidValues()
5124    if valid:
5125      return valid[0]
5126
5127    index = func.GetOriginalArgs().index(self)
5128    return str(index + 1)
5129
5130  def GetValidClientSideArg(self, func):
5131    """Gets a valid value for this argument."""
5132    return self.GetValidArg(func)
5133
5134  def GetValidClientSideCmdArg(self, func):
5135    """Gets a valid value for this argument."""
5136    valid_arg = func.GetValidArg(self)
5137    if valid_arg != None:
5138      return valid_arg
5139
5140    valid = self.named_type.GetValidValues()
5141    if valid:
5142      return valid[0]
5143
5144    try:
5145      index = func.GetOriginalArgs().index(self)
5146      return str(index + 1)
5147    except ValueError:
5148      pass
5149    index = func.GetCmdArgs().index(self)
5150    return str(index + 1)
5151
5152  def GetValidGLArg(self, func):
5153    """Gets a valid value for this argument."""
5154    return self.GetValidArg(func)
5155
5156  def GetNumInvalidValues(self, _func):
5157    """returns the number of invalid values to be tested."""
5158    return len(self.named_type.GetInvalidValues())
5159
5160  def GetInvalidArg(self, index):
5161    """returns an invalid value by index."""
5162    invalid = self.named_type.GetInvalidValues()
5163    if invalid:
5164      num_invalid = len(invalid)
5165      if index >= num_invalid:
5166        index = num_invalid - 1
5167      return (invalid[index], "kNoError", self.gl_error)
5168    return ("---ERROR1---", "kNoError", self.gl_error)
5169
5170
5171class EnumArgument(EnumBaseArgument):
5172  """A class that represents a GLenum argument"""
5173
5174  def __init__(self, name, arg_type, named_type_info, arg_default):
5175    EnumBaseArgument.__init__(self, name, "GLenum", arg_type[len("GLenum"):],
5176                              arg_type, "GL_INVALID_ENUM", named_type_info,
5177                              arg_default)
5178
5179  def GetLogArg(self):
5180    """Overridden from Argument."""
5181    return ("GLES2Util::GetString%s(%s)" %
5182            (self.type_name, self.name))
5183
5184
5185class EnumClassArgument(EnumBaseArgument):
5186  """A class that represents a C++ enum argument encoded as uint32_t"""
5187
5188  def __init__(self, name, arg_type, named_type_info, arg_default):
5189    type_name = arg_type[len("EnumClass"):]
5190    EnumBaseArgument.__init__(self, name, type_name, type_name, arg_type,
5191                              "GL_INVALID_ENUM", named_type_info, arg_default)
5192
5193  def GetArgAccessor(self, struct_name):
5194    """Returns the name of the accessor for the argument within the struct."""
5195    return 'static_cast<%s>(%s.%s)' % (self.type_name, struct_name, self.name)
5196
5197  def WriteSetCode(self, f, indent, var):
5198    f.write("%s%s = static_cast<uint32_t>(%s);\n" %
5199            (' ' * indent, self.name, var))
5200
5201  def GetLogArg(self):
5202    return 'static_cast<uint32_t>(%s)' % self.name
5203
5204
5205class IntArgument(EnumBaseArgument):
5206  """A class for a GLint argument that can only accept specific values.
5207
5208  For example glTexImage2D takes a GLint for its internalformat
5209  argument instead of a GLenum.
5210  """
5211
5212  def __init__(self, name, arg_type, named_type_info, arg_default):
5213    EnumBaseArgument.__init__(self, name, "GLint", arg_type[len("GLint"):],
5214                              arg_type, "GL_INVALID_VALUE", named_type_info,
5215                              arg_default)
5216
5217
5218class BitFieldArgument(EnumBaseArgument):
5219  """A class for a GLbitfield argument that can only accept specific values.
5220
5221  For example glFenceSync takes a GLbitfield for its flags argument bit it
5222  must be 0.
5223  """
5224
5225  def __init__(self, name, arg_type, named_type_info, arg_default):
5226    EnumBaseArgument.__init__(self, name, "GLbitfield",
5227                              arg_type[len("GLbitfield"):], arg_type,
5228                              "GL_INVALID_VALUE", named_type_info, arg_default)
5229
5230
5231class ImmediatePointerArgument(Argument):
5232  """A class that represents an immediate argument to a function.
5233
5234  An immediate argument is one where the data follows the command.
5235  """
5236
5237  def IsPointer(self):
5238    return True
5239
5240  def GetPointedType(self):
5241    match = re.match('(const\s+)?(?P<element_type>[\w]+)\s*\*', self.type)
5242    assert match
5243    return match.groupdict()['element_type']
5244
5245  def AddCmdArgs(self, args):
5246    """Overridden from Argument."""
5247    pass
5248
5249  def WriteGetCode(self, f):
5250    """Overridden from Argument."""
5251    f.write("  volatile %s %s = %sGetImmediateDataAs<volatile %s>(\n" %
5252            (self.type, self.name, _Namespace(), self.type))
5253    f.write("      c, %s, immediate_data_size);\n" %
5254            self.GetReservedSizeId())
5255
5256  def WriteValidationCode(self, f, func):
5257    """Overridden from Argument."""
5258    if self.optional:
5259      return
5260    f.write("  if (%s == nullptr) {\n" % self.name)
5261    f.write("    return error::kOutOfBounds;\n")
5262    f.write("  }\n")
5263
5264  def WritePassthroughValidationCode(self, f, func):
5265    """Overridden from Argument."""
5266    if self.optional:
5267      return
5268    f.write("  if (%s == nullptr) {\n" % self.name)
5269    f.write("    return error::kOutOfBounds;\n")
5270    f.write("  }\n")
5271
5272  def GetImmediateVersion(self):
5273    """Overridden from Argument."""
5274    return None
5275
5276  def WriteDestinationInitalizationValidation(self, f, func):
5277    """Overridden from Argument."""
5278    self.WriteDestinationInitalizationValidatationIfNeeded(f, func)
5279
5280  def GetLogArg(self):
5281    """Overridden from Argument."""
5282    return "static_cast<const void*>(%s)" % self.name
5283
5284
5285class PointerArgument(Argument):
5286  """A class that represents a pointer argument to a function."""
5287
5288  def IsPointer(self):
5289    """Overridden from Argument."""
5290    return True
5291
5292  def IsPointer2D(self):
5293    """Overridden from Argument."""
5294    return self.type.count('*') == 2
5295
5296  def GetPointedType(self):
5297    match = re.match('(const\s+)?(?P<element_type>[\w]+)\s*\*', self.type)
5298    assert match
5299    return match.groupdict()['element_type']
5300
5301  def GetValidArg(self, func):
5302    """Overridden from Argument."""
5303    return "shared_memory_id_, shared_memory_offset_"
5304
5305  def GetValidGLArg(self, func):
5306    """Overridden from Argument."""
5307    return "reinterpret_cast<%s>(shared_memory_address_)" % self.type
5308
5309  def GetNumInvalidValues(self, _func):
5310    """Overridden from Argument."""
5311    return 2
5312
5313  def GetInvalidArg(self, index):
5314    """Overridden from Argument."""
5315    if index == 0:
5316      return ("kInvalidSharedMemoryId, 0", "kOutOfBounds", None)
5317    else:
5318      return ("shared_memory_id_, kInvalidSharedMemoryOffset",
5319              "kOutOfBounds", None)
5320
5321  def GetLogArg(self):
5322    """Overridden from Argument."""
5323    return "static_cast<const void*>(%s)" % self.name
5324
5325  def AddCmdArgs(self, args):
5326    """Overridden from Argument."""
5327    args.append(Argument("%s_shm_id" % self.name, 'uint32_t'))
5328    args.append(Argument("%s_shm_offset" % self.name, 'uint32_t'))
5329
5330  def WriteGetCode(self, f):
5331    """Overridden from Argument."""
5332    f.write(
5333        "  %s %s = GetSharedMemoryAs<%s>(\n" %
5334        (self.type, self.name, self.type))
5335    f.write(
5336        "      c.%s_shm_id, c.%s_shm_offset, %s);\n" %
5337        (self.name, self.name, self.GetReservedSizeId()))
5338
5339  def WriteValidationCode(self, f, func):
5340    """Overridden from Argument."""
5341    if self.optional:
5342      return
5343    f.write("  if (%s == nullptr) {\n" % self.name)
5344    f.write("    return error::kOutOfBounds;\n")
5345    f.write("  }\n")
5346
5347  def GetImmediateVersion(self):
5348    """Overridden from Argument."""
5349    return ImmediatePointerArgument(self.name, self.type)
5350
5351  def GetBucketVersion(self):
5352    """Overridden from Argument."""
5353    if self.type.find('char') >= 0:
5354      if self.IsPointer2D():
5355        return InputStringArrayBucketArgument(self.name, self.type)
5356      return InputStringBucketArgument(self.name, self.type)
5357    return BucketPointerArgument(self.name, self.type)
5358
5359  def WriteDestinationInitalizationValidation(self, f, func):
5360    """Overridden from Argument."""
5361    self.WriteDestinationInitalizationValidatationIfNeeded(f, func)
5362
5363
5364class BucketPointerArgument(PointerArgument):
5365  """A class that represents an bucket argument to a function."""
5366
5367  def AddCmdArgs(self, args):
5368    """Overridden from Argument."""
5369    pass
5370
5371  def WriteGetCode(self, f):
5372    """Overridden from Argument."""
5373    f.write(
5374      "  %s %s = bucket->GetData(0, %s);\n" %
5375      (self.type, self.name, self.GetReservedSizeId()))
5376
5377  def WriteValidationCode(self, f, func):
5378    """Overridden from Argument."""
5379    pass
5380
5381  def GetImmediateVersion(self):
5382    """Overridden from Argument."""
5383    return None
5384
5385  def WriteDestinationInitalizationValidation(self, f, func):
5386    """Overridden from Argument."""
5387    self.WriteDestinationInitalizationValidatationIfNeeded(f, func)
5388
5389  def GetLogArg(self):
5390    """Overridden from Argument."""
5391    return "static_cast<const void*>(%s)" % self.name
5392
5393
5394class InputStringBucketArgument(Argument):
5395  """A string input argument where the string is passed in a bucket."""
5396
5397  def __init__(self, name, _type):
5398    Argument.__init__(self, name + "_bucket_id", "uint32_t")
5399
5400  def IsPointer(self):
5401    """Overridden from Argument."""
5402    return True
5403
5404  def IsPointer2D(self):
5405    """Overridden from Argument."""
5406    return False
5407
5408
5409class InputStringArrayBucketArgument(Argument):
5410  """A string array input argument where the strings are passed in a bucket."""
5411
5412  def __init__(self, name, _type):
5413    Argument.__init__(self, name + "_bucket_id", "uint32_t")
5414    self._original_name = name
5415
5416  def WriteGetCode(self, f):
5417    """Overridden from Argument."""
5418    code = """
5419  Bucket* bucket = GetBucket(c.%(name)s);
5420  if (!bucket) {
5421    return error::kInvalidArguments;
5422  }
5423  GLsizei count = 0;
5424  std::vector<char*> strs;
5425  std::vector<GLint> len;
5426  if (!bucket->GetAsStrings(&count, &strs, &len)) {
5427    return error::kInvalidArguments;
5428  }
5429  const char** %(original_name)s =
5430      strs.size() > 0 ? const_cast<const char**>(&strs[0]) : nullptr;
5431  const GLint* length =
5432      len.size() > 0 ? const_cast<const GLint*>(&len[0]) : nullptr;
5433  (void)length;
5434"""
5435    f.write(code % {
5436        'name': self.name,
5437        'original_name': self._original_name,
5438      })
5439
5440  def GetValidArg(self, func):
5441    return "kNameBucketId"
5442
5443  def GetValidGLArg(self, func):
5444    return "_"
5445
5446  def IsPointer(self):
5447    """Overridden from Argument."""
5448    return True
5449
5450  def IsPointer2D(self):
5451    """Overridden from Argument."""
5452    return True
5453
5454
5455class ResourceIdArgument(Argument):
5456  """A class that represents a resource id argument to a function."""
5457
5458  def __init__(self, name, arg_type, arg_default):
5459    match = re.match("(GLid\w+)", arg_type)
5460    self.resource_type = match.group(1)[4:]
5461    if self.resource_type == "Sync":
5462      arg_type = arg_type.replace(match.group(1), "GLsync")
5463    else:
5464      arg_type = arg_type.replace(match.group(1), "GLuint")
5465    Argument.__init__(self, name, arg_type, arg_default)
5466
5467  def WriteGetCode(self, f):
5468    """Overridden from Argument."""
5469    if self.type == "GLsync":
5470      my_type = "GLuint"
5471    else:
5472      my_type = self.type
5473    f.write("  %s %s = %s;\n" % (my_type, self.name, self.GetArgAccessor('c')))
5474
5475  def GetValidArg(self, func):
5476    return "client_%s_id_" % self.resource_type.lower()
5477
5478  def GetValidGLArg(self, func):
5479    if self.resource_type == "Sync":
5480      return "reinterpret_cast<GLsync>(kService%sId)" % self.resource_type
5481    return "kService%sId" % self.resource_type
5482
5483
5484class ResourceIdBindArgument(Argument):
5485  """Represents a resource id argument to a bind function."""
5486
5487  def __init__(self, name, arg_type, arg_default):
5488    match = re.match("(GLidBind\w+)", arg_type)
5489    self.resource_type = match.group(1)[8:]
5490    arg_type = arg_type.replace(match.group(1), "GLuint")
5491    Argument.__init__(self, name, arg_type, arg_default)
5492
5493  def WriteGetCode(self, f):
5494    """Overridden from Argument."""
5495    code = """  %(type)s %(name)s = c.%(name)s;
5496"""
5497    f.write(code % {'type': self.type, 'name': self.name})
5498
5499  def GetValidArg(self, func):
5500    return "client_%s_id_" % self.resource_type.lower()
5501
5502  def GetValidGLArg(self, func):
5503    return "kService%sId" % self.resource_type
5504
5505
5506class ResourceIdZeroArgument(Argument):
5507  """Represents a resource id argument to a function that can be zero."""
5508
5509  def __init__(self, name, arg_type, arg_default):
5510    match = re.match("(GLidZero\w+)", arg_type)
5511    self.resource_type = match.group(1)[8:]
5512    arg_type = arg_type.replace(match.group(1), "GLuint")
5513    Argument.__init__(self, name, arg_type, arg_default)
5514
5515  def WriteGetCode(self, f):
5516    """Overridden from Argument."""
5517    f.write("  %s %s = %s;\n" % (self.type, self.name,
5518                                 self.GetArgAccessor('c')))
5519
5520  def GetValidArg(self, func):
5521    return "client_%s_id_" % self.resource_type.lower()
5522
5523  def GetValidGLArg(self, func):
5524    return "kService%sId" % self.resource_type
5525
5526  def GetNumInvalidValues(self, _func):
5527    """returns the number of invalid values to be tested."""
5528    return 1
5529
5530  def GetInvalidArg(self, _index):
5531    """returns an invalid value by index."""
5532    return ("kInvalidClientId", "kNoError", "GL_INVALID_VALUE")
5533
5534
5535class Int64Argument(Argument):
5536  """Represents a GLuint64 argument which splits up into 2 uint32_t items."""
5537
5538  def __init__(self, name, arg_type, arg_default):
5539    Argument.__init__(self, name, arg_type, arg_default)
5540
5541  def GetArgAccessor(self, cmd_struct_name):
5542    return "%s.%s()" % (cmd_struct_name, self.name)
5543
5544  def WriteArgAccessor(self, f):
5545    """Writes specialized accessor for compound members."""
5546    f.write("  %s %s() const volatile {\n" % (self.type, self.name))
5547    f.write("    return static_cast<%s>(\n" % self.type)
5548    f.write("        %sGLES2Util::MapTwoUint32ToUint64(\n" % _Namespace())
5549    f.write("            %s_0,\n" % self.name)
5550    f.write("            %s_1));\n" % self.name)
5551    f.write("  }\n")
5552    f.write("\n")
5553
5554  def WriteGetCode(self, f):
5555    """Writes the code to get an argument from a command structure."""
5556    f.write("  %s %s = c.%s();\n" % (self.type, self.name, self.name))
5557
5558  def WriteSetCode(self, f, indent, var):
5559    indent_str = ' ' * indent
5560    f.write("%s%sGLES2Util::MapUint64ToTwoUint32(static_cast<uint64_t>(%s),\n" %
5561            (indent_str, _Namespace(), var))
5562    f.write("%s                                &%s_0,\n" %
5563            (indent_str, self.name))
5564    f.write("%s                                &%s_1);\n" %
5565            (indent_str, self.name))
5566
5567class Function(object):
5568  """A class that represents a function."""
5569
5570  def __init__(self, name, info, named_type_info, type_handlers):
5571    self.name = name
5572    self.named_type_info = named_type_info
5573
5574    self.prefixed_name = info['prefixed_name']
5575    self.original_name = info['original_name']
5576
5577    self.original_args = self.ParseArgs(info['original_args'])
5578
5579    if 'cmd_args' in info:
5580      self.args_for_cmds = self.ParseArgs(info['cmd_args'])
5581    else:
5582      self.args_for_cmds = self.original_args[:]
5583
5584    self.passthrough_service_doer_args = self.original_args[:]
5585
5586    if 'size_args' in info:
5587      self.size_args = info['size_args']
5588    else:
5589      self.size_args = {}
5590
5591    self.return_type = info['return_type']
5592    if self.return_type != 'void':
5593      self.return_arg = CreateArg(info['return_type'] + " result",
5594                                  named_type_info)
5595    else:
5596      self.return_arg = None
5597
5598    self.num_pointer_args = sum(
5599      [1 for arg in self.args_for_cmds if arg.IsPointer()])
5600    if self.num_pointer_args > 0:
5601      for arg in reversed(self.original_args):
5602        if arg.IsPointer():
5603          self.last_original_pointer_arg = arg
5604          break
5605    else:
5606      self.last_original_pointer_arg = None
5607    self.info = info
5608    self.type_handler = type_handlers[info['type']]
5609    self.can_auto_generate = (self.num_pointer_args == 0 and
5610                              info['return_type'] == "void")
5611
5612    # Satisfy pylint warning attribute-defined-outside-init.
5613    #
5614    # self.cmd_args is typically set in InitFunction, but that method may be
5615    # overriden.
5616    self.cmd_args = []
5617    self.InitFunction()
5618
5619  def ParseArgs(self, arg_string):
5620    """Parses a function arg string."""
5621    args = []
5622    parts = arg_string.split(',')
5623    for arg_string in parts:
5624      arg = CreateArg(arg_string, self.named_type_info)
5625      if arg:
5626        args.append(arg)
5627    return args
5628
5629  def IsType(self, type_name):
5630    """Returns true if function is a certain type."""
5631    return self.info['type'] == type_name
5632
5633  def InitFunction(self):
5634    """Creates command args and calls the init function for the type handler.
5635
5636    Creates argument lists for command buffer commands, eg. self.cmd_args and
5637    self.init_args.
5638    Calls the type function initialization.
5639    Override to create different kind of command buffer command argument lists.
5640    """
5641    self.cmd_args = []
5642    for arg in self.args_for_cmds:
5643      arg.AddCmdArgs(self.cmd_args)
5644
5645    self.init_args = []
5646    for arg in self.args_for_cmds:
5647      arg.AddInitArgs(self.init_args)
5648
5649    if self.return_arg:
5650      self.init_args.append(self.return_arg)
5651
5652    self.type_handler.InitFunction(self)
5653
5654  def IsImmediate(self):
5655    """Returns whether the function is immediate data function or not."""
5656    return False
5657
5658  def IsES3(self):
5659    """Returns whether the function requires an ES3 context or not."""
5660    return self.GetInfo('es3', False)
5661
5662  def IsES31(self):
5663    """Returns whether the function requires an ES31 context or not."""
5664    return self.GetInfo('es31', False)
5665
5666  def GetInfo(self, name, default = None):
5667    """Returns a value from the function info for this function."""
5668    if name in self.info:
5669      return self.info[name]
5670    return default
5671
5672  def GetValidArg(self, arg):
5673    """Gets a valid argument value for the parameter arg from the function info
5674    if one exists."""
5675    try:
5676      index = self.GetOriginalArgs().index(arg)
5677    except ValueError:
5678      return None
5679
5680    valid_args = self.GetInfo('valid_args')
5681    if valid_args and str(index) in valid_args:
5682      return valid_args[str(index)]
5683    return None
5684
5685  def AddInfo(self, name, value):
5686    """Adds an info."""
5687    self.info[name] = value
5688
5689  def IsExtension(self):
5690    return self.GetInfo('extension') or self.GetInfo('extension_flag')
5691
5692  def IsCoreGLFunction(self):
5693    return (not self.IsExtension() and
5694            not self.GetInfo('pepper_interface') and
5695            not self.IsES3() and
5696            not self.IsES31())
5697
5698  def InPepperInterface(self, interface):
5699    ext = self.GetInfo('pepper_interface')
5700    if not interface.GetName():
5701      return self.IsCoreGLFunction()
5702    return ext == interface.GetName()
5703
5704  def InAnyPepperExtension(self):
5705    return self.IsCoreGLFunction() or self.GetInfo('pepper_interface')
5706
5707  def GetErrorReturnString(self):
5708    if self.GetInfo("error_return"):
5709      return self.GetInfo("error_return")
5710    elif self.return_type == "GLboolean":
5711      return "GL_FALSE"
5712    elif "*" in self.return_type:
5713      return "nullptr"
5714    return "0"
5715
5716  def GetGLFunctionName(self):
5717    """Gets the function to call to execute GL for this command."""
5718    if self.GetInfo('decoder_func'):
5719      return self.GetInfo('decoder_func')
5720    return "api()->gl%sFn" % self.original_name
5721
5722  def GetGLTestFunctionName(self):
5723    gl_func_name = self.GetInfo('gl_test_func')
5724    if gl_func_name == None:
5725      gl_func_name = self.GetGLFunctionName()
5726    if gl_func_name.startswith("gl"):
5727      gl_func_name = gl_func_name[2:]
5728    else:
5729      gl_func_name = self.original_name
5730    return gl_func_name
5731
5732  def GetDataTransferMethods(self):
5733    return self.GetInfo('data_transfer_methods',
5734                        ['immediate' if self.num_pointer_args == 1 else 'shm'])
5735
5736  def AddCmdArg(self, arg):
5737    """Adds a cmd argument to this function."""
5738    self.cmd_args.append(arg)
5739
5740  def GetCmdArgs(self):
5741    """Gets the command args for this function."""
5742    return self.cmd_args
5743
5744  def ClearCmdArgs(self):
5745    """Clears the command args for this function."""
5746    self.cmd_args = []
5747
5748  def GetCmdConstants(self):
5749    """Gets the constants for this function."""
5750    return [arg for arg in self.args_for_cmds if arg.IsConstant()]
5751
5752  def GetInitArgs(self):
5753    """Gets the init args for this function."""
5754    return self.init_args
5755
5756  def GetOriginalArgs(self):
5757    """Gets the original arguments to this function."""
5758    return self.original_args
5759
5760  def GetPassthroughServiceDoerArgs(self):
5761    """Gets the original arguments to this function."""
5762    return self.passthrough_service_doer_args
5763
5764  def GetLastOriginalArg(self):
5765    """Gets the last original argument to this function."""
5766    return self.original_args[len(self.original_args) - 1]
5767
5768  def GetLastOriginalPointerArg(self):
5769    return self.last_original_pointer_arg
5770
5771  def GetResourceIdArg(self):
5772    for arg in self.original_args:
5773      if hasattr(arg, 'resource_type'):
5774        return arg
5775    return None
5776
5777  def _MaybePrependComma(self, arg_string, add_comma):
5778    """Adds a comma if arg_string is not empty and add_comma is true."""
5779    comma = ""
5780    if add_comma and len(arg_string):
5781      comma = ", "
5782    return "%s%s" % (comma, arg_string)
5783
5784  def MakeTypedOriginalArgString(self, prefix, add_comma = False,
5785                                 add_default = False):
5786    """Gets a list of arguments as they are in GL."""
5787    args = self.GetOriginalArgs()
5788    def ArgToString(arg):
5789      tmp = [arg.type, prefix + arg.name]
5790      if add_default and arg.default:
5791        tmp.append("=")
5792        tmp.append(arg.default)
5793      return " ".join(tmp)
5794    arg_string = ", ".join([ArgToString(arg) for arg in args])
5795    return self._MaybePrependComma(arg_string, add_comma)
5796
5797  def MakeOriginalArgString(self, prefix, add_comma = False, separator = ", "):
5798    """Gets the list of arguments as they are in GL."""
5799    args = self.GetOriginalArgs()
5800    arg_string = separator.join(
5801        ["%s%s" % (prefix, arg.name) for arg in args])
5802    return self._MaybePrependComma(arg_string, add_comma)
5803
5804  def MakePassthroughServiceDoerArgString(self, prefix, add_comma = False,
5805                                          separator = ", "):
5806    """Gets the list of arguments as they are in used by the passthrough
5807       service doer function."""
5808    args = self.GetPassthroughServiceDoerArgs()
5809    arg_string = separator.join(
5810        ["%s%s" % (prefix, arg.name) for arg in args])
5811    return self._MaybePrependComma(arg_string, add_comma)
5812
5813  def MakeHelperArgString(self, prefix, add_comma = False, separator = ", "):
5814    """Gets a list of GL arguments after removing unneeded arguments."""
5815    args = self.GetOriginalArgs()
5816    arg_string = separator.join(
5817        ["%s%s" % (prefix, arg.name)
5818         for arg in args if not arg.IsConstant()])
5819    return self._MaybePrependComma(arg_string, add_comma)
5820
5821  def MakeTypedPepperArgString(self, prefix):
5822    """Gets a list of arguments as they need to be for Pepper."""
5823    if self.GetInfo("pepper_args"):
5824      return self.GetInfo("pepper_args")
5825    else:
5826      return self.MakeTypedOriginalArgString(prefix, False)
5827
5828  def MapCTypeToPepperIdlType(self, ctype, is_for_return_type=False):
5829    """Converts a C type name to the corresponding Pepper IDL type."""
5830    idltype = {
5831        'char*': '[out] str_t',
5832        'const GLchar* const*': '[out] cstr_t',
5833        'const char*': 'cstr_t',
5834        'const void*': 'mem_t',
5835        'void*': '[out] mem_t',
5836        'void**': '[out] mem_ptr_t',
5837    }.get(ctype, ctype)
5838    # We use "GLxxx_ptr_t" for "GLxxx*".
5839    matched = re.match(r'(const )?(GL\w+)\*$', ctype)
5840    if matched:
5841      idltype = matched.group(2) + '_ptr_t'
5842      if not matched.group(1):
5843        idltype = '[out] ' + idltype
5844    # If an in/out specifier is not specified yet, prepend [in].
5845    if idltype[0] != '[':
5846      idltype = '[in] ' + idltype
5847    # Strip the in/out specifier for a return type.
5848    if is_for_return_type:
5849      idltype = re.sub(r'\[\w+\] ', '', idltype)
5850    return idltype
5851
5852  def MakeTypedPepperIdlArgStrings(self):
5853    """Gets a list of arguments as they need to be for Pepper IDL."""
5854    args = self.GetOriginalArgs()
5855    return ["%s %s" % (self.MapCTypeToPepperIdlType(arg.type), arg.name)
5856            for arg in args]
5857
5858  def GetPepperName(self):
5859    if self.GetInfo("pepper_name"):
5860      return self.GetInfo("pepper_name")
5861    return self.name
5862
5863  def MakeTypedCmdArgString(self, prefix, add_comma = False):
5864    """Gets a typed list of arguments as they need to be for command buffers."""
5865    args = self.GetCmdArgs()
5866    arg_string = ", ".join(
5867        ["%s %s%s" % (arg.type, prefix, arg.name) for arg in args])
5868    return self._MaybePrependComma(arg_string, add_comma)
5869
5870  def MakeCmdArgString(self, prefix, add_comma = False):
5871    """Gets the list of arguments as they need to be for command buffers."""
5872    args = self.GetCmdArgs()
5873    arg_string = ", ".join(
5874        ["%s%s" % (prefix, arg.name) for arg in args])
5875    return self._MaybePrependComma(arg_string, add_comma)
5876
5877  def MakeTypedInitString(self, prefix, add_comma = False):
5878    """Gets a typed list of arguments as they need to be for cmd Init/Set."""
5879    args = self.GetInitArgs()
5880    arg_string = ", ".join(
5881        ["%s %s%s" % (arg.type, prefix, arg.name) for arg in args])
5882    return self._MaybePrependComma(arg_string, add_comma)
5883
5884  def MakeInitString(self, prefix, add_comma = False):
5885    """Gets the list of arguments as they need to be for cmd Init/Set."""
5886    args = self.GetInitArgs()
5887    arg_string = ", ".join(
5888        ["%s%s" % (prefix, arg.name) for arg in args])
5889    return self._MaybePrependComma(arg_string, add_comma)
5890
5891  def MakeLogArgString(self):
5892    """Makes a string of the arguments for the LOG macros"""
5893    args = self.GetOriginalArgs()
5894    return ' << ", " << '.join([arg.GetLogArg() for arg in args])
5895
5896  def WriteHandlerValidation(self, f):
5897    """Writes validation code for the function."""
5898    for arg in self.GetOriginalArgs():
5899      arg.WriteValidationCode(f, self)
5900    self.WriteValidationCode(f)
5901
5902  def WriteQueueTraceEvent(self, f):
5903    if self.GetInfo("trace_queueing_flow", False):
5904      trace = 'TRACE_DISABLED_BY_DEFAULT("gpu_cmd_queue")'
5905      f.write("""if (c.trace_id) {
5906          TRACE_EVENT_WITH_FLOW0(%s, "CommandBufferQueue",
5907          c.trace_id, TRACE_EVENT_FLAG_FLOW_IN);\n}""" % trace)
5908
5909  def WritePassthroughHandlerValidation(self, f):
5910    """Writes validation code for the function."""
5911    for arg in self.GetOriginalArgs():
5912      arg.WritePassthroughValidationCode(f, self)
5913
5914  def WriteHandlerImplementation(self, f):
5915    """Writes the handler implementation for this command."""
5916    self.type_handler.WriteHandlerImplementation(self, f)
5917
5918  def WriteValidationCode(self, f):
5919    """Writes the validation code for a command."""
5920    pass
5921
5922  def WriteCmdFlag(self, f):
5923    """Writes the cmd cmd_flags constant."""
5924    # By default trace only at the highest level 3.
5925    trace_level = int(self.GetInfo('trace_level', default = 3))
5926    if trace_level not in xrange(0, 4):
5927      raise KeyError("Unhandled trace_level: %d" % trace_level)
5928
5929    cmd_flags = ('CMD_FLAG_SET_TRACE_LEVEL(%d)' % trace_level)
5930    f.write("  static const uint8_t cmd_flags = %s;\n" % cmd_flags)
5931
5932
5933  def WriteCmdArgFlag(self, f):
5934    """Writes the cmd kArgFlags constant."""
5935    f.write("  static const cmd::ArgFlags kArgFlags = cmd::kFixed;\n")
5936
5937  def WriteCmdComputeSize(self, f):
5938    """Writes the ComputeSize function for the command."""
5939    f.write("  static uint32_t ComputeSize() {\n")
5940    f.write(
5941        "    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT\n")
5942    f.write("  }\n")
5943    f.write("\n")
5944
5945  def WriteCmdSetHeader(self, f):
5946    """Writes the cmd's SetHeader function."""
5947    f.write("  void SetHeader() {\n")
5948    f.write("    header.SetCmd<ValueType>();\n")
5949    f.write("  }\n")
5950    f.write("\n")
5951
5952  def WriteCmdInit(self, f):
5953    """Writes the cmd's Init function."""
5954    f.write("  void Init(%s) {\n" % self.MakeTypedCmdArgString("_"))
5955    f.write("    SetHeader();\n")
5956    args = self.GetCmdArgs()
5957    for arg in args:
5958      arg.WriteSetCode(f, 4, '_%s' % arg.name)
5959    if self.GetInfo("trace_queueing_flow", False):
5960      trace = 'TRACE_DISABLED_BY_DEFAULT("gpu_cmd_queue")'
5961      f.write('bool is_tracing = false;')
5962      f.write('TRACE_EVENT_CATEGORY_GROUP_ENABLED(%s, &is_tracing);' % trace)
5963      f.write('if (is_tracing) {')
5964      f.write('  trace_id = base::RandUint64();')
5965      f.write('TRACE_EVENT_WITH_FLOW1(%s, "CommandBufferQueue",' % trace)
5966      f.write('trace_id, TRACE_EVENT_FLAG_FLOW_OUT,')
5967      f.write('"command", "%s");' % self.name)
5968      f.write('} else {\n  trace_id = 0;\n}\n');
5969    f.write("}\n")
5970    f.write("\n")
5971
5972  def WriteCmdSet(self, f):
5973    """Writes the cmd's Set function."""
5974    copy_args = self.MakeCmdArgString("_", False)
5975    f.write("  void* Set(void* cmd%s) {\n" %
5976               self.MakeTypedCmdArgString("_", True))
5977    f.write("    static_cast<ValueType*>(cmd)->Init(%s);\n" % copy_args)
5978    f.write("    return NextCmdAddress<ValueType>(cmd);\n")
5979    f.write("  }\n")
5980    f.write("\n")
5981
5982  def WriteArgAccessors(self, f):
5983    """Writes the cmd's accessor functions."""
5984    for arg in self.GetCmdArgs():
5985      arg.WriteArgAccessor(f)
5986
5987  def WriteStruct(self, f):
5988    self.type_handler.WriteStruct(self, f)
5989
5990  def WriteDocs(self, f):
5991    self.type_handler.WriteDocs(self, f)
5992
5993  def WriteCmdHelper(self, f):
5994    """Writes the cmd's helper."""
5995    self.type_handler.WriteCmdHelper(self, f)
5996
5997  def WriteServiceImplementation(self, f):
5998    """Writes the service implementation for a command."""
5999    self.type_handler.WriteServiceImplementation(self, f)
6000
6001  def WritePassthroughServiceImplementation(self, f):
6002    """Writes the service implementation for a command."""
6003    self.type_handler.WritePassthroughServiceImplementation(self, f)
6004
6005  def WriteServiceUnitTest(self, f, *extras):
6006    """Writes the service implementation for a command."""
6007    self.type_handler.WriteServiceUnitTest(self, f, *extras)
6008
6009  def WriteGLES2CLibImplementation(self, f):
6010    """Writes the GLES2 C Lib Implemention."""
6011    self.type_handler.WriteGLES2CLibImplementation(self, f)
6012
6013  def WriteGLES2InterfaceHeader(self, f):
6014    """Writes the GLES2 Interface declaration."""
6015    self.type_handler.WriteGLES2InterfaceHeader(self, f)
6016
6017  def WriteGLES2InterfaceStub(self, f):
6018    """Writes the GLES2 Interface Stub declaration."""
6019    self.type_handler.WriteGLES2InterfaceStub(self, f)
6020
6021  def WriteGLES2InterfaceStubImpl(self, f):
6022    """Writes the GLES2 Interface Stub declaration."""
6023    self.type_handler.WriteGLES2InterfaceStubImpl(self, f)
6024
6025  def WriteGLES2ImplementationHeader(self, f):
6026    """Writes the GLES2 Implemention declaration."""
6027    self.type_handler.WriteGLES2ImplementationHeader(self, f)
6028
6029  def WriteGLES2Implementation(self, f):
6030    """Writes the GLES2 Implemention definition."""
6031    self.type_handler.WriteGLES2Implementation(self, f)
6032
6033  def WriteGLES2TraceImplementationHeader(self, f):
6034    """Writes the GLES2 Trace Implemention declaration."""
6035    self.type_handler.WriteGLES2TraceImplementationHeader(self, f)
6036
6037  def WriteGLES2TraceImplementation(self, f):
6038    """Writes the GLES2 Trace Implemention definition."""
6039    self.type_handler.WriteGLES2TraceImplementation(self, f)
6040
6041  def WriteGLES2Header(self, f):
6042    """Writes the GLES2 Implemention unit test."""
6043    self.type_handler.WriteGLES2Header(self, f)
6044
6045  def WriteGLES2ImplementationUnitTest(self, f):
6046    """Writes the GLES2 Implemention unit test."""
6047    self.type_handler.WriteGLES2ImplementationUnitTest(self, f)
6048
6049  def WriteDestinationInitalizationValidation(self, f):
6050    """Writes the client side destintion initialization validation."""
6051    self.type_handler.WriteDestinationInitalizationValidation(self, f)
6052
6053  def WriteFormatTest(self, f):
6054    """Writes the cmd's format test."""
6055    self.type_handler.WriteFormatTest(self, f)
6056
6057
6058class PepperInterface(object):
6059  """A class that represents a function."""
6060
6061  def __init__(self, info):
6062    self.name = info["name"]
6063    self.dev = info["dev"]
6064
6065  def GetName(self):
6066    return self.name
6067
6068  def GetInterfaceName(self):
6069    upperint = ""
6070    dev = ""
6071    if self.name:
6072      upperint = "_" + self.name.upper()
6073    if self.dev:
6074      dev = "_DEV"
6075    return "PPB_OPENGLES2%s%s_INTERFACE" % (upperint, dev)
6076
6077  def GetStructName(self):
6078    dev = ""
6079    if self.dev:
6080      dev = "_Dev"
6081    return "PPB_OpenGLES2%s%s" % (self.name, dev)
6082
6083
6084class ImmediateFunction(Function):
6085  """A class that represents an immediate function command."""
6086
6087  def __init__(self, func, type_handlers):
6088    Function.__init__(
6089        self,
6090        "%sImmediate" % func.name,
6091        func.info,
6092        func.named_type_info,
6093        type_handlers)
6094
6095  def InitFunction(self):
6096    # Override args in original_args and args_for_cmds with immediate versions
6097    # of the args.
6098
6099    new_original_args = []
6100    for arg in self.original_args:
6101      new_arg = arg.GetImmediateVersion()
6102      if new_arg:
6103        new_original_args.append(new_arg)
6104    self.original_args = new_original_args
6105
6106    new_args_for_cmds = []
6107    for arg in self.args_for_cmds:
6108      new_arg = arg.GetImmediateVersion()
6109      if new_arg:
6110        new_args_for_cmds.append(new_arg)
6111
6112    self.args_for_cmds = new_args_for_cmds
6113
6114    Function.InitFunction(self)
6115
6116  def IsImmediate(self):
6117    return True
6118
6119  def WriteServiceImplementation(self, f):
6120    """Overridden from Function"""
6121    self.type_handler.WriteImmediateServiceImplementation(self, f)
6122
6123  def WritePassthroughServiceImplementation(self, f):
6124    """Overridden from Function"""
6125    self.type_handler.WritePassthroughImmediateServiceImplementation(self, f)
6126
6127  def WriteHandlerImplementation(self, f):
6128    """Overridden from Function"""
6129    self.type_handler.WriteImmediateHandlerImplementation(self, f)
6130
6131  def WriteServiceUnitTest(self, f, *extras):
6132    """Writes the service implementation for a command."""
6133    self.type_handler.WriteImmediateServiceUnitTest(self, f, *extras)
6134
6135  def WriteValidationCode(self, f):
6136    """Overridden from Function"""
6137    self.type_handler.WriteImmediateValidationCode(self, f)
6138
6139  def WriteCmdArgFlag(self, f):
6140    """Overridden from Function"""
6141    f.write("  static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;\n")
6142
6143  def WriteCmdComputeSize(self, f):
6144    """Overridden from Function"""
6145    self.type_handler.WriteImmediateCmdComputeSize(self, f)
6146
6147  def WriteCmdSetHeader(self, f):
6148    """Overridden from Function"""
6149    self.type_handler.WriteImmediateCmdSetHeader(self, f)
6150
6151  def WriteCmdInit(self, f):
6152    """Overridden from Function"""
6153    self.type_handler.WriteImmediateCmdInit(self, f)
6154
6155  def WriteCmdSet(self, f):
6156    """Overridden from Function"""
6157    self.type_handler.WriteImmediateCmdSet(self, f)
6158
6159  def WriteCmdHelper(self, f):
6160    """Overridden from Function"""
6161    self.type_handler.WriteImmediateCmdHelper(self, f)
6162
6163  def WriteFormatTest(self, f):
6164    """Overridden from Function"""
6165    self.type_handler.WriteImmediateFormatTest(self, f)
6166
6167
6168class BucketFunction(Function):
6169  """A class that represnets a bucket version of a function command."""
6170
6171  def __init__(self, func, type_handlers):
6172    Function.__init__(
6173      self,
6174      "%sBucket" % func.name,
6175      func.info,
6176      func.named_type_info,
6177      type_handlers)
6178
6179  def InitFunction(self):
6180    # Override args in original_args and args_for_cmds with bucket versions
6181    # of the args.
6182
6183    new_original_args = []
6184    for arg in self.original_args:
6185      new_arg = arg.GetBucketVersion()
6186      if new_arg:
6187        new_original_args.append(new_arg)
6188    self.original_args = new_original_args
6189
6190    new_args_for_cmds = []
6191    for arg in self.args_for_cmds:
6192      new_arg = arg.GetBucketVersion()
6193      if new_arg:
6194        new_args_for_cmds.append(new_arg)
6195
6196    self.args_for_cmds = new_args_for_cmds
6197
6198    Function.InitFunction(self)
6199
6200  def WriteServiceImplementation(self, f):
6201    """Overridden from Function"""
6202    self.type_handler.WriteBucketServiceImplementation(self, f)
6203
6204  def WritePassthroughServiceImplementation(self, f):
6205    """Overridden from Function"""
6206    self.type_handler.WritePassthroughBucketServiceImplementation(self, f)
6207
6208  def WriteHandlerImplementation(self, f):
6209    """Overridden from Function"""
6210    self.type_handler.WriteBucketHandlerImplementation(self, f)
6211
6212  def WriteServiceUnitTest(self, f, *extras):
6213    """Overridden from Function"""
6214    self.type_handler.WriteBucketServiceUnitTest(self, f, *extras)
6215
6216  def MakeOriginalArgString(self, prefix, add_comma = False, separator = ", "):
6217    """Overridden from Function"""
6218    args = self.GetOriginalArgs()
6219    arg_string = separator.join(
6220        ["%s%s" % (prefix, arg.name[0:-10] if arg.name.endswith("_bucket_id")
6221                           else arg.name) for arg in args])
6222    return super(BucketFunction, self)._MaybePrependComma(arg_string, add_comma)
6223
6224
6225def CreateArg(arg_string, named_type_info):
6226  """Convert string argument to an Argument class that represents it.
6227
6228  The parameter 'arg_string' can be a single argument to a GL function,
6229  something like 'GLsizei width' or 'const GLenum* bufs'. Returns an instance of
6230  the Argument class, or None if 'arg_string' is 'void'.
6231  """
6232  if arg_string == 'void':
6233    return None
6234
6235  arg_string = arg_string.strip()
6236  arg_default = None
6237  if '=' in arg_string:
6238    arg_string, arg_default = arg_string.split('=')
6239    arg_default = arg_default.strip()
6240  arg_parts = arg_string.split()
6241  assert len(arg_parts) > 1
6242  arg_name = arg_parts[-1]
6243  arg_type = " ".join(arg_parts[0:-1])
6244  t = arg_parts[0]  # only the first part of arg_type
6245
6246  # Is this a pointer argument?
6247  if arg_string.find('*') >= 0:
6248    return PointerArgument(arg_name, arg_type, arg_default)
6249  elif t.startswith('EnumClass'):
6250    return EnumClassArgument(arg_name, arg_type, named_type_info, arg_default)
6251  # Is this a resource argument? Must come after pointer check.
6252  elif t.startswith('GLidBind'):
6253    return ResourceIdBindArgument(arg_name, arg_type, arg_default)
6254  elif t.startswith('GLidZero'):
6255    return ResourceIdZeroArgument(arg_name, arg_type, arg_default)
6256  elif t.startswith('GLid'):
6257    return ResourceIdArgument(arg_name, arg_type, arg_default)
6258  elif t.startswith('GLenum') and t !='GLenum':
6259    return EnumArgument(arg_name, arg_type, named_type_info, arg_default)
6260  elif t.startswith('GLbitfield') and t != 'GLbitfield':
6261    return BitFieldArgument(arg_name, arg_type, named_type_info, arg_default)
6262  elif t.startswith('GLboolean'):
6263    return GLBooleanArgument(arg_name, arg_type, arg_default)
6264  elif t.startswith('GLintUniformLocation'):
6265    return UniformLocationArgument(arg_name, arg_default)
6266  elif (t.startswith('GLint') and t != 'GLint' and
6267        not t.startswith('GLintptr')):
6268    return IntArgument(arg_name, arg_type, named_type_info, arg_default)
6269  elif t == 'bool':
6270    return BoolArgument(arg_name, arg_type, arg_default)
6271  elif t == 'GLsizeiNotNegative' or t == 'GLintptrNotNegative':
6272    return SizeNotNegativeArgument(arg_name, t.replace('NotNegative', ''),
6273                                   arg_default)
6274  elif t.startswith('GLsize'):
6275    return SizeArgument(arg_name, arg_type, arg_default)
6276  elif t == 'GLuint64' or t == 'GLint64':
6277    return Int64Argument(arg_name, arg_type, arg_default)
6278  else:
6279    return Argument(arg_name, arg_type, arg_default)
6280
6281
6282class GLGenerator(object):
6283  """A class to generate GL command buffers."""
6284
6285  _whitespace_re = re.compile(r'^\w*$')
6286  _comment_re = re.compile(r'^//.*$')
6287  _function_re = re.compile(r'^GL_APICALL(.*?)GL_APIENTRY (.*?) \((.*?)\);$')
6288
6289  def __init__(self, verbose, year, function_info, named_type_info,
6290               chromium_root_dir):
6291    self.original_functions = []
6292    self.functions = []
6293    self.chromium_root_dir = chromium_root_dir
6294    self.verbose = verbose
6295    self.year = year
6296    self.errors = 0
6297    self.pepper_interfaces = []
6298    self.interface_info = {}
6299    self.generated_cpp_filenames = []
6300    self.function_info = function_info
6301    self.named_type_info = named_type_info
6302    self.capability_flags = _CAPABILITY_FLAGS
6303    self.type_handlers = {
6304        '': TypeHandler(),
6305        'Bind': BindHandler(),
6306        'Create': CreateHandler(),
6307        'Custom': CustomHandler(),
6308        'Data': DataHandler(),
6309        'Delete': DeleteHandler(),
6310        'DELn': DELnHandler(),
6311        'GENn': GENnHandler(),
6312        'GETn': GETnHandler(),
6313        'GLchar': GLcharHandler(),
6314        'GLcharN': GLcharNHandler(),
6315        'Is': IsHandler(),
6316        'NoCommand': NoCommandHandler(),
6317        'PUT': PUTHandler(),
6318        'PUTn': PUTnHandler(),
6319        'PUTSTR': PUTSTRHandler(),
6320        'PUTXn': PUTXnHandler(),
6321        'StateSet': StateSetHandler(),
6322        'StateSetRGBAlpha': StateSetRGBAlphaHandler(),
6323        'StateSetFrontBack': StateSetFrontBackHandler(),
6324        'StateSetFrontBackSeparate':
6325        StateSetFrontBackSeparateHandler(),
6326        'StateSetNamedParameter': StateSetNamedParameter(),
6327        'STRn': STRnHandler(),
6328    }
6329
6330    for interface in _PEPPER_INTERFACES:
6331      interface = PepperInterface(interface)
6332      self.pepper_interfaces.append(interface)
6333      self.interface_info[interface.GetName()] = interface
6334
6335  def AddFunction(self, func):
6336    """Adds a function."""
6337    self.functions.append(func)
6338
6339  def GetFunctionInfo(self, name):
6340    """Gets a type info for the given function name."""
6341    if name in self.function_info:
6342      func_info = self.function_info[name].copy()
6343    else:
6344      func_info = {}
6345
6346    if not 'type' in func_info:
6347      func_info['type'] = ''
6348
6349    return func_info
6350
6351  def Log(self, msg):
6352    """Prints something if verbose is true."""
6353    if self.verbose:
6354      print msg
6355
6356  def Error(self, msg):
6357    """Prints an error."""
6358    print "Error: %s" % msg
6359    self.errors += 1
6360
6361  def ParseGLH(self, filename):
6362    """Parses the cmd_buffer_functions.txt file and extracts the functions"""
6363    filename = os.path.join(self.chromium_root_dir, filename)
6364    with open(filename, "r") as f:
6365      functions = f.read()
6366    for line in functions.splitlines():
6367      if self._whitespace_re.match(line) or self._comment_re.match(line):
6368        continue
6369      match = self._function_re.match(line)
6370      if match:
6371        prefixed_name = match.group(2)
6372        func_name = prefixed_name[2:]
6373        func_info = self.GetFunctionInfo(func_name)
6374        if func_info['type'] == 'Noop':
6375          continue
6376
6377        parsed_func_info = {
6378          'prefixed_name': prefixed_name,
6379          'original_name': func_name,
6380          'original_args': match.group(3),
6381          'return_type': match.group(1).strip(),
6382        }
6383
6384        for k in parsed_func_info.keys():
6385          if not k in func_info:
6386            func_info[k] = parsed_func_info[k]
6387
6388        f = Function(func_name, func_info, self.named_type_info,
6389                     self.type_handlers)
6390        if not f.GetInfo('internal'):
6391          self.original_functions.append(f)
6392
6393        #for arg in f.GetOriginalArgs():
6394        #  if not isinstance(arg, EnumArgument) and arg.type == 'GLenum':
6395        #    self.Log("%s uses bare GLenum %s." % (func_name, arg.name))
6396
6397        func_type = f.GetInfo('type')
6398        if func_type != 'NoCommand':
6399          if f.type_handler.NeedsDataTransferFunction(f):
6400            methods = f.GetDataTransferMethods()
6401            if 'immediate' in methods:
6402              self.AddFunction(ImmediateFunction(f, self.type_handlers))
6403            if 'bucket' in methods:
6404              self.AddFunction(BucketFunction(f, self.type_handlers))
6405            if 'shm' in methods:
6406              self.AddFunction(f)
6407          else:
6408            self.AddFunction(f)
6409      else:
6410        self.Error("Could not parse function: %s using regex: %s" %
6411                   (line, self._function_re.pattern))
6412
6413    self.Log("Auto Generated Functions    : %d" %
6414             len([f for f in self.functions if f.can_auto_generate or
6415                  (not f.IsType('') and not f.IsType('Custom') and
6416                   not f.IsType('Todo'))]))
6417
6418    funcs = [f for f in self.functions if not f.can_auto_generate and
6419             (f.IsType('') or f.IsType('Custom') or f.IsType('Todo'))]
6420    self.Log("Non Auto Generated Functions: %d" % len(funcs))
6421
6422    for f in funcs:
6423      self.Log("  %-10s %-20s gl%s" % (f.info['type'], f.return_type, f.name))
6424
6425  def WriteCommandIds(self, filename):
6426    """Writes the command buffer format"""
6427    with CHeaderWriter(filename, self.year) as f:
6428      f.write("#define %s_COMMAND_LIST(OP) \\\n" % _upper_prefix)
6429      cmd_id = 256
6430      for func in self.functions:
6431        f.write("  %-60s /* %d */ \\\n" %
6432                   ("OP(%s)" % func.name, cmd_id))
6433        cmd_id += 1
6434      f.write("\n")
6435
6436      f.write("enum CommandId {\n")
6437      f.write("  kOneBeforeStartPoint = cmd::kLastCommonId,  "
6438                 "// All %s commands start after this.\n" % _prefix)
6439      f.write("#define %s_CMD_OP(name) k ## name,\n" % _upper_prefix)
6440      f.write("  %s_COMMAND_LIST(%s_CMD_OP)\n" %
6441              (_upper_prefix, _upper_prefix))
6442      f.write("#undef %s_CMD_OP\n" % _upper_prefix)
6443      f.write("  kNumCommands,\n")
6444      f.write("  kFirst%sCommand = kOneBeforeStartPoint + 1\n" % _prefix)
6445      f.write("};\n")
6446      f.write("\n")
6447    self.generated_cpp_filenames.append(filename)
6448
6449  def WriteFormat(self, filename):
6450    """Writes the command buffer format"""
6451    with CHeaderWriter(filename, self.year) as f:
6452      # Forward declaration of a few enums used in constant argument
6453      # to avoid including GL header files.
6454      enum_defines = {'GL_SCANOUT_CHROMIUM': '0x6000'}
6455      if 'FenceSync' in self.function_info:
6456        enum_defines['GL_SYNC_GPU_COMMANDS_COMPLETE'] = '0x9117'
6457      if 'ClientWaitSync' in self.function_info:
6458        enum_defines['GL_SYNC_FLUSH_COMMANDS_BIT'] = '0x00000001'
6459      f.write('\n')
6460      for enum in enum_defines:
6461        f.write("#define %s %s\n" % (enum, enum_defines[enum]))
6462      f.write('\n')
6463      for func in self.functions:
6464        func.WriteStruct(f)
6465      f.write("\n")
6466    self.generated_cpp_filenames.append(filename)
6467
6468  def WriteDocs(self, filename):
6469    """Writes the command buffer doc version of the commands"""
6470    with CHeaderWriter(filename, self.year) as f:
6471      for func in self.functions:
6472        func.WriteDocs(f)
6473      f.write("\n")
6474    self.generated_cpp_filenames.append(filename)
6475
6476  def WriteFormatTest(self, filename):
6477    """Writes the command buffer format test."""
6478    comment = ("// This file contains unit tests for %s commands\n"
6479               "// It is included by %s_cmd_format_test.cc\n\n" %
6480               (_lower_prefix, _lower_prefix))
6481    with CHeaderWriter(filename, self.year, comment) as f:
6482      for func in self.functions:
6483        func.WriteFormatTest(f)
6484    self.generated_cpp_filenames.append(filename)
6485
6486  def WriteCmdHelperHeader(self, filename):
6487    """Writes the gles2 command helper."""
6488    with CHeaderWriter(filename, self.year) as f:
6489      for func in self.functions:
6490        func.WriteCmdHelper(f)
6491    self.generated_cpp_filenames.append(filename)
6492
6493  def WriteServiceContextStateHeader(self, filename):
6494    """Writes the service context state header."""
6495    comment = "// It is included by context_state.h\n"
6496    with CHeaderWriter(filename, self.year, comment) as f:
6497      f.write("struct EnableFlags {\n")
6498      f.write("  EnableFlags();\n")
6499      for capability in self.capability_flags:
6500        f.write("  bool %s;\n" % capability['name'])
6501        f.write("  bool cached_%s;\n" % capability['name'])
6502      f.write("};\n\n")
6503
6504      for state_name in sorted(_STATE_INFO.keys()):
6505        state = _STATE_INFO[state_name]
6506        for item in state['states']:
6507          if isinstance(item['default'], list):
6508            f.write("%s %s[%d];\n" % (item['type'], item['name'],
6509                                         len(item['default'])))
6510          else:
6511            f.write("%s %s;\n" % (item['type'], item['name']))
6512
6513          if item.get('cached', False):
6514            if isinstance(item['default'], list):
6515              f.write("%s cached_%s[%d];\n" % (item['type'], item['name'],
6516                                                  len(item['default'])))
6517            else:
6518              f.write("%s cached_%s;\n" % (item['type'], item['name']))
6519
6520      f.write("\n")
6521      f.write("""
6522          inline void SetDeviceCapabilityState(GLenum cap, bool enable) {
6523            switch (cap) {
6524          """)
6525      for capability in self.capability_flags:
6526        f.write("""\
6527              case GL_%s:
6528            """ % capability['name'].upper())
6529        f.write("""\
6530                if (enable_flags.cached_%(name)s == enable &&
6531                    !ignore_cached_state)
6532                  return;
6533                enable_flags.cached_%(name)s = enable;
6534                break;
6535            """ % capability)
6536
6537      f.write("""\
6538              default:
6539                NOTREACHED();
6540                return;
6541            }
6542            if (enable)
6543              api()->glEnableFn(cap);
6544            else
6545              api()->glDisableFn(cap);
6546          }
6547          """)
6548    self.generated_cpp_filenames.append(filename)
6549
6550  def WriteClientContextStateHeader(self, filename):
6551    """Writes the client context state header."""
6552    comment = "// It is included by client_context_state.h\n"
6553    with CHeaderWriter(filename, self.year, comment) as f:
6554      f.write("struct EnableFlags {\n")
6555      f.write("  EnableFlags();\n")
6556      for capability in self.capability_flags:
6557        if 'extension_flag' in capability:
6558          continue
6559        f.write("  bool %s;\n" % capability['name'])
6560      f.write("};\n\n")
6561    self.generated_cpp_filenames.append(filename)
6562
6563  def WriteContextStateGetters(self, f, class_name):
6564    """Writes the state getters."""
6565    for gl_type in ["GLint", "GLfloat"]:
6566      f.write("""
6567bool %s::GetStateAs%s(
6568    GLenum pname, %s* params, GLsizei* num_written) const {
6569  switch (pname) {
6570""" % (class_name, gl_type, gl_type))
6571      for state_name in sorted(_STATE_INFO.keys()):
6572        state = _STATE_INFO[state_name]
6573        if 'enum' in state:
6574          f.write("    case %s:\n" % state['enum'])
6575          f.write("      *num_written = %d;\n" % len(state['states']))
6576          f.write("      if (params) {\n")
6577          for ndx,item in enumerate(state['states']):
6578            f.write("        params[%d] = static_cast<%s>(%s);\n" %
6579                       (ndx, gl_type, item['name']))
6580          f.write("      }\n")
6581          f.write("      return true;\n")
6582        else:
6583          for item in state['states']:
6584            f.write("    case %s:\n" % item['enum'])
6585            if isinstance(item['default'], list):
6586              item_len = len(item['default'])
6587              f.write("      *num_written = %d;\n" % item_len)
6588              f.write("      if (params) {\n")
6589              if item['type'] == gl_type:
6590                f.write("        memcpy(params, %s, sizeof(%s) * %d);\n" %
6591                           (item['name'], item['type'], item_len))
6592              else:
6593                f.write("        for (size_t i = 0; i < %s; ++i) {\n" %
6594                           item_len)
6595                f.write("          params[i] = %s;\n" %
6596                           (GetGLGetTypeConversion(gl_type, item['type'],
6597                                                   "%s[i]" % item['name'])))
6598                f.write("        }\n");
6599            else:
6600              f.write("      *num_written = 1;\n")
6601              f.write("      if (params) {\n")
6602              f.write("        params[0] = %s;\n" %
6603                         (GetGLGetTypeConversion(gl_type, item['type'],
6604                                                 item['name'])))
6605            f.write("      }\n")
6606            f.write("      return true;\n")
6607      for capability in self.capability_flags:
6608            f.write("    case GL_%s:\n" % capability['name'].upper())
6609            f.write("      *num_written = 1;\n")
6610            f.write("      if (params) {\n")
6611            f.write(
6612                "        params[0] = static_cast<%s>(enable_flags.%s);\n" %
6613                (gl_type, capability['name']))
6614            f.write("      }\n")
6615            f.write("      return true;\n")
6616      f.write("""    default:
6617      return false;
6618  }
6619}
6620""")
6621
6622  def WriteServiceContextStateImpl(self, filename):
6623    """Writes the context state service implementation."""
6624    comment = "// It is included by context_state.cc\n"
6625    with CHeaderWriter(filename, self.year, comment) as f:
6626      code = []
6627      for capability in self.capability_flags:
6628        code.append("%s(%s)" %
6629                    (capability['name'],
6630                     ('false', 'true')['default' in capability]))
6631        code.append("cached_%s(%s)" %
6632                    (capability['name'],
6633                     ('false', 'true')['default' in capability]))
6634      f.write("ContextState::EnableFlags::EnableFlags()\n    : %s {\n}\n" %
6635                 ",\n      ".join(code))
6636      f.write("\n")
6637
6638      f.write("void ContextState::Initialize() {\n")
6639      for state_name in sorted(_STATE_INFO.keys()):
6640        state = _STATE_INFO[state_name]
6641        for item in state['states']:
6642          if isinstance(item['default'], list):
6643            for ndx, value in enumerate(item['default']):
6644              f.write("  %s[%d] = %s;\n" % (item['name'], ndx, value))
6645          else:
6646            f.write("  %s = %s;\n" % (item['name'], item['default']))
6647          if item.get('cached', False):
6648            if isinstance(item['default'], list):
6649              for ndx, value in enumerate(item['default']):
6650                f.write("  cached_%s[%d] = %s;\n" % (item['name'], ndx, value))
6651            else:
6652              f.write("  cached_%s = %s;\n" % (item['name'], item['default']))
6653      f.write("}\n")
6654
6655      f.write("""
6656void ContextState::InitCapabilities(const ContextState* prev_state) const {
6657""")
6658      def WriteCapabilities(test_prev, es3_caps):
6659        for capability in self.capability_flags:
6660          capability_name = capability['name']
6661          capability_no_init = 'no_init' in capability and \
6662              capability['no_init'] == True
6663          if capability_no_init:
6664            continue
6665          capability_es3 = 'es3' in capability and capability['es3'] == True
6666          if capability_es3 and not es3_caps or not capability_es3 and es3_caps:
6667            continue
6668          if 'extension_flag' in capability:
6669            f.write("  if (feature_info_->feature_flags().%s) {\n  " %
6670                       capability['extension_flag'])
6671          if test_prev:
6672            f.write("""  if (prev_state->enable_flags.cached_%s !=
6673                                enable_flags.cached_%s) {\n""" %
6674                       (capability_name, capability_name))
6675          f.write("    EnableDisable(GL_%s, enable_flags.cached_%s);\n" %
6676                     (capability_name.upper(), capability_name))
6677          if test_prev:
6678            f.write("  }")
6679          if 'extension_flag' in capability:
6680            f.write("  }")
6681
6682      f.write("  if (prev_state) {")
6683      WriteCapabilities(True, False)
6684      f.write("    if (feature_info_->IsES3Capable()) {\n")
6685      WriteCapabilities(True, True)
6686      f.write("    }\n")
6687      f.write("  } else {")
6688      WriteCapabilities(False, False)
6689      f.write("    if (feature_info_->IsES3Capable()) {\n")
6690      WriteCapabilities(False, True)
6691      f.write("    }\n")
6692      f.write("  }")
6693      f.write("""}
6694
6695void ContextState::InitState(const ContextState *prev_state) const {
6696""")
6697
6698      def WriteStates(test_prev):
6699        # We need to sort the keys so the expectations match
6700        for state_name in sorted(_STATE_INFO.keys()):
6701          state = _STATE_INFO[state_name]
6702          if 'no_init' in state and state['no_init']:
6703            continue
6704          if state['type'] == 'FrontBack':
6705            num_states = len(state['states'])
6706            for ndx, group in enumerate(Grouper(num_states / 2,
6707                                        state['states'])):
6708              if test_prev:
6709                f.write("  if (")
6710              args = []
6711              for place, item in enumerate(group):
6712                item_name = CachedStateName(item)
6713                args.append('%s' % item_name)
6714                if test_prev:
6715                  if place > 0:
6716                    f.write(' ||\n')
6717                  f.write("(%s != prev_state->%s)" % (item_name, item_name))
6718              if test_prev:
6719                f.write(")\n")
6720              f.write(
6721                  "  api()->gl%sFn(%s, %s);\n" %
6722                  (state['func'], ('GL_FRONT', 'GL_BACK')[ndx],
6723                   ", ".join(args)))
6724          elif state['type'] == 'NamedParameter':
6725            for item in state['states']:
6726              item_name = CachedStateName(item)
6727
6728              operation = []
6729              if test_prev:
6730                if isinstance(item['default'], list):
6731                  operation.append("  if (memcmp(prev_state->%s, %s, "
6732                                      "sizeof(%s) * %d)) {\n" %
6733                                      (item_name, item_name, item['type'],
6734                                      len(item['default'])))
6735                else:
6736                  operation.append("  if (prev_state->%s != %s) {\n  " %
6737                                      (item_name, item_name))
6738
6739              operation.append("  api()->gl%sFn(%s, %s);\n" %
6740                             (state['func'],
6741                             (item['enum_set']
6742                                 if 'enum_set' in item else item['enum']),
6743                             item['name']))
6744
6745              if test_prev:
6746                operation.append("  }")
6747
6748              guarded_operation = GuardState(item, ''.join(operation),
6749                                             "feature_info_")
6750              f.write(guarded_operation)
6751          else:
6752            if 'extension_flag' in state:
6753              f.write("  if (feature_info_->feature_flags().%s)\n  " %
6754                         state['extension_flag'])
6755            if test_prev:
6756              f.write("  if (")
6757            args = []
6758            for place, item in enumerate(state['states']):
6759              item_name = CachedStateName(item)
6760              args.append('%s' % item_name)
6761              if test_prev:
6762                if place > 0:
6763                  f.write(' ||\n')
6764                f.write("(%s != prev_state->%s)" %
6765                           (item_name, item_name))
6766            if test_prev:
6767              f.write("    )\n")
6768            if 'custom_function' in state:
6769              f.write("  %s(%s);\n" % (state['func'], ", ".join(args)))
6770            else:
6771              f.write("  api()->gl%sFn(%s);\n" % (state['func'],
6772                                                  ", ".join(args)))
6773
6774      f.write("  if (prev_state) {")
6775      WriteStates(True)
6776      f.write("  } else {")
6777      WriteStates(False)
6778      f.write("  }")
6779      f.write("  InitStateManual(prev_state);")
6780      f.write("}\n")
6781
6782      f.write("""bool ContextState::GetEnabled(GLenum cap) const {
6783  switch (cap) {
6784""")
6785      for capability in self.capability_flags:
6786        f.write("    case GL_%s:\n" % capability['name'].upper())
6787        f.write("      return enable_flags.%s;\n" % capability['name'])
6788      f.write("""    default:
6789      NOTREACHED();
6790      return false;
6791  }
6792}
6793""")
6794      self.WriteContextStateGetters(f, "ContextState")
6795    self.generated_cpp_filenames.append(filename)
6796
6797  def WriteClientContextStateImpl(self, filename):
6798    """Writes the context state client side implementation."""
6799    comment = "// It is included by client_context_state.cc\n"
6800    with CHeaderWriter(filename, self.year, comment) as f:
6801      code = []
6802      for capability in self.capability_flags:
6803        if 'extension_flag' in capability:
6804          continue
6805        code.append("%s(%s)" %
6806                    (capability['name'],
6807                     ('false', 'true')['default' in capability]))
6808      f.write(
6809        "ClientContextState::EnableFlags::EnableFlags()\n    : %s {\n}\n" %
6810        ",\n      ".join(code))
6811      f.write("\n")
6812
6813      f.write("""
6814bool ClientContextState::SetCapabilityState(
6815    GLenum cap, bool enabled, bool* changed) {
6816  *changed = false;
6817  switch (cap) {
6818""")
6819      for capability in self.capability_flags:
6820        if 'extension_flag' in capability:
6821          continue
6822        f.write("    case GL_%s:\n" % capability['name'].upper())
6823        f.write("""      if (enable_flags.%(name)s != enabled) {
6824         *changed = true;
6825         enable_flags.%(name)s = enabled;
6826      }
6827      return true;
6828""" % capability)
6829      f.write("""    default:
6830      return false;
6831  }
6832}
6833""")
6834      f.write("""bool ClientContextState::GetEnabled(
6835    GLenum cap, bool* enabled) const {
6836  switch (cap) {
6837""")
6838      for capability in self.capability_flags:
6839        if 'extension_flag' in capability:
6840          continue
6841        f.write("    case GL_%s:\n" % capability['name'].upper())
6842        f.write("      *enabled = enable_flags.%s;\n" % capability['name'])
6843        f.write("      return true;\n")
6844      f.write("""    default:
6845      return false;
6846  }
6847}
6848""")
6849    self.generated_cpp_filenames.append(filename)
6850
6851  def WriteServiceImplementation(self, filename):
6852    """Writes the service decoder implementation."""
6853    comment = "// It is included by %s_cmd_decoder.cc\n" % _lower_prefix
6854    with CHeaderWriter(filename, self.year, comment) as f:
6855      for func in self.functions:
6856        func.WriteServiceImplementation(f)
6857      if self.capability_flags and _prefix == 'GLES2':
6858        f.write("""
6859bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
6860  switch (cap) {
6861""")
6862        for capability in self.capability_flags:
6863          f.write("    case GL_%s:\n" % capability['name'].upper())
6864          if 'on_change' in capability:
6865
6866            f.write("""\
6867              state_.enable_flags.%(name)s = enabled;
6868              if (state_.enable_flags.cached_%(name)s != enabled
6869                  || state_.ignore_cached_state) {
6870                %(on_change)s
6871              }
6872              return false;
6873              """ % capability)
6874          else:
6875            f.write("""\
6876              state_.enable_flags.%(name)s = enabled;
6877              if (state_.enable_flags.cached_%(name)s != enabled
6878                  || state_.ignore_cached_state) {
6879                state_.enable_flags.cached_%(name)s = enabled;
6880                return true;
6881              }
6882              return false;
6883              """ % capability)
6884        f.write("""    default:
6885      NOTREACHED();
6886      return false;
6887  }
6888}
6889""")
6890    self.generated_cpp_filenames.append(filename)
6891
6892  def WritePassthroughServiceImplementation(self, filename):
6893    """Writes the passthrough service decoder implementation."""
6894    with CWriter(filename, self.year) as f:
6895      header = """
6896#include \"gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h\"
6897
6898namespace gpu {
6899namespace gles2 {
6900
6901""";
6902      f.write(header);
6903
6904      for func in self.functions:
6905        func.WritePassthroughServiceImplementation(f)
6906
6907      footer = """
6908}  // namespace gles2
6909}  // namespace gpu
6910
6911""";
6912      f.write(footer);
6913    self.generated_cpp_filenames.append(filename)
6914
6915  def WriteServiceUnitTests(self, filename_pattern):
6916    """Writes the service decoder unit tests."""
6917    num_tests = len(self.functions)
6918    FUNCTIONS_PER_FILE = 98  # hard code this so it doesn't change.
6919    count = 0
6920    for test_num in range(0, num_tests, FUNCTIONS_PER_FILE):
6921      count += 1
6922      filename = filename_pattern % count
6923      comment = "// It is included by %s_cmd_decoder_unittest_%d.cc\n" \
6924                % (_lower_prefix, count)
6925      with CHeaderWriter(filename, self.year, comment) as f:
6926        end = test_num + FUNCTIONS_PER_FILE
6927        if end > num_tests:
6928          end = num_tests
6929        for idx in range(test_num, end):
6930          func = self.functions[idx]
6931          test_name = '%sDecoderTest%d' % (_prefix, count)
6932          if func.IsES3():
6933            test_name = 'GLES3DecoderTest%d' % count
6934
6935          # Do any filtering of the functions here, so that the functions
6936          # will not move between the numbered files if filtering properties
6937          # are changed.
6938          if func.GetInfo('extension_flag'):
6939            continue
6940
6941          if func.GetInfo('unit_test') != False:
6942            func.WriteServiceUnitTest(f, {
6943              'test_name': test_name
6944            })
6945      self.generated_cpp_filenames.append(filename)
6946
6947
6948  def WriteServiceContextStateTestHelpers(self, filename):
6949    comment = "// It is included by context_state_test_helpers.cc\n"
6950    with CHeaderWriter(filename, self.year, comment) as f:
6951      if self.capability_flags:
6952        f.write(
6953            """void ContextStateTestHelpers::SetupInitCapabilitiesExpectations(
6954    MockGL* gl,
6955    gles2::FeatureInfo* feature_info) {
6956""")
6957        for capability in self.capability_flags:
6958          capability_no_init = 'no_init' in capability and \
6959              capability['no_init'] == True
6960          if capability_no_init:
6961              continue
6962          capability_es3 = 'es3' in capability and capability['es3'] == True
6963          if capability_es3:
6964            continue
6965          if 'extension_flag' in capability:
6966            f.write("  if (feature_info->feature_flags().%s) {\n" %
6967                     capability['extension_flag'])
6968            f.write("  ")
6969          f.write("  ExpectEnableDisable(gl, GL_%s, %s);\n" %
6970                  (capability['name'].upper(),
6971                   ('false', 'true')['default' in capability]))
6972          if 'extension_flag' in capability:
6973            f.write("  }")
6974        f.write("  if (feature_info->IsES3Capable()) {")
6975        for capability in self.capability_flags:
6976          capability_es3 = 'es3' in capability and capability['es3'] == True
6977          if capability_es3:
6978            f.write("    ExpectEnableDisable(gl, GL_%s, %s);\n" %
6979                       (capability['name'].upper(),
6980                        ('false', 'true')['default' in capability]))
6981        f.write("""  }
6982}
6983""")
6984      f.write("""
6985void ContextStateTestHelpers::SetupInitStateExpectations(
6986    MockGL* gl,
6987    gles2::FeatureInfo* feature_info,
6988    const gfx::Size& initial_size) {
6989""")
6990      # We need to sort the keys so the expectations match
6991      for state_name in sorted(_STATE_INFO.keys()):
6992        state = _STATE_INFO[state_name]
6993        if state['type'] == 'FrontBack':
6994          num_states = len(state['states'])
6995          for ndx, group in enumerate(Grouper(num_states / 2,
6996                                              state['states'])):
6997            args = []
6998            for item in group:
6999              if 'expected' in item:
7000                args.append(item['expected'])
7001              else:
7002                args.append(item['default'])
7003            f.write(
7004                "  EXPECT_CALL(*gl, %s(%s, %s))\n" %
7005                (state['func'], ('GL_FRONT', 'GL_BACK')[ndx],
7006                 ", ".join(args)))
7007            f.write("      .Times(1)\n")
7008            f.write("      .RetiresOnSaturation();\n")
7009        elif state['type'] == 'NamedParameter':
7010          for item in state['states']:
7011            expect_value = item['default']
7012            if isinstance(expect_value, list):
7013              # TODO: Currently we do not check array values.
7014              expect_value = "_"
7015
7016            operation = []
7017            operation.append(
7018                             "  EXPECT_CALL(*gl, %s(%s, %s))\n" %
7019                             (state['func'],
7020                              (item['enum_set']
7021                                  if 'enum_set' in item else item['enum']),
7022                              expect_value))
7023            operation.append("      .Times(1)\n")
7024            operation.append("      .RetiresOnSaturation();\n")
7025
7026            guarded_operation = GuardState(item, ''.join(operation),
7027                                           "feature_info")
7028            f.write(guarded_operation)
7029        elif 'no_init' not in state:
7030          if 'extension_flag' in state:
7031            f.write("  if (feature_info->feature_flags().%s) {\n" %
7032                       state['extension_flag'])
7033            f.write("  ")
7034          args = []
7035          for item in state['states']:
7036            if 'expected' in item:
7037              args.append(item['expected'])
7038            else:
7039              args.append(item['default'])
7040          # TODO: Currently we do not check array values.
7041          args = ["_" if isinstance(arg, list) else arg for arg in args]
7042          if 'custom_function' in state:
7043            f.write("  SetupInitStateManualExpectationsFor%s(gl, %s);\n" %
7044                       (state['func'], ", ".join(args)))
7045          else:
7046            f.write("  EXPECT_CALL(*gl, %s(%s))\n" %
7047                       (state['func'], ", ".join(args)))
7048            f.write("      .Times(1)\n")
7049            f.write("      .RetiresOnSaturation();\n")
7050          if 'extension_flag' in state:
7051            f.write("  }\n")
7052      f.write("  SetupInitStateManualExpectations(gl, feature_info);\n")
7053      f.write("}\n")
7054    self.generated_cpp_filenames.append(filename)
7055
7056  def WriteServiceUnitTestsForExtensions(self, filename):
7057    """Writes the service decoder unit tests for functions with extension_flag.
7058
7059       The functions are special in that they need a specific unit test
7060       baseclass to turn on the extension.
7061    """
7062    functions = [f for f in self.functions if f.GetInfo('extension_flag')]
7063    comment = "// It is included by gles2_cmd_decoder_unittest_extensions.cc\n"
7064    with CHeaderWriter(filename, self.year, comment) as f:
7065      for func in functions:
7066        if True:
7067          if func.GetInfo('unit_test') != False:
7068            extension = ToCamelCase(
7069              ToGLExtensionString(func.GetInfo('extension_flag')))
7070            test_name = 'GLES2DecoderTestWith%s' % extension
7071            if func.IsES3():
7072              test_name = 'GLES3DecoderTestWith%s' % extension
7073            func.WriteServiceUnitTest(f, {
7074              'test_name': test_name
7075            })
7076    self.generated_cpp_filenames.append(filename)
7077
7078  def WriteGLES2Header(self, filename):
7079    """Writes the GLES2 header."""
7080    comment = "// This file contains Chromium-specific GLES2 declarations.\n\n"
7081    with CHeaderWriter(filename, self.year, comment) as f:
7082      for func in self.original_functions:
7083        func.WriteGLES2Header(f)
7084      f.write("\n")
7085    self.generated_cpp_filenames.append(filename)
7086
7087  def WriteGLES2CLibImplementation(self, filename):
7088    """Writes the GLES2 c lib implementation."""
7089    comment = "// These functions emulate GLES2 over command buffers.\n"
7090    with CHeaderWriter(filename, self.year, comment) as f:
7091      for func in self.original_functions:
7092        func.WriteGLES2CLibImplementation(f)
7093      f.write("""
7094namespace gles2 {
7095
7096extern const NameToFunc g_gles2_function_table[] = {
7097""")
7098      for func in self.original_functions:
7099        f.write(
7100            '  { "gl%s", reinterpret_cast<GLES2FunctionPointer>(gl%s), },\n' %
7101            (func.name, func.name))
7102      f.write("""  { nullptr, nullptr, },
7103};
7104
7105}  // namespace gles2
7106""")
7107    self.generated_cpp_filenames.append(filename)
7108
7109  def WriteGLES2InterfaceHeader(self, filename):
7110    """Writes the GLES2 interface header."""
7111    comment = ("// This file is included by %s_interface.h to declare the\n"
7112               "// GL api functions.\n" % _lower_prefix)
7113    with CHeaderWriter(filename, self.year, comment) as f:
7114      for func in self.original_functions:
7115        func.WriteGLES2InterfaceHeader(f)
7116    self.generated_cpp_filenames.append(filename)
7117
7118  def WriteGLES2InterfaceStub(self, filename):
7119    """Writes the GLES2 interface stub header."""
7120    comment = "// This file is included by gles2_interface_stub.h.\n"
7121    with CHeaderWriter(filename, self.year, comment) as f:
7122      for func in self.original_functions:
7123        func.WriteGLES2InterfaceStub(f)
7124    self.generated_cpp_filenames.append(filename)
7125
7126  def WriteGLES2InterfaceStubImpl(self, filename):
7127    """Writes the GLES2 interface header."""
7128    comment = "// This file is included by gles2_interface_stub.cc.\n"
7129    with CHeaderWriter(filename, self.year, comment) as f:
7130      for func in self.original_functions:
7131        func.WriteGLES2InterfaceStubImpl(f)
7132    self.generated_cpp_filenames.append(filename)
7133
7134  def WriteGLES2ImplementationHeader(self, filename):
7135    """Writes the GLES2 Implementation header."""
7136    comment = \
7137      ("// This file is included by %s_implementation.h to declare the\n"
7138       "// GL api functions.\n" % _lower_prefix)
7139    with CHeaderWriter(filename, self.year, comment) as f:
7140      for func in self.original_functions:
7141        func.WriteGLES2ImplementationHeader(f)
7142    self.generated_cpp_filenames.append(filename)
7143
7144  def WriteGLES2Implementation(self, filename):
7145    """Writes the GLES2 Implementation."""
7146    comment = \
7147      ("// This file is included by %s_implementation.cc to define the\n"
7148       "// GL api functions.\n" % _lower_prefix)
7149    with CHeaderWriter(filename, self.year, comment) as f:
7150      for func in self.original_functions:
7151        func.WriteGLES2Implementation(f)
7152    self.generated_cpp_filenames.append(filename)
7153
7154  def WriteGLES2TraceImplementationHeader(self, filename):
7155    """Writes the GLES2 Trace Implementation header."""
7156    comment = "// This file is included by gles2_trace_implementation.h\n"
7157    with CHeaderWriter(filename, self.year, comment) as f:
7158      for func in self.original_functions:
7159        func.WriteGLES2TraceImplementationHeader(f)
7160    self.generated_cpp_filenames.append(filename)
7161
7162  def WriteGLES2TraceImplementation(self, filename):
7163    """Writes the GLES2 Trace Implementation."""
7164    comment = "// This file is included by gles2_trace_implementation.cc\n"
7165    with CHeaderWriter(filename, self.year, comment) as f:
7166      for func in self.original_functions:
7167        func.WriteGLES2TraceImplementation(f)
7168    self.generated_cpp_filenames.append(filename)
7169
7170  def WriteGLES2ImplementationUnitTests(self, filename):
7171    """Writes the GLES2 helper header."""
7172    comment = \
7173      ("// This file is included by %s_implementation.h to declare the\n"
7174       "// GL api functions.\n" % _lower_prefix)
7175    with CHeaderWriter(filename, self.year, comment) as f:
7176      for func in self.original_functions:
7177        func.WriteGLES2ImplementationUnitTest(f)
7178    self.generated_cpp_filenames.append(filename)
7179
7180  def WriteServiceUtilsHeader(self, filename):
7181    """Writes the gles2 auto generated utility header."""
7182    with CHeaderWriter(filename, self.year) as f:
7183      for name in sorted(self.named_type_info.keys()):
7184        named_type = NamedType(self.named_type_info[name])
7185        if not named_type.CreateValidator():
7186          continue
7187        class_name = ValidatorClassName(name)
7188        if named_type.IsComplete():
7189          f.write("""class %(class_name)s {
7190                      public:
7191                       bool IsValid(const %(type)s value) const;"""% {
7192            'class_name': class_name,
7193            'type': named_type.GetType()
7194          })
7195          if named_type.HasES3Values():
7196            f.write("""%s();
7197                       void SetIsES3(bool is_es3) { is_es3_ = is_es3; }
7198                      private:
7199                       bool is_es3_;""" % class_name)
7200          f.write("};\n")
7201          f.write("%s %s;\n\n" %
7202                     (class_name, ToUnderscore(name)))
7203        else:
7204          f.write("ValueValidator<%s> %s;\n" %
7205                     (named_type.GetType(), ToUnderscore(name)))
7206      f.write("\n")
7207    self.generated_cpp_filenames.append(filename)
7208
7209  def WriteServiceUtilsImplementation(self, filename):
7210    """Writes the gles2 auto generated utility implementation."""
7211    with CHeaderWriter(filename, self.year) as f:
7212      names = sorted(self.named_type_info.keys())
7213      for name in names:
7214        named_type = NamedType(self.named_type_info[name])
7215        class_name = ValidatorClassName(name)
7216        if not named_type.CreateValidator():
7217          continue
7218        if named_type.IsComplete():
7219          if named_type.HasES3Values():
7220            f.write("""Validators::%(class_name)s::%(class_name)s()
7221                         : is_es3_(false) {}""" % { 'class_name': class_name })
7222
7223          f.write("""bool Validators::%(class_name)s::IsValid(
7224                         const %(type)s value) const {
7225                       switch(value) {\n""" % {
7226            'class_name': class_name,
7227            'type': named_type.GetType()
7228          })
7229          if named_type.GetValidValues():
7230            for value in named_type.GetValidValues():
7231                f.write("case %s:\n" % value)
7232            f.write("return true;\n")
7233          if named_type.GetValidValuesES3():
7234            for value in named_type.GetValidValuesES3():
7235                f.write("case %s:\n" % value)
7236            f.write("return is_es3_;\n")
7237          if named_type.GetDeprecatedValuesES3():
7238            for value in named_type.GetDeprecatedValuesES3():
7239                f.write("case %s:\n" % value)
7240            f.write("return !is_es3_;\n")
7241          f.write("}\nreturn false;\n}\n")
7242          f.write("\n")
7243        else:
7244          if named_type.GetValidValues():
7245            f.write("static const %s valid_%s_table[] = {\n" %
7246                       (named_type.GetType(), ToUnderscore(name)))
7247            for value in named_type.GetValidValues():
7248              f.write("  %s,\n" % value)
7249            f.write("};\n")
7250            f.write("\n")
7251          if named_type.GetValidValuesES3():
7252            f.write("static const %s valid_%s_table_es3[] = {\n" %
7253                       (named_type.GetType(), ToUnderscore(name)))
7254            for value in named_type.GetValidValuesES3():
7255              f.write("  %s,\n" % value)
7256            f.write("};\n")
7257            f.write("\n")
7258          if named_type.GetDeprecatedValuesES3():
7259            f.write("static const %s deprecated_%s_table_es3[] = {\n" %
7260                       (named_type.GetType(), ToUnderscore(name)))
7261            for value in named_type.GetDeprecatedValuesES3():
7262              f.write("  %s,\n" % value)
7263            f.write("};\n")
7264          f.write("\n")
7265      f.write("Validators::Validators()")
7266      pre = '    : '
7267      for name in names:
7268        named_type = NamedType(self.named_type_info[name])
7269        if not named_type.CreateValidator() or named_type.IsComplete():
7270          continue
7271        if named_type.GetValidValues():
7272          code = """%(pre)s%(name)s(
7273            valid_%(name)s_table, base::size(valid_%(name)s_table))"""
7274        else:
7275          code = "%(pre)s%(name)s()"
7276        f.write(code % {
7277          'name': ToUnderscore(name),
7278          'pre': pre,
7279        })
7280        pre = ',\n    '
7281      f.write(" {\n");
7282      f.write("}\n\n");
7283
7284      if _prefix == 'GLES2':
7285        f.write("void Validators::UpdateValuesES3() {\n")
7286        for name in names:
7287          named_type = NamedType(self.named_type_info[name])
7288          if not named_type.IsConstant() and named_type.IsComplete():
7289            if named_type.HasES3Values():
7290              f.write("  %(name)s.SetIsES3(true);" % {
7291                'name': ToUnderscore(name),
7292              })
7293            continue
7294          if named_type.GetDeprecatedValuesES3():
7295            code = """  %(name)s.RemoveValues(
7296      deprecated_%(name)s_table_es3, base::size(deprecated_%(name)s_table_es3));
7297"""
7298            f.write(code % {
7299              'name': ToUnderscore(name),
7300            })
7301          if named_type.GetValidValuesES3():
7302            code = """  %(name)s.AddValues(
7303      valid_%(name)s_table_es3, base::size(valid_%(name)s_table_es3));
7304"""
7305            f.write(code % {
7306              'name': ToUnderscore(name),
7307            })
7308        f.write("}\n\n");
7309
7310        f.write("void Validators::UpdateETCCompressedTextureFormats() {\n")
7311        for name in ['CompressedTextureFormat', 'TextureInternalFormatStorage']:
7312          for fmt in _ETC_COMPRESSED_TEXTURE_FORMATS:
7313            code = """  %(name)s.AddValue(%(format)s);
7314"""
7315            f.write(code % {
7316              'name': ToUnderscore(name),
7317              'format': fmt,
7318            })
7319        f.write("}\n\n");
7320    self.generated_cpp_filenames.append(filename)
7321
7322  def WriteCommonUtilsHeader(self, filename):
7323    """Writes the gles2 common utility header."""
7324    with CHeaderWriter(filename, self.year) as f:
7325      type_infos = sorted(self.named_type_info.keys())
7326      for type_info in type_infos:
7327        if self.named_type_info[type_info]['type'] == 'GLenum':
7328          f.write("static std::string GetString%s(uint32_t value);\n" %
7329                     type_info)
7330      f.write("\n")
7331    self.generated_cpp_filenames.append(filename)
7332
7333  def WriteCommonUtilsImpl(self, filename):
7334    """Writes the gles2 common utility header."""
7335    enum_re = re.compile(r'\#define\s+(GL_[a-zA-Z0-9_]+)\s+([0-9A-Fa-fx]+)')
7336    define_dict = {}
7337    for fname in ['third_party/khronos/GLES2/gl2.h',
7338                  'third_party/khronos/GLES2/gl2ext.h',
7339                  'third_party/khronos/GLES3/gl3.h',
7340                  'third_party/khronos/GLES3/gl31.h',
7341                  'gpu/GLES2/gl2chromium.h',
7342                  'gpu/GLES2/gl2extchromium.h']:
7343      fname = os.path.join(self.chromium_root_dir, fname)
7344      lines = open(fname).readlines()
7345      for line in lines:
7346        m = enum_re.match(line)
7347        if m:
7348          name = m.group(1)
7349          value = m.group(2)
7350          if len(value) <= 10 and value.startswith('0x'):
7351            if not value in define_dict:
7352              define_dict[value] = name
7353            # check our own _CHROMIUM macro conflicts with khronos GL headers.
7354            elif EnumsConflict(define_dict[value], name):
7355              self.Error("code collision: %s and %s have the same code %s" %
7356                         (define_dict[value], name, value))
7357
7358    with CHeaderWriter(filename, self.year) as f:
7359      f.write("static const %sUtil::EnumToString "
7360                 "enum_to_string_table[] = {\n" % _prefix)
7361      for value in sorted(define_dict):
7362        f.write('  { %s, "%s", },\n' % (value, define_dict[value]))
7363      f.write("""};
7364
7365const %(p)sUtil::EnumToString* const %(p)sUtil::enum_to_string_table_ =
7366    enum_to_string_table;
7367const size_t %(p)sUtil::enum_to_string_table_len_ =
7368    sizeof(enum_to_string_table) / sizeof(enum_to_string_table[0]);
7369
7370""" % { 'p' : _prefix})
7371
7372      enums = sorted(self.named_type_info.keys())
7373      for enum in enums:
7374        if self.named_type_info[enum]['type'] == 'GLenum':
7375          f.write("std::string %sUtil::GetString%s(uint32_t value) {\n" %
7376                     (_prefix, enum))
7377          valid_list = self.named_type_info[enum]['valid']
7378          if 'valid_es3' in self.named_type_info[enum]:
7379            for es3_enum in self.named_type_info[enum]['valid_es3']:
7380              if not es3_enum in valid_list:
7381                valid_list.append(es3_enum)
7382          assert len(valid_list) == len(set(valid_list))
7383          if len(valid_list) > 0:
7384            f.write("  static const EnumToString string_table[] = {\n")
7385            for value in valid_list:
7386              f.write('    { %s, "%s" },\n' % (value, value))
7387            f.write("""  };
7388  return %sUtil::GetQualifiedEnumString(
7389      string_table, base::size(string_table), value);
7390}
7391
7392""" % _prefix)
7393          else:
7394            f.write("""  return %sUtil::GetQualifiedEnumString(
7395      nullptr, 0, value);
7396}
7397
7398""" % _prefix)
7399    self.generated_cpp_filenames.append(filename)
7400
7401  def WritePepperGLES2Interface(self, filename, dev):
7402    """Writes the Pepper OpenGLES interface definition."""
7403    with CWriter(filename, self.year) as f:
7404      f.write("label Chrome {\n")
7405      f.write("  M39 = 1.0\n")
7406      f.write("};\n\n")
7407
7408      if not dev:
7409        # Declare GL types.
7410        f.write("[version=1.0]\n")
7411        f.write("describe {\n")
7412        for gltype in ['GLbitfield', 'GLboolean', 'GLbyte', 'GLclampf',
7413                       'GLclampx', 'GLenum', 'GLfixed', 'GLfloat', 'GLint',
7414                       'GLintptr', 'GLshort', 'GLsizei', 'GLsizeiptr',
7415                       'GLubyte', 'GLuint', 'GLushort']:
7416          f.write("  %s;\n" % gltype)
7417          f.write("  %s_ptr_t;\n" % gltype)
7418        f.write("};\n\n")
7419
7420      # C level typedefs.
7421      f.write("#inline c\n")
7422      f.write("#include \"ppapi/c/pp_resource.h\"\n")
7423      if dev:
7424        f.write("#include \"ppapi/c/ppb_opengles2.h\"\n\n")
7425      else:
7426        f.write("\n#ifndef __gl2_h_\n")
7427        for (k, v) in _GL_TYPES.iteritems():
7428          f.write("typedef %s %s;\n" % (v, k))
7429        f.write("#ifdef _WIN64\n")
7430        for (k, v) in _GL_TYPES_64.iteritems():
7431          f.write("typedef %s %s;\n" % (v, k))
7432        f.write("#else\n")
7433        for (k, v) in _GL_TYPES_32.iteritems():
7434          f.write("typedef %s %s;\n" % (v, k))
7435        f.write("#endif  // _WIN64\n")
7436        f.write("#endif  // __gl2_h_\n\n")
7437      f.write("#endinl\n")
7438
7439      for interface in self.pepper_interfaces:
7440        if interface.dev != dev:
7441          continue
7442        # Historically, we provide OpenGLES2 interfaces with struct
7443        # namespace. Not to break code which uses the interface as
7444        # "struct OpenGLES2", we put it in struct namespace.
7445        f.write('\n[macro="%s", force_struct_namespace]\n' %
7446                   interface.GetInterfaceName())
7447        f.write("interface %s {\n" % interface.GetStructName())
7448        for func in self.original_functions:
7449          if not func.InPepperInterface(interface):
7450            continue
7451
7452          ret_type = func.MapCTypeToPepperIdlType(func.return_type,
7453                                                  is_for_return_type=True)
7454          func_prefix = "  %s %s(" % (ret_type, func.GetPepperName())
7455          f.write(func_prefix)
7456          f.write("[in] PP_Resource context")
7457          for arg in func.MakeTypedPepperIdlArgStrings():
7458            f.write(",\n" + " " * len(func_prefix) + arg)
7459          f.write(");\n")
7460        f.write("};\n\n")
7461
7462  def WritePepperGLES2Implementation(self, filename):
7463    """Writes the Pepper OpenGLES interface implementation."""
7464    with CWriter(filename, self.year) as f:
7465      f.write("#include \"ppapi/shared_impl/ppb_opengles2_shared.h\"\n\n")
7466      f.write("#include \"base/logging.h\"\n")
7467      f.write("#include \"gpu/command_buffer/client/gles2_implementation.h\"\n")
7468      f.write("#include \"ppapi/shared_impl/ppb_graphics_3d_shared.h\"\n")
7469      f.write("#include \"ppapi/thunk/enter.h\"\n\n")
7470
7471      f.write("namespace ppapi {\n\n")
7472      f.write("namespace {\n\n")
7473
7474      f.write("typedef thunk::EnterResource<thunk::PPB_Graphics3D_API>"
7475                 " Enter3D;\n\n")
7476
7477      f.write("gpu::gles2::GLES2Implementation* ToGles2Impl(Enter3D*"
7478                 " enter) {\n")
7479      f.write("  DCHECK(enter);\n")
7480      f.write("  DCHECK(enter->succeeded());\n")
7481      f.write("  return static_cast<PPB_Graphics3D_Shared*>(enter->object())->"
7482                 "gles2_impl();\n");
7483      f.write("}\n\n");
7484
7485      for func in self.original_functions:
7486        if not func.InAnyPepperExtension():
7487          continue
7488
7489        original_arg = func.MakeTypedPepperArgString("")
7490        context_arg = "PP_Resource context_id"
7491        if len(original_arg):
7492          arg = context_arg + ", " + original_arg
7493        else:
7494          arg = context_arg
7495        f.write("%s %s(%s) {\n" %
7496                   (func.return_type, func.GetPepperName(), arg))
7497        f.write("  Enter3D enter(context_id, true);\n")
7498        f.write("  if (enter.succeeded()) {\n")
7499
7500        return_str = "" if func.return_type == "void" else "return "
7501        f.write("    %sToGles2Impl(&enter)->%s(%s);\n" %
7502                   (return_str, func.original_name,
7503                    func.MakeOriginalArgString("")))
7504        f.write("  }")
7505        if func.return_type == "void":
7506          f.write("\n")
7507        else:
7508          f.write(" else {\n")
7509          f.write("    return %s;\n" % func.GetErrorReturnString())
7510          f.write("  }\n")
7511        f.write("}\n\n")
7512
7513      f.write("}  // namespace\n")
7514
7515      for interface in self.pepper_interfaces:
7516        f.write("const %s* PPB_OpenGLES2_Shared::Get%sInterface() {\n" %
7517                   (interface.GetStructName(), interface.GetName()))
7518        f.write("  static const struct %s "
7519                   "ppb_opengles2 = {\n" % interface.GetStructName())
7520        f.write("    &")
7521        f.write(",\n    &".join(
7522          f.GetPepperName() for f in self.original_functions
7523            if f.InPepperInterface(interface)))
7524        f.write("\n")
7525
7526        f.write("  };\n")
7527        f.write("  return &ppb_opengles2;\n")
7528        f.write("}\n")
7529
7530      f.write("}  // namespace ppapi\n")
7531    self.generated_cpp_filenames.append(filename)
7532
7533  def WriteGLES2ToPPAPIBridge(self, filename):
7534    """Connects GLES2 helper library to PPB_OpenGLES2 interface"""
7535    with CWriter(filename, self.year) as f:
7536      f.write("#ifndef GL_GLEXT_PROTOTYPES\n")
7537      f.write("#define GL_GLEXT_PROTOTYPES\n")
7538      f.write("#endif\n")
7539      f.write("#include <GLES2/gl2.h>\n")
7540      f.write("#include <GLES2/gl2ext.h>\n")
7541      f.write("#include \"ppapi/lib/gl/gles2/gl2ext_ppapi.h\"\n\n")
7542
7543      for func in self.original_functions:
7544        if not func.InAnyPepperExtension():
7545          continue
7546
7547        interface = self.interface_info[func.GetInfo('pepper_interface') or '']
7548
7549        f.write("%s GL_APIENTRY gl%s(%s) {\n" %
7550                   (func.return_type, func.GetPepperName(),
7551                    func.MakeTypedPepperArgString("")))
7552        return_str = "" if func.return_type == "void" else "return "
7553        interface_str = "glGet%sInterfacePPAPI()" % interface.GetName()
7554        original_arg = func.MakeOriginalArgString("")
7555        context_arg = "glGetCurrentContextPPAPI()"
7556        if len(original_arg):
7557          arg = context_arg + ", " + original_arg
7558        else:
7559          arg = context_arg
7560        if interface.GetName():
7561          f.write("  const struct %s* ext = %s;\n" %
7562                     (interface.GetStructName(), interface_str))
7563          f.write("  if (ext)\n")
7564          f.write("    %sext->%s(%s);\n" %
7565                     (return_str, func.GetPepperName(), arg))
7566          if return_str:
7567            f.write("  %s0;\n" % return_str)
7568        else:
7569          f.write("  %s%s->%s(%s);\n" %
7570                     (return_str, interface_str, func.GetPepperName(), arg))
7571        f.write("}\n\n")
7572    self.generated_cpp_filenames.append(filename)
7573
7574
7575def Format(generated_files, output_dir, chromium_root_dir):
7576  """Format generated_files relative to output_dir using clang-format."""
7577  formatter = "third_party/depot_tools/clang-format"
7578  if platform.system() == "Windows":
7579    formatter = "third_party\\depot_tools\\clang-format.bat"
7580  formatter = os.path.join(chromium_root_dir, formatter)
7581  generated_files = map(lambda filename: os.path.join(output_dir, filename),
7582                        generated_files)
7583  for filename in generated_files:
7584    call([formatter, "-i", "-style=chromium", filename], cwd=chromium_root_dir)
7585