1#!/usr/bin/env python 2# Copyright 2017 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Generate data struct from GPU blocklist and driver bug workarounds json.""" 7 8import json 9import os 10import platform 11import sys 12import zlib 13from optparse import OptionParser 14from subprocess import call 15 16_LICENSE = """// Copyright (c) 2019 The Chromium Authors. All rights reserved. 17// Use of this source code is governed by a BSD-style license that can be 18// found in the LICENSE file. 19 20""" 21 22_DO_NOT_EDIT_WARNING = """// This file is auto-generated from 23// gpu/config/process_json.py 24// It's formatted by clang-format using chromium coding style: 25// clang-format -i -style=chromium filename 26// DO NOT EDIT! 27 28""" 29 30_OS_TYPE_MAP = { 31 'win': 'kOsWin', 32 'macosx': 'kOsMacosx', 33 'android': 'kOsAndroid', 34 'linux': 'kOsLinux', 35 'chromeos': 'kOsChromeOS', 36 '': 'kOsAny', 37 } 38 39INTEL_DRIVER_VERSION_SCHEMA = ''' 40The version format of Intel graphics driver is AA.BB.CCC.DDDD. 41DDDD(old schema) or CCC.DDDD(new schema) is the build number. That is, 42indicates the actual driver number. The comparison between old schema 43and new schema is NOT valid. In such a condition the only comparison 44operator that returns true is "not equal". 45 46AA.BB: You are free to specify the real number here, but they are meaningless 47when comparing two version numbers. Usually it's okay to leave it to "0.0". 48 49CCC: It's necessary for new schema. Regarding to old schema, you can speicy 50the real number or any number less than 100 in order to differentiate from 51new schema. 52 53DDDD: It's always meaningful. It must not be "0" under old schema. 54 55Legal: "24.20.100.7000", "0.0.100.7000", "0.0.0.7000", "0.0.100.0" 56Illegal: "24.0.0.0", "24.20.0.0", "0.0.99.0" 57''' 58 59NVIDIA_DRIVER_VERSION_SCHEMA = ''' 60The version format used by Nvidia is ABC.DE, where A-E are any digit. When 61queried by Chrome, it will detect XX.XX.XXXA.BCDE, where 'X' is any digit and 62can be ignored. Chrome will re-format this to ABC.DE, and compare to the 63version listed here. 64 65So, Chrome might detect 26.21.0014.4575, which would be given here as 445.75 in 66the Nvidia version schema. The 26.21.001 is ignored. 67''' 68 69 70def check_intel_driver_version(version): 71 ver_list = version.split('.') 72 if len(ver_list) != 4: 73 return False 74 for ver in ver_list: 75 if not ver.isdigit(): 76 return False 77 if int(ver_list[2]) < 100 and ver_list[3] == '0': 78 return False 79 return True 80 81def check_nvidia_driver_version(version): 82 ver_list = version.split('.') 83 # Allow "456" to match "456.*", so allow a single-entry list. 84 if len(ver_list) == 0 or len(ver_list) > 2: 85 return False; 86 elif len(ver_list) == 2 and len(ver_list[1]) != 2: 87 return False 88 # Must start with three digits, whether it's "456.*" or "456.78". 89 if len(ver_list[0]) != 3: 90 return False 91 for ver in ver_list: 92 if not ver.isdigit(): 93 return False 94 return True 95 96def load_software_rendering_list_features(feature_type_filename): 97 header_file = open(feature_type_filename, 'r') 98 start = False 99 features = [] 100 for line in header_file: 101 if line.startswith('enum GpuFeatureType {'): 102 assert not start 103 start = True 104 continue 105 if not start: 106 continue 107 line = line.strip() 108 line = line.split(' ', 1)[0] 109 line = line.split(',', 1)[0] 110 if line.startswith('NUMBER_OF_GPU_FEATURE_TYPES'): 111 assert start 112 start = False 113 break 114 elif line.startswith('GPU_FEATURE_TYPE_'): 115 name = line[len('GPU_FEATURE_TYPE_'):] 116 features.append(name.lower()) 117 else: 118 assert False 119 assert not start 120 assert len(features) > 0 121 header_file.close() 122 return features 123 124 125def load_gpu_driver_bug_workarounds(workaround_type_filename): 126 header_file = open(workaround_type_filename, 'r') 127 start = False 128 workaround = None 129 workarounds = [] 130 for line in header_file: 131 if line.startswith('#define GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP)'): 132 assert not start 133 start = True 134 continue 135 if not start: 136 continue 137 line = line.strip() 138 if line.startswith('GPU_OP('): 139 assert not workaround 140 workaround = line[len('GPU_OP('):] 141 workaround = workaround.split(',', 1)[0].lower() 142 continue 143 if workaround: 144 line = line.split(')', 1)[0] 145 assert line == workaround 146 workarounds.append(line) 147 workaround = None 148 continue 149 start = False 150 break 151 assert not start 152 assert len(workarounds) > 0 153 header_file.close() 154 return workarounds 155 156 157def get_feature_set(features, total_feature_set): 158 assert len(features) > 0 159 feature_set = set([]) 160 for feature in features: 161 if feature == 'all': 162 feature_set = set(total_feature_set) 163 elif isinstance(feature, dict): 164 for key in feature: 165 if key == 'exceptions': 166 for exception in feature['exceptions']: 167 assert exception in feature_set 168 feature_set.remove(exception) 169 else: 170 raise KeyError('only exceptions are allowed') 171 else: 172 assert feature in total_feature_set 173 feature_set.add(feature) 174 return feature_set 175 176 177def write_features(feature_set, feature_name_prefix, var_name, 178 data_helper_file): 179 data_helper_file.write('const int %s[%d] = {\n' % 180 (var_name, len(feature_set))) 181 for feature in feature_set: 182 data_helper_file.write(feature_name_prefix + feature.upper()) 183 data_helper_file.write(',\n') 184 data_helper_file.write('};\n\n') 185 186 187def write_disabled_extension_list(entry_kind, entry_id, data, data_file, 188 data_helper_file): 189 if data: 190 var_name = 'k%sForEntry%d' % (entry_kind, entry_id) 191 # define the list 192 data_helper_file.write( 193 'const char* const %s[%d] = {\n' % (var_name, len(data))) 194 for item in data: 195 write_string(item, data_helper_file) 196 data_helper_file.write(',\n') 197 data_helper_file.write('};\n\n') 198 # use the list 199 data_file.write('base::size(%s), // %s size\n' % (var_name, entry_kind)) 200 data_file.write('%s, // %s\n' % (var_name, entry_kind)) 201 else: 202 data_file.write('0, // %s size\n' % entry_kind) 203 data_file.write('nullptr, // %s\n' % entry_kind) 204 205 206def write_gl_strings(entry_id, is_exception, exception_id, data, 207 unique_symbol_id, data_file, data_helper_file): 208 if data: 209 var_name = 'kGLStringsFor%sEntry%d' % (unique_symbol_id, entry_id) 210 if is_exception: 211 var_name += 'Exception' + str(exception_id) 212 # define the GL strings 213 data_helper_file.write('const GpuControlList::GLStrings %s = {\n' % 214 var_name) 215 for item in data: 216 write_string(item, data_helper_file) 217 data_helper_file.write(',\n') 218 data_helper_file.write('};\n\n') 219 # reference the GL strings 220 data_file.write('&%s, // GL strings\n' % var_name) 221 else: 222 data_file.write('nullptr, // GL strings\n') 223 224 225def write_version(version_info, name_tag, data_file): 226 op = '' 227 style = '' 228 schema = '' 229 version1 = '' 230 version2 = '' 231 if version_info: 232 op = version_info['op'] 233 if 'style' in version_info: 234 style = version_info['style'] 235 if 'schema' in version_info: 236 schema = version_info['schema'] 237 version1 = version_info['value'] 238 if 'value2' in version_info: 239 version2 = version_info['value2'] 240 data_file.write('{') 241 op_map = { 242 '=': 'kEQ', 243 '<': 'kLT', 244 '<=': 'kLE', 245 '>': 'kGT', 246 '>=': 'kGE', 247 'any': 'kAny', 248 'between': 'kBetween', 249 '': 'kUnknown', 250 } 251 assert op in op_map 252 data_file.write('GpuControlList::%s, ' % op_map[op]) 253 style_map = { 254 'lexical': 'Lexical', 255 'numerical': 'Numerical', 256 '': 'Numerical', 257 } 258 assert style in style_map 259 data_file.write('GpuControlList::kVersionStyle%s, ' % style_map[style]) 260 schema_map = { 261 'common': 'Common', 262 'intel_driver': 'IntelDriver', 263 'nvidia_driver': 'NvidiaDriver', 264 '': 'Common', 265 } 266 assert schema in schema_map 267 data_file.write('GpuControlList::kVersionSchema%s, ' % schema_map[schema]) 268 write_string(version1, data_file) 269 data_file.write(', ') 270 write_string(version2, data_file) 271 data_file.write('}, // %s\n' % name_tag) 272 273 274def write_driver_info(entry_id, is_exception, exception_id, driver_vendor, 275 driver_version, unique_symbol_id, 276 data_file, data_helper_file): 277 var_name = 'kDriverInfoFor%sEntry%d' % (unique_symbol_id, entry_id) 278 if is_exception: 279 var_name += 'Exception' + str(exception_id) 280 # define the GL strings 281 data_helper_file.write('const GpuControlList::DriverInfo %s = {\n' % 282 var_name) 283 write_string_value(driver_vendor, 'driver_vendor', data_helper_file) 284 write_version(driver_version, 'driver_version', data_helper_file) 285 data_helper_file.write('};\n\n') 286 # reference the GL strings 287 data_file.write('&%s, // driver info\n' % var_name) 288 289 290def write_number_list(entry_id, data_type, name_tag, data, is_exception, 291 exception_id, unique_symbol_id, data_file, 292 data_helper_file): 293 if data: 294 var_name = 'k%sFor%sEntry%d' % (name_tag, unique_symbol_id, entry_id) 295 if is_exception: 296 var_name += 'Exception' + str(exception_id) 297 # define the list 298 data_helper_file.write('const %s %s[%d] = {\n' % 299 (data_type, var_name, len(data))) 300 for item in data: 301 data_helper_file.write(str(item)) 302 data_helper_file.write(',\n') 303 data_helper_file.write('};\n\n') 304 # reference the list 305 data_file.write('base::size(%s), // %s size\n' % (var_name, name_tag)) 306 data_file.write('%s, // %s\n' % (var_name, name_tag)) 307 else: 308 data_file.write('0, // %s size\n' % name_tag) 309 data_file.write('nullptr, // %s\n' % name_tag) 310 311 312def write_string(string, data_file): 313 if string == '': 314 data_file.write('nullptr') 315 else: 316 data_file.write('"%s"' % string.replace('\\', '\\\\')) 317 318 319def write_string_value(string, name_tag, data_file): 320 write_string(string, data_file) 321 data_file.write(', // %s\n' % name_tag) 322 323 324def write_boolean_value(value, name_tag, data_file): 325 data_file.write('%s, // %s\n' % (str(value).lower(), name_tag)) 326 327 328def write_integer_value(value, name_tag, data_file): 329 data_file.write('%s, // %s\n' % (str(value), name_tag)) 330 331 332def write_device_list(entry_id, device_id, device_revision, is_exception, 333 exception_id, unique_symbol_id, data_file, 334 data_helper_file): 335 if device_id: 336 # It's one of the three ways to specify devices: 337 # 1) only specify device IDs 338 # 2) specify one device ID, associated with multiple revisions 339 # 3) specify k device IDs associated with k device revisions. 340 device_size = len(device_id) 341 if device_size == 1 and device_revision and len(device_revision) > 1: 342 device_size = len(device_revision) 343 for ii in range(device_size - 1): 344 device_id.append(device_id[0]) 345 if device_revision is None: 346 device_revision = [] 347 for ii in range(device_size): 348 device_revision.append('0x0') 349 assert len(device_id) == len(device_revision) 350 var_name = 'kDevicesFor%sEntry%d' % (unique_symbol_id, entry_id) 351 if is_exception: 352 var_name += 'Exception' + str(exception_id) 353 # define the list 354 data_helper_file.write('const GpuControlList::Device %s[%d] = {\n' % 355 (var_name, len(device_id))) 356 for ii in range(device_size): 357 data_helper_file.write('{%s, %s},\n' % 358 (device_id[ii], device_revision[ii])) 359 data_helper_file.write('};\n\n') 360 # reference the list 361 data_file.write('base::size(%s), // Devices size\n' % var_name) 362 data_file.write('%s, // Devices\n' % var_name) 363 else: 364 assert not device_revision 365 data_file.write('0, // Devices size\n') 366 data_file.write('nullptr, // Devices\n') 367 368 369def write_machine_model_info(entry_id, is_exception, exception_id, 370 machine_model_name, machine_model_version, 371 data_file, data_helper_file): 372 model_name_var_name = None 373 if machine_model_name: 374 assert isinstance(machine_model_name, list) 375 model_name_var_name = 'kMachineModelNameForEntry' + str(entry_id) 376 if is_exception: 377 model_name_var_name += 'Exception' + str(exception_id) 378 data_helper_file.write('const char* const %s[%d] = {\n' % 379 (model_name_var_name, len(machine_model_name))) 380 for item in machine_model_name: 381 write_string(item, data_helper_file) 382 data_helper_file.write(',\n') 383 data_helper_file.write('};\n\n') 384 var_name = None 385 if machine_model_name or machine_model_version: 386 var_name = 'kMachineModelInfoForEntry' + str(entry_id) 387 if is_exception: 388 var_name += 'Exception' + str(exception_id) 389 # define machine model info 390 data_helper_file.write( 391 'const GpuControlList::MachineModelInfo %s = {\n' % var_name) 392 if machine_model_name: 393 data_helper_file.write('base::size(%s), // machine model name size\n' % 394 model_name_var_name) 395 data_helper_file.write('%s, // machine model names\n' % 396 model_name_var_name) 397 else: 398 data_helper_file.write('0, // machine model name size\n') 399 data_helper_file.write('nullptr, // machine model names\n') 400 write_version(machine_model_version, 'machine model version', 401 data_helper_file) 402 data_helper_file.write('};\n\n') 403 # reference the machine model info 404 data_file.write('&%s, // machine model info\n' % var_name) 405 else: 406 data_file.write('nullptr, // machine model info\n') 407 408 409def write_os_type(os_type, data_file): 410 assert os_type in _OS_TYPE_MAP 411 data_file.write('GpuControlList::%s, // os_type\n' % _OS_TYPE_MAP[os_type]) 412 413 414def write_multi_gpu_category(multi_gpu_category, data_file): 415 suffix_for_category = { 416 'primary': 'Primary', 417 'secondary': 'Secondary', 418 'active': 'Active', 419 'any': 'Any', 420 '': 'None', 421 } 422 assert multi_gpu_category in suffix_for_category 423 data_file.write( 424 'GpuControlList::kMultiGpuCategory%s, // multi_gpu_category\n' % 425 suffix_for_category[multi_gpu_category]) 426 427 428def write_multi_gpu_style(multi_gpu_style, data_file): 429 suffix_for_style = { 430 'optimus': 'Optimus', 431 'amd_switchable': 'AMDSwitchable', 432 'amd_switchable_discrete': 'AMDSwitchableDiscrete', 433 'amd_switchable_integrated': 'AMDSwitchableIntegrated', 434 '': 'None', 435 } 436 assert multi_gpu_style in suffix_for_style 437 data_file.write( 438 'GpuControlList::kMultiGpuStyle%s, // multi_gpu_style\n' % 439 suffix_for_style[multi_gpu_style]) 440 441 442def write_gl_type(gl_type, data_file): 443 suffix_for_type = { 444 'gl': 'GL', 445 'gles': 'GLES', 446 'angle': 'ANGLE', 447 '': 'None', 448 } 449 assert gl_type in suffix_for_type 450 data_file.write('GpuControlList::kGLType%s, // gl_type\n' % 451 suffix_for_type[gl_type]) 452 453 454def write_supported_or_not(feature_value, feature_name, data_file): 455 if feature_value is None: 456 feature_value = 'dont_care' 457 suffix_for_value = { 458 'supported': 'Supported', 459 'unsupported': 'Unsupported', 460 'dont_care': 'DontCare', 461 } 462 assert feature_value in suffix_for_value 463 data_file.write('GpuControlList::k%s, // %s\n' % 464 (suffix_for_value[feature_value], feature_name)) 465 466 467def write_conditions(entry_id, is_exception, exception_id, entry, 468 unique_symbol_id, data_file, data_helper_file, 469 _data_exception_file): 470 os_type = '' 471 os_version = None 472 vendor_id = 0 473 device_id = None 474 device_revision = None 475 multi_gpu_category = '' 476 multi_gpu_style = '' 477 intel_gpu_series_list = None 478 intel_gpu_generation = None 479 driver_vendor = '' 480 driver_version = None 481 gl_renderer = '' 482 gl_vendor = '' 483 gl_extensions = '' 484 gl_version_string = '' 485 gl_type = '' 486 gl_version = None 487 pixel_shader_version = None 488 in_process_gpu = False 489 gl_reset_notification_strategy = None 490 direct_rendering_version = '' 491 gpu_count = None 492 hardware_overlay = None 493 test_group = 0 494 machine_model_name = None 495 machine_model_version = None 496 exception_count = 0 497 subpixel_font_rendering = None 498 # process the entry 499 for key in entry: 500 if key == 'id': 501 assert not is_exception 502 assert entry['id'] == entry_id 503 continue 504 elif key == 'description': 505 assert not is_exception 506 continue 507 elif key == 'driver_update_url': 508 assert not is_exception 509 continue 510 elif key == 'features': 511 assert not is_exception 512 continue 513 elif key == 'disabled_extensions': 514 assert not is_exception 515 continue 516 elif key == 'disabled_webgl_extensions': 517 assert not is_exception 518 continue 519 elif key == 'comment': 520 continue 521 elif key == 'webkit_bugs': 522 assert not is_exception 523 continue 524 elif key == 'cr_bugs': 525 assert not is_exception 526 continue 527 elif key == 'os': 528 os_info = entry[key] 529 os_type = os_info['type'] 530 if 'version' in os_info: 531 os_version = os_info['version'] 532 elif key == 'vendor_id': 533 vendor_id = int(entry[key], 0) 534 elif key == 'device_id': 535 device_id = entry[key] 536 elif key == 'device_revision': 537 device_revision = entry[key] 538 elif key == 'multi_gpu_category': 539 multi_gpu_category = entry[key] 540 elif key == 'multi_gpu_style': 541 multi_gpu_style = entry[key] 542 elif key == 'intel_gpu_series': 543 intel_gpu_series_list = entry[key] 544 elif key == 'intel_gpu_generation': 545 intel_gpu_generation = entry[key] 546 elif key == 'driver_vendor': 547 driver_vendor = entry[key] 548 elif key == 'driver_version': 549 driver_version = entry[key] 550 elif key == 'gl_vendor': 551 gl_vendor = entry[key] 552 elif key == 'gl_renderer': 553 gl_renderer = entry[key] 554 elif key == 'gl_version_string': 555 gl_version_string = entry[key] 556 elif key == 'gl_type': 557 gl_type = entry[key] 558 elif key == 'gl_version': 559 gl_version = entry[key] 560 elif key == 'gl_extensions': 561 gl_extensions = entry[key] 562 elif key == 'pixel_shader_version': 563 pixel_shader_version = entry[key] 564 elif key == 'in_process_gpu': 565 assert entry[key] 566 in_process_gpu = True 567 elif key == 'gl_reset_notification_strategy': 568 gl_reset_notification_strategy = entry[key] 569 elif key == 'direct_rendering_version': 570 direct_rendering_version = entry[key] 571 elif key == 'gpu_count': 572 gpu_count = entry[key] 573 elif key == 'hardware_overlay': 574 hardware_overlay = entry[key] 575 elif key == 'test_group': 576 assert entry[key] > 0 577 test_group = entry[key] 578 elif key == 'machine_model_name': 579 machine_model_name = entry[key] 580 elif key == 'machine_model_version': 581 machine_model_version = entry[key] 582 elif key == 'subpixel_font_rendering': 583 subpixel_font_rendering = entry[key] 584 elif key == 'exceptions': 585 assert not is_exception 586 assert exception_count == 0 587 else: 588 raise ValueError('unknown key: ' + key + ' in entry ' + str(entry)) 589 # write out the entry 590 write_os_type(os_type, data_file) 591 write_version(os_version, 'os_version', data_file) 592 data_file.write(format(vendor_id, '#04x')) 593 data_file.write(', // vendor_id\n') 594 write_device_list(entry_id, device_id, device_revision, is_exception, 595 exception_id, unique_symbol_id, data_file, 596 data_helper_file) 597 write_multi_gpu_category(multi_gpu_category, data_file) 598 write_multi_gpu_style(multi_gpu_style, data_file) 599 # group driver info 600 if driver_vendor != '' or driver_version != None: 601 if driver_version and driver_version.get('schema') == 'intel_driver': 602 assert os_type == 'win', 'Intel driver schema is only for Windows' 603 is_intel = (format(vendor_id, '#04x') == '0x8086' or 604 intel_gpu_series_list or 605 intel_gpu_generation or 606 'Intel' in driver_vendor) 607 assert is_intel, 'Intel driver schema is only for Intel GPUs' 608 valid_version = check_intel_driver_version(driver_version['value']) 609 if driver_version.has_key('value2'): 610 valid_version = (valid_version and 611 check_intel_driver_version(driver_version['value2'])) 612 assert valid_version, INTEL_DRIVER_VERSION_SCHEMA 613 614 if driver_version and driver_version.get('schema') == 'nvidia_driver': 615 assert os_type == 'win', 'Nvidia driver schema is only for Windows' 616 is_nvidia = (format(vendor_id, '#04x') == '0x10de') 617 assert is_nvidia, 'Nvidia driver schema is only for Nvidia GPUs' 618 valid_version = check_nvidia_driver_version(driver_version['value']) 619 if driver_version.has_key('value2'): 620 valid_version = (valid_version and 621 check_nvidia_driver_version(driver_version['value2'])) 622 assert valid_version, NVIDIA_DRIVER_VERSION_SCHEMA 623 624 write_driver_info(entry_id, is_exception, exception_id, driver_vendor, 625 driver_version, unique_symbol_id, 626 data_file, data_helper_file) 627 else: 628 data_file.write('nullptr, // driver info\n') 629 # group GL strings 630 gl_strings = None 631 if (gl_vendor != '' or gl_renderer != '' or gl_extensions != '' or 632 gl_version_string != ''): 633 gl_strings = [gl_vendor, gl_renderer, gl_extensions, gl_version_string] 634 write_gl_strings(entry_id, is_exception, exception_id, gl_strings, 635 unique_symbol_id, data_file, data_helper_file) 636 # group machine model info 637 write_machine_model_info(entry_id, is_exception, exception_id, 638 machine_model_name, machine_model_version, 639 data_file, data_helper_file) 640 write_intel_gpu_series_list(entry_id, is_exception, exception_id, 641 intel_gpu_series_list, 642 data_file, data_helper_file) 643 write_version(intel_gpu_generation, 'intel_gpu_generation', data_file) 644 # group a bunch of less used conditions 645 if (gl_version != None or pixel_shader_version != None or in_process_gpu or 646 gl_reset_notification_strategy != None or direct_rendering_version != None 647 or gpu_count != None or hardware_overlay != None or test_group != 0 or 648 subpixel_font_rendering != None): 649 write_entry_more_data(entry_id, is_exception, exception_id, gl_type, 650 gl_version, pixel_shader_version, in_process_gpu, 651 gl_reset_notification_strategy, 652 direct_rendering_version, gpu_count, hardware_overlay, 653 test_group, subpixel_font_rendering, 654 data_file, data_helper_file) 655 else: 656 data_file.write('nullptr, // more conditions\n') 657 658 659def write_intel_gpu_series_list(entry_id, is_exception, exception_id, 660 intel_gpu_series_list, 661 data_file, data_helper_file): 662 if intel_gpu_series_list: 663 var_name = 'kIntelGpuSeriesForEntry' + str(entry_id) 664 if is_exception: 665 var_name += 'Exception' + str(exception_id) 666 data_helper_file.write('const IntelGpuSeriesType %s[%d] = {\n' % 667 (var_name, len(intel_gpu_series_list))) 668 intel_gpu_series_map = { 669 'broadwater': 'kBroadwater', 670 'eaglelake': 'kEaglelake', 671 'ironlake': 'kIronlake', 672 'sandybridge': 'kSandybridge', 673 'baytrail': 'kBaytrail', 674 'ivybridge': 'kIvybridge', 675 'haswell': 'kHaswell', 676 'cherrytrail': 'kCherrytrail', 677 'broadwell': 'kBroadwell', 678 'apollolake': 'kApollolake', 679 'skylake': 'kSkylake', 680 'geminilake': 'kGeminilake', 681 'kabylake': 'kKabylake', 682 'coffeelake': 'kCoffeelake', 683 'whiskeylake': 'kWhiskeylake', 684 'cometlake': 'kCometlake', 685 'cannonlake': 'kCannonlake', 686 'icelake': 'kIcelake', 687 'elkhartlake': 'kElkhartlake', 688 'jasperlake': 'kJasperlake', 689 'tigerlake': 'kTigerlake' 690 } 691 for series in intel_gpu_series_list: 692 assert series in intel_gpu_series_map 693 data_helper_file.write('IntelGpuSeriesType::%s,\n' % 694 intel_gpu_series_map[series]) 695 data_helper_file.write('};\n\n') 696 697 data_file.write('base::size(%s), // intel_gpu_series size\n' % var_name) 698 data_file.write('%s, // intel_gpu_series\n' % var_name) 699 else: 700 data_file.write('0, // intel_gpu_series size\n') 701 data_file.write('nullptr, // intel_gpu_series\n') 702 703 704def write_entry_more_data(entry_id, is_exception, exception_id, gl_type, 705 gl_version, pixel_shader_version, in_process_gpu, 706 gl_reset_notification_strategy, 707 direct_rendering_version, gpu_count, hardware_overlay, 708 test_group, subpixel_font_rendering, data_file, 709 data_helper_file): 710 # write more data 711 712 # Generate a unique name for jumbo build which concatenates multiple 713 # translation units into one to speed compilation. 714 basename = os.path.basename(data_helper_file.name) 715 # & 0xffffffff converts to unsigned to keep consistent across Python versions 716 # and platforms as per https://docs.python.org/3/library/zlib.html 717 suffix = '_%s' % (zlib.crc32(basename.encode()) & 0xffffffff) 718 var_name = 'kMoreForEntry' + str(entry_id) + suffix 719 if is_exception: 720 var_name += 'Exception' + str(exception_id) 721 data_helper_file.write('const GpuControlList::More %s = {\n' % var_name) 722 write_gl_type(gl_type, data_helper_file) 723 write_version(gl_version, 'gl_version', data_helper_file) 724 write_version(pixel_shader_version, 'pixel_shader_version', data_helper_file) 725 write_boolean_value(in_process_gpu, 'in_process_gpu', data_helper_file) 726 if not gl_reset_notification_strategy: 727 gl_reset_notification_strategy = '0' 728 data_helper_file.write('%s, // gl_reset_notification_strategy\n' % 729 gl_reset_notification_strategy) 730 write_version(direct_rendering_version, 'direct_rendering_version', 731 data_helper_file) 732 write_version(gpu_count, 'gpu_count', data_helper_file) 733 write_supported_or_not(hardware_overlay, 'hardware_overlay', data_helper_file) 734 write_integer_value(test_group, 'test_group', data_helper_file) 735 write_supported_or_not(subpixel_font_rendering, 'subpixel_font_rendering', 736 data_helper_file) 737 data_helper_file.write('};\n\n') 738 # reference more data in entry 739 data_file.write('&%s, // more data\n' % var_name) 740 741 742def write_entry(entry, total_feature_set, feature_name_prefix, 743 unique_symbol_id, data_file, data_helper_file, 744 data_exception_file): 745 data_file.write('{\n') 746 # ID 747 entry_id = entry['id'] 748 data_file.write('%d, // id\n' % entry_id) 749 description = entry['description'] 750 if 'driver_update_url' in entry: 751 description += (' Please update your graphics driver via this link: ' + 752 entry['driver_update_url']) 753 data_file.write('"%s",\n' % description); 754 # Features 755 if 'features' in entry: 756 var_name = 'kFeatureListFor%sEntry%d' % (unique_symbol_id, entry_id) 757 features = entry['features'] 758 feature_set = get_feature_set(features, total_feature_set) 759 data_file.write('base::size(%s), // features size\n' % var_name) 760 data_file.write('%s, // features\n' % var_name) 761 write_features(feature_set, feature_name_prefix, var_name, data_helper_file) 762 else: 763 data_file.write('0, // feature size\n') 764 data_file.write('nullptr, // features\n') 765 # Disabled extensions 766 write_disabled_extension_list('DisabledExtensions', entry_id, 767 entry.get('disabled_extensions', None), 768 data_file, data_helper_file) 769 # Disabled WebGL extensions 770 write_disabled_extension_list('DisabledWebGLExtensions', entry_id, 771 entry.get('disabled_webgl_extensions', None), 772 data_file, data_helper_file) 773 # webkit_bugs are skipped because there is only one entry that has it. 774 # cr_bugs 775 cr_bugs = None 776 if 'cr_bugs' in entry: 777 cr_bugs = entry['cr_bugs'] 778 write_number_list(entry_id, 'uint32_t', 'CrBugs', cr_bugs, False, -1, 779 unique_symbol_id, data_file, data_helper_file) 780 # Conditions 781 data_file.write('{\n') 782 write_conditions(entry_id, False, -1, entry, unique_symbol_id, 783 data_file, data_helper_file, data_exception_file) 784 data_file.write('},\n') 785 # Exceptions 786 if 'exceptions' in entry: 787 exceptions = entry['exceptions'] 788 exception_count = len(exceptions) 789 exception_var = 'kExceptionsForEntry' + str(entry_id) 790 data_exception_file.write('const GpuControlList::Conditions %s[%d] = {\n' % 791 (exception_var, exception_count)) 792 for index in range(exception_count): 793 exception = exceptions[index] 794 if 'device_id' in exception and 'vendor_id' not in exception: 795 assert 'vendor_id' in entry 796 exception['vendor_id'] = entry['vendor_id'] 797 data_exception_file.write('{\n') 798 write_conditions(entry_id, True, index, exception, unique_symbol_id, 799 data_exception_file, data_helper_file, None) 800 data_exception_file.write('},\n') 801 data_exception_file.write('};\n\n') 802 data_file.write('base::size(%s), // exceptions count\n' % exception_var) 803 data_file.write('%s, // exceptions\n' % exception_var) 804 else: 805 data_file.write('0, // exceptions count\n') 806 data_file.write('nullptr, // exceptions\n') 807 # END 808 data_file.write('},\n') 809 810 811def format_files(generated_files): 812 formatter = "clang-format" 813 if platform.system() == "Windows": 814 formatter += ".bat" 815 for filename in generated_files: 816 call([formatter, "-i", "-style=chromium", filename]) 817 818 819def write_header_file_guard(out_file, filename, path, begin): 820 token = (path.upper().replace('/', '_') + '_' + 821 filename.upper().replace('.', '_') + '_') 822 if begin: 823 out_file.write('#ifndef %s\n#define %s\n\n' % (token, token)) 824 else: 825 out_file.write('\n#endif // %s\n' % token) 826 827 828def process_json_file(json_filepath, list_tag, 829 feature_header_filename, total_features, feature_tag, 830 output_header_filepath, output_data_filepath, 831 output_helper_filepath, output_exception_filepath, path, 832 export_tag, git_format, os_filter, unique_symbol_id): 833 output_header_filename = os.path.basename(output_header_filepath) 834 output_helper_filename = os.path.basename(output_helper_filepath) 835 output_exception_filename = os.path.basename(output_exception_filepath) 836 json_file = open(json_filepath, 'rb') 837 json_data = json.load(json_file) 838 json_file.close() 839 data_file = open(output_data_filepath, 'w') 840 data_file.write(_LICENSE) 841 data_file.write(_DO_NOT_EDIT_WARNING) 842 data_file.write('#include "%s/%s"\n\n' % (path, output_header_filename)) 843 data_file.write('#include "%s/%s"\n' % (path, output_helper_filename)) 844 data_file.write('#include "%s/%s"\n\n' % (path, output_exception_filename)) 845 data_helper_file = open(output_helper_filepath, 'w') 846 data_helper_file.write(_LICENSE) 847 data_helper_file.write(_DO_NOT_EDIT_WARNING) 848 write_header_file_guard(data_helper_file, output_helper_filename, path, True) 849 data_helper_file.write('#include "gpu/config/%s"\n\n' % 850 feature_header_filename) 851 data_helper_file.write('namespace gpu {\n') 852 data_exception_file = open(output_exception_filepath, 'w') 853 data_exception_file.write(_LICENSE) 854 data_exception_file.write(_DO_NOT_EDIT_WARNING) 855 write_header_file_guard(data_exception_file, output_exception_filename, path, 856 True) 857 data_exception_file.write('namespace gpu {\n') 858 data_file.write('namespace gpu {\n\n') 859 data_file.write('const GpuControlList::Entry k%sEntries[] = {\n' % list_tag) 860 ids = [] 861 entry_count = 0 862 for index in range(len(json_data['entries'])): 863 entry = json_data['entries'][index] 864 entry_id = entry['id'] 865 assert entry_id not in ids 866 ids.append(entry_id) 867 if 'os' in entry: 868 os_type = entry['os']['type'] 869 # Check for typos in the .json data 870 if os_type not in _OS_TYPE_MAP: 871 raise Exception('Unknown OS type "%s" for entry %d' % 872 (os_type, entry_id)) 873 if os_filter != None and os_type != os_filter: 874 continue 875 entry_count += 1 876 write_entry(entry, total_features, feature_tag, unique_symbol_id, 877 data_file, data_helper_file, data_exception_file) 878 data_file.write('};\n') 879 data_file.write('const size_t k%sEntryCount = %d;\n' % 880 (list_tag, entry_count)) 881 data_file.write('} // namespace gpu\n') 882 data_file.close() 883 data_helper_file.write('} // namespace gpu\n') 884 write_header_file_guard(data_helper_file, output_helper_filename, path, False) 885 data_helper_file.close() 886 data_exception_file.write('} // namespace gpu\n') 887 write_header_file_guard(data_exception_file, output_exception_filename, path, 888 False) 889 data_exception_file.close() 890 data_header_file = open(output_header_filepath, 'w') 891 data_header_file.write(_LICENSE) 892 data_header_file.write(_DO_NOT_EDIT_WARNING) 893 write_header_file_guard(data_header_file, output_header_filename, path, True) 894 if export_tag == 'CONTENT_EXPORT ': 895 data_header_file.write('#include "content/common/content_export.h"\n') 896 data_header_file.write('#include "gpu/config/gpu_control_list.h"\n\n') 897 data_header_file.write('\n') 898 data_header_file.write('namespace gpu {\n') 899 data_header_file.write('%sextern const size_t k%sEntryCount;\n' % 900 (export_tag, list_tag)) 901 data_header_file.write( 902 '%sextern const GpuControlList::Entry k%sEntries[];\n' % 903 (export_tag, list_tag)) 904 data_header_file.write('} // namespace gpu\n') 905 write_header_file_guard(data_header_file, output_header_filename, path, False) 906 data_header_file.close() 907 if git_format: 908 format_files([output_header_filepath, output_data_filepath, 909 output_helper_filepath, output_exception_filepath]) 910 911 912def process_software_rendering_list(script_dir, output_dir, os_filter): 913 total_features = load_software_rendering_list_features( 914 os.path.join(script_dir, 'gpu_feature_type.h')) 915 process_json_file( 916 os.path.join(script_dir, 'software_rendering_list.json'), 917 'SoftwareRenderingList', 918 'gpu_feature_type.h', 919 total_features, 920 'GPU_FEATURE_TYPE_', 921 os.path.join(output_dir, 'software_rendering_list_autogen.h'), 922 os.path.join(output_dir, 'software_rendering_list_autogen.cc'), 923 os.path.join(output_dir, 924 'software_rendering_list_arrays_and_structs_autogen.h'), 925 os.path.join(output_dir, 'software_rendering_list_exceptions_autogen.h'), 926 'gpu/config', 927 'GPU_EXPORT ', 928 False, 929 os_filter, 930 'Software') 931 932 933def process_gpu_driver_bug_list(script_dir, output_dir, os_filter): 934 total_features = load_gpu_driver_bug_workarounds( 935 os.path.join(output_dir, 'gpu_driver_bug_workaround_autogen.h')) 936 process_json_file( 937 os.path.join(script_dir, 'gpu_driver_bug_list.json'), 938 'GpuDriverBugList', 939 'gpu_driver_bug_workaround_type.h', 940 total_features, 941 '', 942 os.path.join(output_dir, 'gpu_driver_bug_list_autogen.h'), 943 os.path.join(output_dir, 'gpu_driver_bug_list_autogen.cc'), 944 os.path.join(output_dir, 945 'gpu_driver_bug_list_arrays_and_structs_autogen.h'), 946 os.path.join(output_dir, 'gpu_driver_bug_list_exceptions_autogen.h'), 947 'gpu/config', 948 'GPU_EXPORT ', 949 False, 950 os_filter, 951 'Workarounds') 952 953 954def process_gpu_control_list_testing(script_dir, output_dir): 955 total_features = ['test_feature_0', 'test_feature_1', 'test_feature_2'] 956 process_json_file( 957 os.path.join(script_dir, 'gpu_control_list_testing.json'), 958 'GpuControlListTesting', 959 'gpu_control_list_testing_data.h', 960 total_features, 961 '', 962 os.path.join(output_dir, 'gpu_control_list_testing_autogen.h'), 963 os.path.join(output_dir, 'gpu_control_list_testing_autogen.cc'), 964 os.path.join(output_dir, 965 'gpu_control_list_testing_arrays_and_structs_autogen.h'), 966 os.path.join(output_dir, 'gpu_control_list_testing_exceptions_autogen.h'), 967 'gpu/config', 968 '', 969 True, 970 None, 971 'GpuControlTesting') 972 973 974def process_gpu_data_manager_testing(script_dir, output_dir): 975 total_features = load_software_rendering_list_features( 976 os.path.join(script_dir, 'gpu_feature_type.h')) 977 process_json_file( 978 os.path.join(output_dir, 'gpu_data_manager_testing.json'), 979 'GpuDataManagerTesting', 980 'gpu_feature_type.h', 981 total_features, 982 'GPU_FEATURE_TYPE_', 983 os.path.join(output_dir, 'gpu_data_manager_testing_autogen.h'), 984 os.path.join(output_dir, 'gpu_data_manager_testing_autogen.cc'), 985 os.path.join(output_dir, 986 'gpu_data_manager_testing_arrays_and_structs_autogen.h'), 987 os.path.join(output_dir, 'gpu_data_manager_testing_exceptions_autogen.h'), 988 'content/browser/gpu', 989 '', 990 True, 991 None, 992 'GpuManagerTesting') 993 994 995def write_test_entry_enums(input_json_filepath, output_entry_enums_filepath, 996 path, list_tag): 997 json_file = open(input_json_filepath, 'rb') 998 json_data = json.load(json_file) 999 json_file.close() 1000 1001 output_entry_enums_filename = os.path.basename(output_entry_enums_filepath) 1002 enum_file = open(output_entry_enums_filepath, 'w') 1003 enum_file.write(_LICENSE) 1004 enum_file.write(_DO_NOT_EDIT_WARNING) 1005 write_header_file_guard(enum_file, output_entry_enums_filename, path, True) 1006 enum_file.write('namespace gpu {\n') 1007 enum_file.write('enum %sEntryEnum {\n' % list_tag) 1008 entry_count = len(json_data['entries']) 1009 for index in range(entry_count): 1010 entry = json_data['entries'][index] 1011 entry_id = entry['id'] 1012 description = entry['description'] 1013 assert(index + 1 == int(entry_id)) 1014 description = 'k' + description 1015 description = description.replace('.', '_') 1016 enum_file.write(' %s = %d,\n' % (description, index)) 1017 enum_file.write('};\n') 1018 enum_file.write('} // namespace gpu\n') 1019 write_header_file_guard(enum_file, output_entry_enums_filename, path, False) 1020 enum_file.close() 1021 format_files([output_entry_enums_filepath]) 1022 1023 1024def main(argv): 1025 parser = OptionParser() 1026 parser.add_option("--output-dir", 1027 help="output directory for SoftwareRenderingList and " 1028 "GpuDriverBugList data files. " 1029 "If unspecified, these files are not generated.") 1030 parser.add_option("--skip-testing-data", action="store_false", 1031 dest="generate_testing_data", default=True, 1032 help="skip testing data generation.") 1033 parser.add_option("--os-filter", 1034 help="only output entries applied to the specified os.") 1035 (options, _) = parser.parse_args(args=argv) 1036 1037 script_dir = os.path.dirname(os.path.realpath(__file__)) 1038 1039 if options.output_dir != None: 1040 process_software_rendering_list( 1041 script_dir, options.output_dir, options.os_filter) 1042 process_gpu_driver_bug_list( 1043 script_dir, options.output_dir, options.os_filter) 1044 1045 if options.generate_testing_data: 1046 # Testing data files are generated by calling the script manually. 1047 process_gpu_control_list_testing(script_dir, script_dir) 1048 write_test_entry_enums( 1049 os.path.join(script_dir, 'gpu_control_list_testing.json'), 1050 os.path.join(script_dir, 1051 'gpu_control_list_testing_entry_enums_autogen.h'), 1052 'gpu/config', 1053 'GpuControlListTesting') 1054 chrome_root_dir = os.path.abspath(os.path.join(script_dir, '../../')) 1055 gpu_data_manager_dir = os.path.join(chrome_root_dir, 'content/browser/gpu') 1056 process_gpu_data_manager_testing(script_dir, gpu_data_manager_dir) 1057 write_test_entry_enums( 1058 os.path.join(gpu_data_manager_dir, 'gpu_data_manager_testing.json'), 1059 os.path.join(gpu_data_manager_dir, 1060 'gpu_data_manager_testing_entry_enums_autogen.h'), 1061 'content/browser/gpu', 1062 'GpuDataManagerTesting') 1063 1064 1065if __name__ == '__main__': 1066 sys.exit(main(sys.argv[1:])) 1067