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 blacklist 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 59 60def check_intel_driver_version(version): 61 ver_list = version.split('.') 62 if len(ver_list) != 4: 63 return False 64 for ver in ver_list: 65 if not ver.isdigit(): 66 return False 67 if int(ver_list[2]) < 100 and ver_list[3] == '0': 68 return False 69 return True 70 71 72def load_software_rendering_list_features(feature_type_filename): 73 header_file = open(feature_type_filename, 'r') 74 start = False 75 features = [] 76 for line in header_file: 77 if line.startswith('enum GpuFeatureType {'): 78 assert not start 79 start = True 80 continue 81 if not start: 82 continue 83 line = line.strip() 84 line = line.split(' ', 1)[0] 85 line = line.split(',', 1)[0] 86 if line.startswith('NUMBER_OF_GPU_FEATURE_TYPES'): 87 assert start 88 start = False 89 break 90 elif line.startswith('GPU_FEATURE_TYPE_'): 91 name = line[len('GPU_FEATURE_TYPE_'):] 92 features.append(name.lower()) 93 else: 94 assert False 95 assert not start 96 assert len(features) > 0 97 header_file.close() 98 return features 99 100 101def load_gpu_driver_bug_workarounds(workaround_type_filename): 102 header_file = open(workaround_type_filename, 'r') 103 start = False 104 workaround = None 105 workarounds = [] 106 for line in header_file: 107 if line.startswith('#define GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP)'): 108 assert not start 109 start = True 110 continue 111 if not start: 112 continue 113 line = line.strip() 114 if line.startswith('GPU_OP('): 115 assert not workaround 116 workaround = line[len('GPU_OP('):] 117 workaround = workaround.split(',', 1)[0].lower() 118 continue 119 if workaround: 120 line = line.split(')', 1)[0] 121 assert line == workaround 122 workarounds.append(line) 123 workaround = None 124 continue 125 start = False 126 break 127 assert not start 128 assert len(workarounds) > 0 129 header_file.close() 130 return workarounds 131 132 133def get_feature_set(features, total_feature_set): 134 assert len(features) > 0 135 feature_set = set([]) 136 for feature in features: 137 if feature == 'all': 138 feature_set = set(total_feature_set) 139 elif isinstance(feature, dict): 140 for key in feature: 141 if key == 'exceptions': 142 for exception in feature['exceptions']: 143 assert exception in feature_set 144 feature_set.remove(exception) 145 else: 146 raise KeyError('only exceptions are allowed') 147 else: 148 assert feature in total_feature_set 149 feature_set.add(feature) 150 return feature_set 151 152 153def write_features(feature_set, feature_name_prefix, var_name, 154 data_helper_file): 155 data_helper_file.write('const int %s[%d] = {\n' % 156 (var_name, len(feature_set))) 157 for feature in feature_set: 158 data_helper_file.write(feature_name_prefix + feature.upper()) 159 data_helper_file.write(',\n') 160 data_helper_file.write('};\n\n') 161 162 163def write_disabled_extension_list(entry_kind, entry_id, data, data_file, 164 data_helper_file): 165 if data: 166 var_name = 'k%sForEntry%d' % (entry_kind, entry_id) 167 # define the list 168 data_helper_file.write( 169 'const char* const %s[%d] = {\n' % (var_name, len(data))) 170 for item in data: 171 write_string(item, data_helper_file) 172 data_helper_file.write(',\n') 173 data_helper_file.write('};\n\n') 174 # use the list 175 data_file.write('base::size(%s), // %s size\n' % (var_name, entry_kind)) 176 data_file.write('%s, // %s\n' % (var_name, entry_kind)) 177 else: 178 data_file.write('0, // %s size\n' % entry_kind) 179 data_file.write('nullptr, // %s\n' % entry_kind) 180 181 182def write_gl_strings(entry_id, is_exception, exception_id, data, 183 unique_symbol_id, data_file, data_helper_file): 184 if data: 185 var_name = 'kGLStringsFor%sEntry%d' % (unique_symbol_id, entry_id) 186 if is_exception: 187 var_name += 'Exception' + str(exception_id) 188 # define the GL strings 189 data_helper_file.write('const GpuControlList::GLStrings %s = {\n' % 190 var_name) 191 for item in data: 192 write_string(item, data_helper_file) 193 data_helper_file.write(',\n') 194 data_helper_file.write('};\n\n') 195 # reference the GL strings 196 data_file.write('&%s, // GL strings\n' % var_name) 197 else: 198 data_file.write('nullptr, // GL strings\n') 199 200 201def write_version(version_info, name_tag, data_file): 202 op = '' 203 style = '' 204 version1 = '' 205 version2 = '' 206 if version_info: 207 op = version_info['op'] 208 if 'style' in version_info: 209 style = version_info['style'] 210 version1 = version_info['value'] 211 if 'value2' in version_info: 212 version2 = version_info['value2'] 213 data_file.write('{') 214 op_map = { 215 '=': 'kEQ', 216 '<': 'kLT', 217 '<=': 'kLE', 218 '>': 'kGT', 219 '>=': 'kGE', 220 'any': 'kAny', 221 'between': 'kBetween', 222 '': 'kUnknown', 223 } 224 assert op in op_map 225 data_file.write('GpuControlList::%s, ' % op_map[op]) 226 style_map = { 227 'lexical': 'Lexical', 228 'numerical': 'Numerical', 229 '': 'Numerical', 230 } 231 assert style in style_map 232 data_file.write('GpuControlList::kVersionStyle%s, ' % style_map[style]) 233 write_string(version1, data_file) 234 data_file.write(', ') 235 write_string(version2, data_file) 236 data_file.write('}, // %s\n' % name_tag) 237 238 239def write_driver_info(entry_id, is_exception, exception_id, driver_vendor, 240 driver_version, unique_symbol_id, 241 data_file, data_helper_file): 242 var_name = 'kDriverInfoFor%sEntry%d' % (unique_symbol_id, entry_id) 243 if is_exception: 244 var_name += 'Exception' + str(exception_id) 245 # define the GL strings 246 data_helper_file.write('const GpuControlList::DriverInfo %s = {\n' % 247 var_name) 248 write_string_value(driver_vendor, 'driver_vendor', data_helper_file) 249 write_version(driver_version, 'driver_version', data_helper_file) 250 data_helper_file.write('};\n\n') 251 # reference the GL strings 252 data_file.write('&%s, // driver info\n' % var_name) 253 254 255def write_number_list(entry_id, data_type, name_tag, data, is_exception, 256 exception_id, unique_symbol_id, data_file, 257 data_helper_file): 258 if data: 259 var_name = 'k%sFor%sEntry%d' % (name_tag, unique_symbol_id, entry_id) 260 if is_exception: 261 var_name += 'Exception' + str(exception_id) 262 # define the list 263 data_helper_file.write('const %s %s[%d] = {\n' % 264 (data_type, var_name, len(data))) 265 for item in data: 266 data_helper_file.write(str(item)) 267 data_helper_file.write(',\n') 268 data_helper_file.write('};\n\n') 269 # reference the list 270 data_file.write('base::size(%s), // %s size\n' % (var_name, name_tag)) 271 data_file.write('%s, // %s\n' % (var_name, name_tag)) 272 else: 273 data_file.write('0, // %s size\n' % name_tag) 274 data_file.write('nullptr, // %s\n' % name_tag) 275 276 277def write_string(string, data_file): 278 if string == '': 279 data_file.write('nullptr') 280 else: 281 data_file.write('"%s"' % string.replace('\\', '\\\\')) 282 283 284def write_string_value(string, name_tag, data_file): 285 write_string(string, data_file) 286 data_file.write(', // %s\n' % name_tag) 287 288 289def write_boolean_value(value, name_tag, data_file): 290 data_file.write('%s, // %s\n' % (str(value).lower(), name_tag)) 291 292def write_integer_value(value, name_tag, data_file): 293 data_file.write('%s, // %s\n' % (str(value), name_tag)) 294 295def write_machine_model_info(entry_id, is_exception, exception_id, 296 machine_model_name, machine_model_version, 297 data_file, data_helper_file): 298 model_name_var_name = None 299 if machine_model_name: 300 assert isinstance(machine_model_name, list) 301 model_name_var_name = 'kMachineModelNameForEntry' + str(entry_id) 302 if is_exception: 303 model_name_var_name += 'Exception' + str(exception_id) 304 data_helper_file.write('const char* const %s[%d] = {\n' % 305 (model_name_var_name, len(machine_model_name))) 306 for item in machine_model_name: 307 write_string(item, data_helper_file) 308 data_helper_file.write(',\n') 309 data_helper_file.write('};\n\n') 310 var_name = None 311 if machine_model_name or machine_model_version: 312 var_name = 'kMachineModelInfoForEntry' + str(entry_id) 313 if is_exception: 314 var_name += 'Exception' + str(exception_id) 315 # define machine model info 316 data_helper_file.write( 317 'const GpuControlList::MachineModelInfo %s = {\n' % var_name) 318 if machine_model_name: 319 data_helper_file.write('base::size(%s), // machine model name size\n' % 320 model_name_var_name) 321 data_helper_file.write('%s, // machine model names\n' % 322 model_name_var_name) 323 else: 324 data_helper_file.write('0, // machine model name size\n') 325 data_helper_file.write('nullptr, // machine model names\n') 326 write_version(machine_model_version, 'machine model version', 327 data_helper_file) 328 data_helper_file.write('};\n\n') 329 # reference the machine model info 330 data_file.write('&%s, // machine model info\n' % var_name) 331 else: 332 data_file.write('nullptr, // machine model info\n') 333 334 335def write_os_type(os_type, data_file): 336 assert os_type in _OS_TYPE_MAP 337 data_file.write('GpuControlList::%s, // os_type\n' % _OS_TYPE_MAP[os_type]) 338 339 340def write_multi_gpu_category(multi_gpu_category, data_file): 341 map = { 342 'primary': 'Primary', 343 'secondary': 'Secondary', 344 'active': 'Active', 345 'any': 'Any', 346 '': 'None', 347 } 348 assert multi_gpu_category in map 349 data_file.write( 350 'GpuControlList::kMultiGpuCategory%s, // multi_gpu_category\n' % 351 map[multi_gpu_category]) 352 353 354def write_multi_gpu_style(multi_gpu_style, data_file): 355 map = { 356 'optimus': 'Optimus', 357 'amd_switchable': 'AMDSwitchable', 358 'amd_switchable_discrete': 'AMDSwitchableDiscrete', 359 'amd_switchable_integrated': 'AMDSwitchableIntegrated', 360 '': 'None', 361 } 362 assert multi_gpu_style in map 363 data_file.write( 364 'GpuControlList::kMultiGpuStyle%s, // multi_gpu_style\n' % 365 map[multi_gpu_style]) 366 367 368def write_gl_type(gl_type, data_file): 369 map = { 370 'gl': 'GL', 371 'gles': 'GLES', 372 'angle': 'ANGLE', 373 '': 'None', 374 } 375 assert gl_type in map 376 data_file.write('GpuControlList::kGLType%s, // gl_type\n' % map[gl_type]) 377 378 379def write_supported_or_not(feature_value, feature_name, data_file): 380 if feature_value is None: 381 feature_value = 'dont_care' 382 map = { 383 'supported': 'Supported', 384 'unsupported': 'Unsupported', 385 'dont_care': 'DontCare', 386 } 387 assert feature_value in map 388 data_file.write('GpuControlList::k%s, // %s\n' % 389 (map[feature_value], feature_name)) 390 391 392def write_conditions(entry_id, is_exception, exception_id, entry, 393 unique_symbol_id, data_file, data_helper_file, 394 _data_exception_file): 395 os_type = '' 396 os_version = None 397 vendor_id = 0 398 device_id = None 399 multi_gpu_category = '' 400 multi_gpu_style = '' 401 intel_gpu_series_list = None 402 intel_gpu_generation = None 403 driver_vendor = '' 404 driver_version = None 405 gl_renderer = '' 406 gl_vendor = '' 407 gl_extensions = '' 408 gl_version_string = '' 409 gl_type = '' 410 gl_version = None 411 pixel_shader_version = None 412 in_process_gpu = False 413 gl_reset_notification_strategy = None 414 direct_rendering_version = '' 415 gpu_count = None 416 hardware_overlay = None 417 test_group = 0 418 machine_model_name = None 419 machine_model_version = None 420 exception_count = 0 421 subpixel_font_rendering = None 422 # process the entry 423 for key in entry: 424 if key == 'id': 425 assert not is_exception 426 assert entry['id'] == entry_id 427 continue 428 elif key == 'description': 429 assert not is_exception 430 continue 431 elif key == 'features': 432 assert not is_exception 433 continue 434 elif key == 'disabled_extensions': 435 assert not is_exception 436 continue 437 elif key == 'disabled_webgl_extensions': 438 assert not is_exception 439 continue 440 elif key == 'comment': 441 continue 442 elif key == 'webkit_bugs': 443 assert not is_exception 444 continue 445 elif key == 'cr_bugs': 446 assert not is_exception 447 continue 448 elif key == 'os': 449 os_info = entry[key] 450 os_type = os_info['type'] 451 if 'version' in os_info: 452 os_version = os_info['version'] 453 elif key == 'vendor_id': 454 vendor_id = int(entry[key], 0) 455 elif key == 'device_id': 456 device_id = entry[key] 457 elif key == 'multi_gpu_category': 458 multi_gpu_category = entry[key] 459 elif key == 'multi_gpu_style': 460 multi_gpu_style = entry[key] 461 elif key == 'intel_gpu_series': 462 intel_gpu_series_list = entry[key] 463 elif key == 'intel_gpu_generation': 464 intel_gpu_generation = entry[key] 465 elif key == 'driver_vendor': 466 driver_vendor = entry[key] 467 elif key == 'driver_version': 468 driver_version = entry[key] 469 elif key == 'gl_vendor': 470 gl_vendor = entry[key] 471 elif key == 'gl_renderer': 472 gl_renderer = entry[key] 473 elif key == 'gl_version_string': 474 gl_version_string = entry[key] 475 elif key == 'gl_type': 476 gl_type = entry[key] 477 elif key == 'gl_version': 478 gl_version = entry[key] 479 elif key == 'gl_extensions': 480 gl_extensions = entry[key] 481 elif key == 'pixel_shader_version': 482 pixel_shader_version = entry[key] 483 elif key == 'in_process_gpu': 484 assert entry[key] 485 in_process_gpu = True 486 elif key == 'gl_reset_notification_strategy': 487 gl_reset_notification_strategy = entry[key] 488 elif key == 'direct_rendering_version': 489 direct_rendering_version = entry[key] 490 elif key == 'gpu_count': 491 gpu_count = entry[key] 492 elif key == 'hardware_overlay': 493 hardware_overlay = entry[key] 494 elif key == 'test_group': 495 assert entry[key] > 0 496 test_group = entry[key] 497 elif key == 'machine_model_name': 498 machine_model_name = entry[key] 499 elif key == 'machine_model_version': 500 machine_model_version = entry[key] 501 elif key == 'subpixel_font_rendering': 502 subpixel_font_rendering = entry[key] 503 elif key == 'exceptions': 504 assert not is_exception 505 assert exception_count == 0 506 else: 507 raise ValueError('unknown key: ' + key + ' in entry ' + str(entry)) 508 # write out the entry 509 write_os_type(os_type, data_file) 510 write_version(os_version, 'os_version', data_file) 511 data_file.write(format(vendor_id, '#04x')) 512 data_file.write(', // vendor_id\n') 513 write_number_list(entry_id, 'uint32_t', 'DeviceIDs', device_id, is_exception, 514 exception_id, unique_symbol_id, data_file, 515 data_helper_file) 516 write_multi_gpu_category(multi_gpu_category, data_file) 517 write_multi_gpu_style(multi_gpu_style, data_file) 518 # group driver info 519 if driver_vendor != '' or driver_version != None: 520 if driver_version and os_type == 'win': 521 if (format(vendor_id, '#04x') == '0x8086' or intel_gpu_series_list 522 or intel_gpu_generation or 'Intel' in driver_vendor): 523 if not check_intel_driver_version(driver_version['value']): 524 assert False, INTEL_DRIVER_VERSION_SCHEMA 525 if 'value2' in driver_version: 526 if not check_intel_driver_version(driver_version['value2']): 527 assert False, INTEL_DRIVER_VERSION_SCHEMA 528 529 write_driver_info(entry_id, is_exception, exception_id, driver_vendor, 530 driver_version, unique_symbol_id, 531 data_file, data_helper_file) 532 else: 533 data_file.write('nullptr, // driver info\n') 534 # group GL strings 535 gl_strings = None 536 if (gl_vendor != '' or gl_renderer != '' or gl_extensions != '' or 537 gl_version_string != ''): 538 gl_strings = [gl_vendor, gl_renderer, gl_extensions, gl_version_string] 539 write_gl_strings(entry_id, is_exception, exception_id, gl_strings, 540 unique_symbol_id, data_file, data_helper_file) 541 # group machine model info 542 write_machine_model_info(entry_id, is_exception, exception_id, 543 machine_model_name, machine_model_version, 544 data_file, data_helper_file) 545 write_intel_gpu_series_list(entry_id, is_exception, exception_id, 546 intel_gpu_series_list, 547 data_file, data_helper_file) 548 write_version(intel_gpu_generation, 'intel_gpu_generation', data_file) 549 # group a bunch of less used conditions 550 if (gl_version != None or pixel_shader_version != None or in_process_gpu or 551 gl_reset_notification_strategy != None or direct_rendering_version != None 552 or gpu_count != None or hardware_overlay != None or test_group != 0 or 553 subpixel_font_rendering != None): 554 write_entry_more_data(entry_id, is_exception, exception_id, gl_type, 555 gl_version, pixel_shader_version, in_process_gpu, 556 gl_reset_notification_strategy, 557 direct_rendering_version, gpu_count, hardware_overlay, 558 test_group, subpixel_font_rendering, 559 data_file, data_helper_file) 560 else: 561 data_file.write('nullptr, // more conditions\n') 562 563 564def write_intel_gpu_series_list(entry_id, is_exception, exception_id, 565 intel_gpu_series_list, 566 data_file, data_helper_file): 567 if intel_gpu_series_list: 568 var_name = 'kIntelGpuSeriesForEntry' + str(entry_id) 569 if is_exception: 570 var_name += 'Exception' + str(exception_id) 571 data_helper_file.write('const IntelGpuSeriesType %s[%d] = {\n' % 572 (var_name, len(intel_gpu_series_list))) 573 intel_gpu_series_map = { 574 'sandybridge': 'kSandybridge', 575 'baytrail': 'kBaytrail', 576 'ivybridge': 'kIvybridge', 577 'haswell': 'kHaswell', 578 'cherrytrail': 'kCherrytrail', 579 'broadwell': 'kBroadwell', 580 'apollolake': 'kApollolake', 581 'skylake': 'kSkylake', 582 'geminilake': 'kGeminilake', 583 'kabylake': 'kKabylake', 584 'coffeelake': 'kCoffeelake', 585 'whiskeylake': 'kWhiskeylake', 586 'cometlake': 'kCometlake', 587 'cannonlake': 'kCannonlake', 588 'icelake': 'kIcelake' 589 } 590 for series in intel_gpu_series_list: 591 assert series in intel_gpu_series_map 592 data_helper_file.write('IntelGpuSeriesType::%s,\n' % 593 intel_gpu_series_map[series]) 594 data_helper_file.write('};\n\n') 595 596 data_file.write('base::size(%s), // intel_gpu_series size\n' % var_name) 597 data_file.write('%s, // intel_gpu_series\n' % var_name) 598 else: 599 data_file.write('0, // intel_gpu_series size\n') 600 data_file.write('nullptr, // intel_gpu_series\n') 601 602 603def write_entry_more_data(entry_id, is_exception, exception_id, gl_type, 604 gl_version, pixel_shader_version, in_process_gpu, 605 gl_reset_notification_strategy, 606 direct_rendering_version, gpu_count, hardware_overlay, 607 test_group, subpixel_font_rendering, data_file, 608 data_helper_file): 609 # write more data 610 611 # Generate a unique name for jumbo build which concatenates multiple 612 # translation units into one to speed compilation. 613 basename = os.path.basename(data_helper_file.name) 614 # & 0xffffffff converts to unsigned to keep consistent across Python versions 615 # and platforms as per https://docs.python.org/3/library/zlib.html 616 suffix = '_%s' % (zlib.crc32(basename.encode()) & 0xffffffff) 617 var_name = 'kMoreForEntry' + str(entry_id) + suffix 618 if is_exception: 619 var_name += 'Exception' + str(exception_id) 620 data_helper_file.write('const GpuControlList::More %s = {\n' % var_name) 621 write_gl_type(gl_type, data_helper_file) 622 write_version(gl_version, 'gl_version', data_helper_file) 623 write_version(pixel_shader_version, 'pixel_shader_version', data_helper_file) 624 write_boolean_value(in_process_gpu, 'in_process_gpu', data_helper_file) 625 if not gl_reset_notification_strategy: 626 gl_reset_notification_strategy = '0' 627 data_helper_file.write('%s, // gl_reset_notification_strategy\n' % 628 gl_reset_notification_strategy) 629 write_version(direct_rendering_version, 'direct_rendering_version', 630 data_helper_file) 631 write_version(gpu_count, 'gpu_count', data_helper_file) 632 write_supported_or_not(hardware_overlay, 'hardware_overlay', data_helper_file) 633 write_integer_value(test_group, 'test_group', data_helper_file) 634 write_supported_or_not(subpixel_font_rendering, 'subpixel_font_rendering', 635 data_helper_file) 636 data_helper_file.write('};\n\n') 637 # reference more data in entry 638 data_file.write('&%s, // more data\n' % var_name) 639 640 641def write_entry(entry, total_feature_set, feature_name_prefix, 642 unique_symbol_id, data_file, data_helper_file, 643 data_exception_file): 644 data_file.write('{\n') 645 # ID 646 entry_id = entry['id'] 647 data_file.write('%d, // id\n' % entry_id) 648 data_file.write('"%s",\n' % entry['description']); 649 # Features 650 if 'features' in entry: 651 var_name = 'kFeatureListFor%sEntry%d' % (unique_symbol_id, entry_id) 652 features = entry['features'] 653 feature_set = get_feature_set(features, total_feature_set) 654 data_file.write('base::size(%s), // features size\n' % var_name) 655 data_file.write('%s, // features\n' % var_name) 656 write_features(feature_set, feature_name_prefix, var_name, data_helper_file) 657 else: 658 data_file.write('0, // feature size\n') 659 data_file.write('nullptr, // features\n') 660 # Disabled extensions 661 write_disabled_extension_list('DisabledExtensions', entry_id, 662 entry.get('disabled_extensions', None), 663 data_file, data_helper_file) 664 # Disabled WebGL extensions 665 write_disabled_extension_list('DisabledWebGLExtensions', entry_id, 666 entry.get('disabled_webgl_extensions', None), 667 data_file, data_helper_file) 668 # webkit_bugs are skipped because there is only one entry that has it. 669 # cr_bugs 670 cr_bugs = None 671 if 'cr_bugs' in entry: 672 cr_bugs = entry['cr_bugs'] 673 write_number_list(entry_id, 'uint32_t', 'CrBugs', cr_bugs, False, -1, 674 unique_symbol_id, data_file, data_helper_file) 675 # Conditions 676 data_file.write('{\n') 677 write_conditions(entry_id, False, -1, entry, unique_symbol_id, 678 data_file, data_helper_file, data_exception_file) 679 data_file.write('},\n') 680 # Exceptions 681 if 'exceptions' in entry: 682 exceptions = entry['exceptions'] 683 exception_count = len(exceptions) 684 exception_var = 'kExceptionsForEntry' + str(entry_id) 685 data_exception_file.write('const GpuControlList::Conditions %s[%d] = {\n' % 686 (exception_var, exception_count)) 687 for index in range(exception_count): 688 exception = exceptions[index] 689 if 'device_id' in exception and 'vendor_id' not in exception: 690 assert 'vendor_id' in entry 691 exception['vendor_id'] = entry['vendor_id'] 692 data_exception_file.write('{\n') 693 write_conditions(entry_id, True, index, exception, unique_symbol_id, 694 data_exception_file, data_helper_file, None) 695 data_exception_file.write('},\n') 696 data_exception_file.write('};\n\n') 697 data_file.write('base::size(%s), // exceptions count\n' % exception_var) 698 data_file.write('%s, // exceptions\n' % exception_var) 699 else: 700 data_file.write('0, // exceptions count\n') 701 data_file.write('nullptr, // exceptions\n') 702 # END 703 data_file.write('},\n') 704 705 706def format_files(generated_files): 707 formatter = "clang-format" 708 if platform.system() == "Windows": 709 formatter += ".bat" 710 for filename in generated_files: 711 call([formatter, "-i", "-style=chromium", filename]) 712 713 714def write_header_file_guard(file, filename, path, begin): 715 token = (path.upper().replace('/', '_') + '_' + 716 filename.upper().replace('.', '_') + '_') 717 if begin: 718 file.write('#ifndef %s\n#define %s\n\n' % (token, token)) 719 else: 720 file.write('\n#endif // %s\n' % token) 721 722 723def process_json_file(json_filepath, list_tag, 724 feature_header_filename, total_features, feature_tag, 725 output_header_filepath, output_data_filepath, 726 output_helper_filepath, output_exception_filepath, path, 727 export_tag, git_format, os_filter, unique_symbol_id): 728 output_header_filename = os.path.basename(output_header_filepath) 729 output_helper_filename = os.path.basename(output_helper_filepath) 730 output_exception_filename = os.path.basename(output_exception_filepath) 731 json_file = open(json_filepath, 'rb') 732 json_data = json.load(json_file) 733 json_file.close() 734 data_file = open(output_data_filepath, 'w') 735 data_file.write(_LICENSE) 736 data_file.write(_DO_NOT_EDIT_WARNING) 737 data_file.write('#include "%s/%s"\n\n' % (path, output_header_filename)) 738 data_file.write('#include "%s/%s"\n' % (path, output_helper_filename)) 739 data_file.write('#include "%s/%s"\n\n' % (path, output_exception_filename)) 740 data_helper_file = open(output_helper_filepath, 'w') 741 data_helper_file.write(_LICENSE) 742 data_helper_file.write(_DO_NOT_EDIT_WARNING) 743 write_header_file_guard(data_helper_file, output_helper_filename, path, True) 744 data_helper_file.write('#include "gpu/config/%s"\n\n' % 745 feature_header_filename) 746 data_helper_file.write('namespace gpu {\n') 747 data_exception_file = open(output_exception_filepath, 'w') 748 data_exception_file.write(_LICENSE) 749 data_exception_file.write(_DO_NOT_EDIT_WARNING) 750 write_header_file_guard(data_exception_file, output_exception_filename, path, 751 True) 752 data_exception_file.write('namespace gpu {\n') 753 data_file.write('namespace gpu {\n\n') 754 data_file.write('const GpuControlList::Entry k%sEntries[] = {\n' % list_tag) 755 ids = [] 756 entry_count = 0 757 for index in range(len(json_data['entries'])): 758 entry = json_data['entries'][index] 759 entry_id = entry['id'] 760 assert entry_id not in ids 761 ids.append(entry_id) 762 if 'os' in entry: 763 os_type = entry['os']['type'] 764 # Check for typos in the .json data 765 if os_type not in _OS_TYPE_MAP: 766 raise Exception('Unknown OS type "%s" for entry %d' % 767 (os_type, entry_id)) 768 if os_filter != None and os_type != os_filter: 769 continue 770 entry_count += 1 771 write_entry(entry, total_features, feature_tag, unique_symbol_id, 772 data_file, data_helper_file, data_exception_file) 773 data_file.write('};\n') 774 data_file.write('const size_t k%sEntryCount = %d;\n' % 775 (list_tag, entry_count)) 776 data_file.write('} // namespace gpu\n') 777 data_file.close() 778 data_helper_file.write('} // namespace gpu\n') 779 write_header_file_guard(data_helper_file, output_helper_filename, path, False) 780 data_helper_file.close() 781 data_exception_file.write('} // namespace gpu\n') 782 write_header_file_guard(data_exception_file, output_exception_filename, path, 783 False) 784 data_exception_file.close() 785 data_header_file = open(output_header_filepath, 'w') 786 data_header_file.write(_LICENSE) 787 data_header_file.write(_DO_NOT_EDIT_WARNING) 788 write_header_file_guard(data_header_file, output_header_filename, path, True) 789 if export_tag == 'CONTENT_EXPORT ': 790 data_header_file.write('#include "content/common/content_export.h"\n') 791 data_header_file.write('#include "gpu/config/gpu_control_list.h"\n\n') 792 data_header_file.write('\n') 793 data_header_file.write('namespace gpu {\n') 794 data_header_file.write('%sextern const size_t k%sEntryCount;\n' % 795 (export_tag, list_tag)) 796 data_header_file.write( 797 '%sextern const GpuControlList::Entry k%sEntries[];\n' % 798 (export_tag, list_tag)) 799 data_header_file.write('} // namespace gpu\n') 800 write_header_file_guard(data_header_file, output_header_filename, path, False) 801 data_header_file.close() 802 if git_format: 803 format_files([output_header_filepath, output_data_filepath, 804 output_helper_filepath, output_exception_filepath]) 805 806 807def process_software_rendering_list(script_dir, output_dir, os_filter): 808 total_features = load_software_rendering_list_features( 809 os.path.join(script_dir, 'gpu_feature_type.h')) 810 process_json_file( 811 os.path.join(script_dir, 'software_rendering_list.json'), 812 'SoftwareRenderingList', 813 'gpu_feature_type.h', 814 total_features, 815 'GPU_FEATURE_TYPE_', 816 os.path.join(output_dir, 'software_rendering_list_autogen.h'), 817 os.path.join(output_dir, 'software_rendering_list_autogen.cc'), 818 os.path.join(output_dir, 819 'software_rendering_list_arrays_and_structs_autogen.h'), 820 os.path.join(output_dir, 'software_rendering_list_exceptions_autogen.h'), 821 'gpu/config', 822 'GPU_EXPORT ', 823 False, 824 os_filter, 825 'Software') 826 827 828def process_gpu_driver_bug_list(script_dir, output_dir, os_filter): 829 total_features = load_gpu_driver_bug_workarounds( 830 os.path.join(output_dir, 'gpu_driver_bug_workaround_autogen.h')) 831 process_json_file( 832 os.path.join(script_dir, 'gpu_driver_bug_list.json'), 833 'GpuDriverBugList', 834 'gpu_driver_bug_workaround_type.h', 835 total_features, 836 '', 837 os.path.join(output_dir, 'gpu_driver_bug_list_autogen.h'), 838 os.path.join(output_dir, 'gpu_driver_bug_list_autogen.cc'), 839 os.path.join(output_dir, 840 'gpu_driver_bug_list_arrays_and_structs_autogen.h'), 841 os.path.join(output_dir, 'gpu_driver_bug_list_exceptions_autogen.h'), 842 'gpu/config', 843 'GPU_EXPORT ', 844 False, 845 os_filter, 846 'Workarounds') 847 848 849def process_gpu_control_list_testing(script_dir, output_dir): 850 total_features = ['test_feature_0', 'test_feature_1', 'test_feature_2'] 851 process_json_file( 852 os.path.join(script_dir, 'gpu_control_list_testing.json'), 853 'GpuControlListTesting', 854 'gpu_control_list_testing_data.h', 855 total_features, 856 '', 857 os.path.join(output_dir, 'gpu_control_list_testing_autogen.h'), 858 os.path.join(output_dir, 'gpu_control_list_testing_autogen.cc'), 859 os.path.join(output_dir, 860 'gpu_control_list_testing_arrays_and_structs_autogen.h'), 861 os.path.join(output_dir, 'gpu_control_list_testing_exceptions_autogen.h'), 862 'gpu/config', 863 '', 864 True, 865 None, 866 'GpuControlTesting') 867 868 869def process_gpu_data_manager_testing(script_dir, output_dir): 870 total_features = load_software_rendering_list_features( 871 os.path.join(script_dir, 'gpu_feature_type.h')) 872 process_json_file( 873 os.path.join(output_dir, 'gpu_data_manager_testing.json'), 874 'GpuDataManagerTesting', 875 'gpu_feature_type.h', 876 total_features, 877 'GPU_FEATURE_TYPE_', 878 os.path.join(output_dir, 'gpu_data_manager_testing_autogen.h'), 879 os.path.join(output_dir, 'gpu_data_manager_testing_autogen.cc'), 880 os.path.join(output_dir, 881 'gpu_data_manager_testing_arrays_and_structs_autogen.h'), 882 os.path.join(output_dir, 'gpu_data_manager_testing_exceptions_autogen.h'), 883 'content/browser/gpu', 884 '', 885 True, 886 None, 887 'GpuManagerTesting') 888 889 890def write_test_entry_enums(input_json_filepath, output_entry_enums_filepath, 891 path, list_tag): 892 json_file = open(input_json_filepath, 'rb') 893 json_data = json.load(json_file) 894 json_file.close() 895 896 output_entry_enums_filename = os.path.basename(output_entry_enums_filepath) 897 enum_file = open(output_entry_enums_filepath, 'w') 898 enum_file.write(_LICENSE) 899 enum_file.write(_DO_NOT_EDIT_WARNING) 900 write_header_file_guard(enum_file, output_entry_enums_filename, path, True) 901 enum_file.write('namespace gpu {\n') 902 enum_file.write('enum %sEntryEnum {\n' % list_tag) 903 entry_count = len(json_data['entries']) 904 for index in range(entry_count): 905 entry = json_data['entries'][index] 906 entry_id = entry['id'] 907 description = entry['description'] 908 assert(index + 1 == int(entry_id)) 909 description = 'k' + description 910 description = description.replace('.', '_') 911 enum_file.write(' %s = %d,\n' % (description, index)) 912 enum_file.write('};\n') 913 enum_file.write('} // namespace gpu\n') 914 write_header_file_guard(enum_file, output_entry_enums_filename, path, False) 915 enum_file.close() 916 format_files([output_entry_enums_filepath]) 917 918 919def main(argv): 920 parser = OptionParser() 921 parser.add_option("--output-dir", 922 help="output directory for SoftwareRenderingList and " 923 "GpuDriverBugList data files. " 924 "If unspecified, these files are not generated.") 925 parser.add_option("--skip-testing-data", action="store_false", 926 dest="generate_testing_data", default=True, 927 help="skip testing data generation.") 928 parser.add_option("--os-filter", 929 help="only output entries applied to the specified os.") 930 (options, _) = parser.parse_args(args=argv) 931 932 script_dir = os.path.dirname(os.path.realpath(__file__)) 933 934 if options.output_dir != None: 935 process_software_rendering_list( 936 script_dir, options.output_dir, options.os_filter) 937 process_gpu_driver_bug_list( 938 script_dir, options.output_dir, options.os_filter) 939 940 if options.generate_testing_data: 941 # Testing data files are generated by calling the script manually. 942 process_gpu_control_list_testing(script_dir, script_dir) 943 write_test_entry_enums( 944 os.path.join(script_dir, 'gpu_control_list_testing.json'), 945 os.path.join(script_dir, 946 'gpu_control_list_testing_entry_enums_autogen.h'), 947 'gpu/config', 948 'GpuControlListTesting') 949 chrome_root_dir = os.path.abspath(os.path.join(script_dir, '../../')) 950 gpu_data_manager_dir = os.path.join(chrome_root_dir, 'content/browser/gpu') 951 process_gpu_data_manager_testing(script_dir, gpu_data_manager_dir) 952 write_test_entry_enums( 953 os.path.join(gpu_data_manager_dir, 'gpu_data_manager_testing.json'), 954 os.path.join(gpu_data_manager_dir, 955 'gpu_data_manager_testing_entry_enums_autogen.h'), 956 'content/browser/gpu', 957 'GpuDataManagerTesting') 958 959 960if __name__ == '__main__': 961 sys.exit(main(sys.argv[1:])) 962