medfall

A super great game engine
Log | Files | Refs

generator.py (12020B)


      1 import os
      2 import sys
      3 
      4 from glad.lang.common.generator import Generator
      5 from glad.lang.common.util import makefiledir
      6 
      7 
      8 KHRPLATFORM = 'https://www.khronos.org/registry/egl/api/KHR/khrplatform.h'
      9 
     10 
     11 class CGenerator(Generator):
     12     NAME = 'c'
     13     NAME_LONG = 'C/C++'
     14 
     15     def open(self):
     16         suffix = ''
     17         if not self.spec.NAME == 'gl':
     18             suffix = '_{}'.format(self.spec.NAME)
     19 
     20         if self.local_files:
     21             self.h_include = '"glad{}.h"'.format(suffix)
     22             self._f_c = open(make_path(self.path,
     23                                         'glad{}.c'.format(suffix)), 'w')
     24             self._f_h = open(make_path(self.path, 
     25                                         'glad{}.h'.format(suffix)), 'w')
     26             khr = self.path
     27         else:
     28             self.h_include = '<glad/glad{}.h>'.format(suffix)
     29             self._f_c = open(make_path(self.path, 'src',
     30                                         'glad{}.c'.format(suffix)), 'w')
     31             self._f_h = open(make_path(self.path, 'include', 'glad',
     32                                         'glad{}.h'.format(suffix)), 'w')
     33             khr = os.path.join(self.path, 'include', 'KHR')
     34 
     35         if not self.omit_khrplatform:
     36             khr_url = KHRPLATFORM
     37             if os.path.exists('khrplatform.h'):
     38                 khr_url = 'file://' + os.path.abspath('khrplatform.h')
     39 
     40             khrplatform = os.path.join(khr, 'khrplatform.h')
     41             if not os.path.exists(khrplatform):
     42                 if not os.path.exists(khr):
     43                     os.makedirs(khr)
     44                 self.opener.urlretrieve(khr_url, khrplatform)
     45 
     46         return self
     47 
     48     def close(self):
     49         self._f_c.close()
     50         self._f_h.close()
     51 
     52     def generate_header(self):
     53         self._f_h.write('/*\n')
     54         self._f_h.write(self.header)
     55         self._f_h.write('*/\n\n')
     56 
     57         self._f_c.write('/*\n')
     58         self._f_c.write(self.header)
     59         self._f_c.write('*/\n\n')
     60 
     61     def generate_loader(self, features, extensions):
     62         f = self._f_c
     63 
     64         if self.spec.NAME in ('egl', 'wgl'):
     65             features = {'egl': [], 'wgl': []}
     66 
     67         written = set()
     68         for api, version in self.api.items():
     69             for feature in features[api]:
     70                 f.write('static void load_{}(GLADloadproc load) {{\n'
     71                         .format(feature.name))
     72                 if self.spec.NAME in ('gl', 'glx', 'wgl'):
     73                     f.write('\tif(!GLAD_{}) return;\n'.format(feature.name))
     74                 for func in feature.functions:
     75                     f.write('\tglad_{0} = (PFN{1}PROC)load("{0}");\n'
     76                             .format(func.proto.name, func.proto.name.upper()))
     77                 f.write('}\n')
     78 
     79             for ext in extensions[api]:
     80                 if len(list(ext.functions)) == 0 or ext.name in written:
     81                     continue
     82 
     83                 f.write('static void load_{}(GLADloadproc load) {{\n'
     84                         .format(ext.name))
     85                 if self.spec.NAME in ('gl', 'glx', 'wgl'):
     86                     f.write('\tif(!GLAD_{}) return;\n'.format(ext.name))
     87                 if ext.name == 'GLX_SGIX_video_source': f.write('#ifdef _VL_H_\n')
     88                 if ext.name == 'GLX_SGIX_dmbuffer': f.write('#ifdef _DM_BUFFER_H_\n')
     89                 for func in ext.functions:
     90                     # even if they were in written we need to load it
     91                     f.write('\tglad_{0} = (PFN{1}PROC)load("{0}");\n'
     92                             .format(func.proto.name, func.proto.name.upper()))
     93                 if ext.name in ('GLX_SGIX_video_source', 'GLX_SGIX_dmbuffer'):
     94                     f.write('#else\n')
     95                     f.write('\t(void)load;\n')
     96                     f.write('#endif\n')
     97                 f.write('}\n')
     98 
     99                 written.add(ext.name)
    100 
    101             f.write('static int find_extensions{}(void) {{\n'.format(api.upper()))
    102             if self.spec.NAME in ('gl', 'glx', 'wgl'):
    103                 f.write('\tif (!get_exts()) return 0;\n')
    104                 for ext in extensions[api]:
    105                     f.write('\tGLAD_{0} = has_ext("{0}");\n'.format(ext.name))
    106                 f.write('\tfree_exts();\n')
    107             f.write('\treturn 1;\n')
    108             f.write('}\n\n')
    109 
    110             if api == 'glx':
    111                 f.write('static void find_core{}(Display *dpy, int screen) {{\n'.format(api.upper()))
    112             elif api == 'wgl':
    113                 f.write('static void find_core{}(HDC hdc) {{\n'.format(api.upper()))
    114             else:
    115                 f.write('static void find_core{}(void) {{\n'.format(api.upper()))
    116 
    117             self.loader.write_find_core(f)
    118             if self.spec.NAME in ('gl', 'glx', 'wgl'):
    119                 for feature in features[api]:
    120                     f.write('\tGLAD_{} = (major == {num[0]} && minor >= {num[1]}) ||'
    121                             ' major > {num[0]};\n'.format(feature.name, num=feature.number))
    122             if self.spec.NAME == 'gl':
    123                 f.write('\tif (GLVersion.major > {0} || (GLVersion.major >= {0} && GLVersion.minor >= {1})) {{\n'.format(version[0], version[1]))
    124                 f.write('\t\tmax_loaded_major = {0};\n'.format(version[0]))
    125                 f.write('\t\tmax_loaded_minor = {0};\n'.format(version[1]))
    126                 f.write('\t}\n')
    127             f.write('}\n\n')
    128 
    129             if api == 'glx':
    130                 f.write('int gladLoad{}Loader(GLADloadproc load, Display *dpy, int screen) {{\n'.format(api.upper()))
    131             elif api == 'wgl':
    132                 f.write('int gladLoad{}Loader(GLADloadproc load, HDC hdc) {{\n'.format(api.upper()))
    133             else:
    134                 f.write('int gladLoad{}Loader(GLADloadproc load) {{\n'.format(api.upper()))
    135 
    136             self.loader.write_begin_load(f)
    137 
    138             if api == 'glx':
    139                 f.write('\tfind_core{}(dpy, screen);\n'.format(api.upper()))
    140             elif api == 'wgl':
    141                 f.write('\tfind_core{}(hdc);\n'.format(api.upper()))
    142             else:
    143                 f.write('\tfind_core{}();\n'.format(api.upper()))
    144 
    145             for feature in features[api]:
    146                 f.write('\tload_{}(load);\n'.format(feature.name))
    147             f.write('\n\tif (!find_extensions{}()) return 0;\n'.format(api.upper()))
    148             for ext in extensions[api]:
    149                 if len(list(ext.functions)) == 0:
    150                     continue
    151                 f.write('\tload_{}(load);\n'.format(ext.name))
    152 
    153             self.loader.write_end_load(f)
    154             f.write('}\n\n')
    155 
    156         self.loader.write_header_end(self._f_h)
    157 
    158     def generate_types(self, types):
    159         f = self._f_h
    160 
    161         self.loader.write_header(f)
    162         self.write_api_header(f)
    163 
    164         for type in types:
    165             output_string = (type.raw + '\n').lstrip().replace('        ', ' ')
    166             if output_string == '#include <KHR/khrplatform.h>\n':
    167                 if self.omit_khrplatform:
    168                     continue
    169                 elif self.local_files:
    170                     output_string = '#include "khrplatform.h"\n'
    171             if not self.spec.NAME in ('egl',) and 'khronos' in type.raw:
    172                 continue
    173             f.write(output_string)
    174 
    175     def generate_features(self, features):
    176         f = self._f_h
    177         write = set()
    178         if self.spec.NAME in ('wgl',):
    179             # These are already defined in windows.h
    180             pass
    181         elif self.spec.NAME in ('egl',):
    182             self.write_enums(f, set(), features)
    183 
    184             for feature in features:
    185                 for func in feature.functions:
    186                     self.write_function_def(f, func)
    187         else:
    188             self.write_functions(f, write, set(), features)
    189 
    190         f = self._f_c
    191         self.write_code_head(f)
    192         self.loader.write(f)
    193         self.loader.write_has_ext(f)
    194 
    195         if self.spec.NAME in ('gl', 'glx', 'wgl'):
    196             for feature in features:
    197                 f.write('int GLAD_{};\n'.format(feature.name))
    198 
    199         for func in write:
    200             self.write_function(f, func)
    201 
    202     def generate_extensions(self, extensions, enums, functions):
    203         write = set()
    204         written = set(enum.name for enum in enums) | \
    205                   set(function.proto.name for function in functions)
    206 
    207         f = self._f_h
    208         self.write_functions(f, write, written, extensions)
    209 
    210         f = self._f_c
    211         if self.spec.NAME in ('gl', 'glx', 'wgl'):
    212             for ext in set(ext.name for ext in extensions):
    213                 f.write('int GLAD_{};\n'.format(ext))
    214 
    215         written = set()
    216         for ext in extensions:
    217             if ext.name == 'GLX_SGIX_video_source': f.write('#ifdef _VL_H_\n')
    218             if ext.name == 'GLX_SGIX_dmbuffer': f.write('#ifdef _DM_BUFFER_H_\n')
    219             for func in ext.functions:
    220                 if func in write and func not in written:
    221                     self.write_function(f, func)
    222                     written.add(func)
    223             if ext.name in ('GLX_SGIX_video_source', 'GLX_SGIX_dmbuffer'): f.write('#endif\n')
    224 
    225     def write_functions(self, f, write, written, extensions):
    226         self.write_enums(f, written, extensions)
    227 
    228         for ext in extensions:
    229             f.write('#ifndef {0}\n#define {0} 1\n'.format(ext.name))
    230             if self.spec.NAME in ('gl', 'glx', 'wgl'):
    231                 f.write('GLAPI int GLAD_{};\n'.format(ext.name))
    232             if ext.name == 'GLX_SGIX_video_source': f.write('#ifdef _VL_H_\n')
    233             if ext.name == 'GLX_SGIX_dmbuffer': f.write('#ifdef _DM_BUFFER_H_\n')
    234             for func in ext.functions:
    235                 if not func.proto.name in written:
    236                     self.write_function_prototype(f, func)
    237                     write.add(func)
    238                 written.add(func.proto.name)
    239             if ext.name in ('GLX_SGIX_video_source', 'GLX_SGIX_dmbuffer'): f.write('#endif\n')
    240             f.write('#endif\n')
    241 
    242     def write_enums(self, f, written, extensions):
    243         for ext in extensions:
    244             for enum in ext.enums:
    245                 if not enum.name in written:
    246                     f.write('#define {} {}\n'.format(enum.name, enum.value))
    247                 written.add(enum.name)
    248 
    249     def write_api_header(self, f):
    250         for api in self.api:
    251             if api == 'glx':
    252                 f.write('GLAPI int gladLoad{}Loader(GLADloadproc, Display *dpy, int screen);\n\n'.format(api.upper()))
    253             elif api == 'wgl':
    254                 f.write('GLAPI int gladLoad{}Loader(GLADloadproc, HDC hdc);\n\n'.format(api.upper()))
    255             else:
    256                 f.write('GLAPI int gladLoad{}Loader(GLADloadproc);\n\n'.format(api.upper()))
    257 
    258     def write_code_head(self, f):
    259         f.write('#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include {}\n'.format(self.h_include))
    260 
    261     def write_extern(self, fobj):
    262         fobj.write('#ifdef __cplusplus\nextern "C" {\n#endif\n')
    263 
    264     def write_extern_end(self, fobj):
    265         fobj.write('#ifdef __cplusplus\n}\n#endif\n')
    266 
    267     def write_function_def(self, fobj, func):
    268         # write a function definition instead of a prototype.
    269         # e.g. egl uses that, since the main functions get linked in and not loaded through a function.
    270         fobj.write('{}('.format(func.proto.ret.raw))
    271         fobj.write(', '.join(param.type.raw for param in func.params))
    272         fobj.write(');\n')
    273 
    274     def write_function_prototype(self, fobj, func):
    275         fobj.write('typedef {} (APIENTRYP PFN{}PROC)({});\n'.format(
    276             func.proto.ret.to_c(), func.proto.name.upper(),
    277             ', '.join(param.type.raw for param in func.params))
    278         )
    279         fobj.write('GLAPI PFN{}PROC glad_{};\n'.format(func.proto.name.upper(),
    280                                                        func.proto.name))
    281         fobj.write('#define {0} glad_{0}\n'.format(func.proto.name))
    282 
    283     def write_function(self, fobj, func):
    284         fobj.write('PFN{}PROC glad_{};\n'.format(func.proto.name.upper(),
    285                                                  func.proto.name))
    286 
    287 
    288 def make_path(path, *args):
    289     path = os.path.join(path, *args)
    290     makefiledir(path)
    291     return path