Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/scripts/generate_new_renderer.py
1693 views
1
#!/usr/bin/python2
2
#
3
# Copyright 2015 The ANGLE Project Authors. All rights reserved.
4
# Use of this source code is governed by a BSD-style license that can be
5
# found in the LICENSE file.
6
#
7
# generate_new_renderer.py:
8
# Utility script to generate stubs for a new Renderer class.
9
# Usage: generate_new_renderer.py <renderer name> <renderer suffix>
10
# Renderer name is the folder for the renderer subdirectory
11
# Renderer suffix is the abbreviation to append after the class names.
12
#
13
# The script is fairly robust but may not work for all new methods or
14
# other unexpected features. It expects that abstract methods are all
15
# grouped after the public destructor or after the private
16
# DISALLOW_COPY_AND_ASSIGN macro.
17
18
import os, sys, re, string
19
20
if len(sys.argv) < 3:
21
print('Usage: ' + sys.argv[0] + ' <renderer dir name> <renderer class suffix>')
22
sys.exit(1)
23
24
renderer_name = sys.argv[1]
25
renderer_suffix = sys.argv[2]
26
27
# change to the renderer directory
28
os.chdir(os.path.join(os.path.dirname(sys.argv[0]), "..", "src", "libANGLE", "renderer"))
29
30
# ensure subdir exists
31
if not os.path.isdir(renderer_name):
32
os.mkdir(renderer_name)
33
34
impl_classes = [
35
'Buffer',
36
'Compiler',
37
'Context',
38
'Device',
39
'Display',
40
'FenceNV',
41
'FenceSync',
42
'Framebuffer',
43
'Image',
44
'Path',
45
'Program',
46
'Query',
47
'Renderbuffer',
48
'Sampler',
49
'Shader',
50
'Surface',
51
'Texture',
52
'TransformFeedback',
53
'VertexArray',
54
]
55
56
h_file_template = """//
57
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
58
// Use of this source code is governed by a BSD-style license that can be
59
// found in the LICENSE file.
60
//
61
// $TypedImpl.h:
62
// Defines the class interface for $TypedImpl, implementing $BaseImpl.
63
//
64
65
#ifndef LIBANGLE_RENDERER_${RendererNameCaps}_${TypedImplCaps}_H_
66
#define LIBANGLE_RENDERER_${RendererNameCaps}_${TypedImplCaps}_H_
67
68
#include "libANGLE/renderer/$BaseImpl.h"
69
70
namespace rx
71
{
72
73
class $TypedImpl : public $BaseImpl
74
{
75
public:
76
$TypedImpl($ConstructorParams);
77
~$TypedImpl() override;
78
$ImplMethodDeclarations$PrivateImplMethodDeclarations};
79
80
} // namespace rx
81
82
#endif // LIBANGLE_RENDERER_${RendererNameCaps}_${TypedImplCaps}_H_
83
"""
84
85
cpp_file_template = """//
86
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
87
// Use of this source code is governed by a BSD-style license that can be
88
// found in the LICENSE file.
89
//
90
// $TypedImpl.cpp:
91
// Implements the class methods for $TypedImpl.
92
//
93
94
#include "libANGLE/renderer/$RendererName/$TypedImpl.h"
95
96
#include "common/debug.h"
97
98
namespace rx
99
{
100
101
$TypedImpl::$TypedImpl($ConstructorParams) : $BaseImpl($BaseContructorArgs)
102
{
103
}
104
105
$TypedImpl::~$TypedImpl()
106
{
107
}
108
$ImplMethodDefinitions
109
} // namespace rx
110
"""
111
112
113
def generate_impl_declaration(impl_stub):
114
# ensure the wrapped lines are aligned vertically
115
temp = re.sub(r'\n ', '\n', impl_stub)
116
return temp + ' override;\n'
117
118
119
def generate_impl_definition(impl_stub, typed_impl):
120
function_signature = impl_stub.strip()
121
122
# strip comments
123
function_signature = re.sub(r'\/\/[^\n]*\n', '', function_signature).strip()
124
125
prog = re.compile(r'^(.+[ \*\&])([^ \(\*\&]+\()')
126
return_value = prog.match(function_signature).group(1)
127
128
# ensure the wrapped lines are aligned vertically
129
spaces = ' ' * len(typed_impl)
130
function_signature = re.sub(r'\n ', '\n' + spaces, function_signature)
131
132
# add class scoping
133
function_signature = prog.sub(r'\1' + typed_impl + r'::\2', function_signature)
134
function_signature += '\n'
135
136
return_statement = ''
137
return_type = return_value.strip()
138
139
if return_type != 'void':
140
# specialized return values for Errors, pointers, etc
141
if return_type == 'gl::Error':
142
return_statement = ' return gl::InvalidOperation();\n'
143
elif return_type == 'egl::Error':
144
return_statement = ' return egl::EglBadAccess();\n'
145
elif return_type == 'LinkResult':
146
return_statement = ' return gl::InvalidOperation();\n'
147
elif re.search(r'\*$', return_type):
148
return_statement = ' return static_cast<' + return_type + '>(0);\n'
149
elif re.search(r'const ([^ \&]+) \&$', return_type):
150
obj_type = re.search(r'const ([^ \&]+) \&$', return_type).group(1)
151
return_statement = ' static ' + obj_type + ' local;\n' + ' return local;\n'
152
else:
153
return_statement = ' return ' + return_type + '();\n'
154
155
body = '{\n' + ' UNIMPLEMENTED();\n' + return_statement + '}\n'
156
157
return '\n' + function_signature + body
158
159
160
def get_constructor_args(constructor):
161
params = re.search(r'\((.*)\)', constructor).group(1)
162
args = ', '.join(re.findall(r'[^\w]?(\w+)(?:\,|$)', params))
163
return params, args
164
165
166
def parse_impl_header(base_impl):
167
impl_h_file_path = base_impl + '.h'
168
impl_h_file = open(impl_h_file_path, 'r')
169
170
# extract impl stubs
171
copy = False
172
copy_private = False
173
impl_stubs = ''
174
private_impl_stubs = ''
175
constructor = base_impl + '() {}'
176
for line in impl_h_file:
177
clean_line = line.strip()
178
179
match = re.search(r'^(?:explicit )?(' + base_impl + r'\([^\)]*\))', clean_line)
180
if match:
181
constructor = match.group(1)
182
183
# begin capture when reading the destructor.
184
# begin capture also in the private scope (a few special cases)
185
# end capture when we reach a non-virtual function, or different scope.
186
if '~' + base_impl in clean_line:
187
copy = True
188
copy_private = False
189
elif 'private:' in clean_line:
190
copy = False
191
copy_private = True
192
elif ';' in clean_line and ' = 0' not in clean_line:
193
copy = False
194
copy_private = False
195
elif '}' in clean_line or 'protected:' in clean_line or 'private:' in clean_line:
196
copy = False
197
copy_private = False
198
elif copy:
199
impl_stubs += line
200
elif copy_private:
201
private_impl_stubs += line
202
203
impl_h_file.close()
204
205
return impl_stubs, private_impl_stubs, constructor
206
207
208
def get_base_class(base_impl):
209
impl_h_file_path = base_impl + '.h'
210
with open(impl_h_file_path, 'r') as impl_h_file:
211
for line in impl_h_file:
212
match = re.search(r'^class ' + base_impl + r' : public (\w+)', line)
213
if match:
214
return match.group(1)
215
return False
216
217
218
for impl_class in impl_classes:
219
220
base_impl = impl_class + 'Impl'
221
typed_impl = impl_class + renderer_suffix
222
223
h_file_path = os.path.join(renderer_name, typed_impl + '.h')
224
cpp_file_path = os.path.join(renderer_name, typed_impl + '.cpp')
225
226
h_file = open(h_file_path, 'w')
227
cpp_file = open(cpp_file_path, 'w')
228
229
# extract impl stubs
230
impl_stubs, private_impl_stubs, constructor = parse_impl_header(base_impl)
231
232
# Handle base classes, skipping angle::NonCopyable.
233
base_class = get_base_class(base_impl)
234
if base_class and base_class != 'angle':
235
base_impl_stubs, base_private_impl_stubs, base_constructor = parse_impl_header(base_class)
236
impl_stubs += base_impl_stubs
237
private_impl_stubs += base_private_impl_stubs
238
239
impl_method_declarations = ''
240
impl_method_definitions = ''
241
private_impl_method_declarations = ''
242
243
for impl_stub in impl_stubs.split(' = 0;\n'):
244
# use 'virtual' to identify the strings with functions
245
if 'virtual' in impl_stub:
246
temp = re.sub(r'virtual ', '', impl_stub)
247
impl_method_declarations += generate_impl_declaration(temp)
248
impl_method_definitions += generate_impl_definition(temp, typed_impl)
249
250
for impl_stub in private_impl_stubs.split(' = 0;\n'):
251
# use 'virtual' to identify the strings with functions
252
if 'virtual' in impl_stub:
253
temp = re.sub(r'virtual ', '', impl_stub)
254
private_impl_method_declarations += generate_impl_declaration(temp)
255
impl_method_definitions += generate_impl_definition(temp, typed_impl)
256
257
constructor_params, base_constructor_args = get_constructor_args(constructor)
258
259
if private_impl_method_declarations:
260
private_impl_method_declarations = "\n private:\n" + private_impl_method_declarations
261
262
substitutions = {
263
'BaseImpl': base_impl,
264
'TypedImpl': typed_impl,
265
'TypedImplCaps': typed_impl.upper(),
266
'RendererName': renderer_name,
267
'RendererNameCaps': renderer_name.upper(),
268
'ImplMethodDeclarations': impl_method_declarations,
269
'ImplMethodDefinitions': impl_method_definitions,
270
'ConstructorParams': constructor_params,
271
'BaseContructorArgs': base_constructor_args,
272
'PrivateImplMethodDeclarations': private_impl_method_declarations
273
}
274
275
h_file.write(string.Template(h_file_template).substitute(substitutions))
276
cpp_file.write(string.Template(cpp_file_template).substitute(substitutions))
277
278
h_file.close()
279
cpp_file.close()
280
281
# Print a block of source files to add to the build
282
print("Generated files:")
283
for impl_class in impl_classes:
284
path = "libANGLE/renderer/" + renderer_name + "/" + impl_class + renderer_suffix
285
print('\'' + path + ".cpp\',")
286
print('\'' + path + ".h\',")
287
288