• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python3 -i
2#
3# Copyright (c) 2013-2018 The Khronos Group Inc.
4# Copyright (c) 2013-2018 Google Inc.
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17
18import os, re, sys
19from generator import *
20from pathlib import Path, PurePosixPath
21
22import cereal
23from cereal.wrapperdefs import VULKAN_STREAM_TYPE
24from cereal.wrapperdefs import VULKAN_STREAM_TYPE_GUEST
25
26# CerealGenerator - generates set of driver sources
27# while being agnostic to the stream implementation
28from reg import GroupInfo, TypeInfo, EnumInfo
29
30copyrightHeader = """// Copyright (C) 2018 The Android Open Source Project
31// Copyright (C) 2018 Google Inc.
32//
33// Licensed under the Apache License, Version 2.0 (the "License");
34// you may not use this file except in compliance with the License.
35// You may obtain a copy of the License at
36//
37// http://www.apache.org/licenses/LICENSE-2.0
38//
39// Unless required by applicable law or agreed to in writing, software
40// distributed under the License is distributed on an "AS IS" BASIS,
41// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
42// See the License for the specific language governing permissions and
43// limitations under the License.
44"""
45
46# We put the long generated commands in a separate paragraph, so that the formatter won't mess up
47# with other texts.
48autogeneratedHeaderTemplate = """
49// Autogenerated module %s
50//
51// %s
52//
53// Please do not modify directly;
54// re-run gfxstream-protocols/scripts/generate-vulkan-sources.sh,
55// or directly from Python by defining:
56// VULKAN_REGISTRY_XML_DIR : Directory containing vk.xml
57// VULKAN_REGISTRY_SCRIPTS_DIR : Directory containing genvk.py
58// CEREAL_OUTPUT_DIR: Where to put the generated sources.
59//
60// python3 $VULKAN_REGISTRY_SCRIPTS_DIR/genvk.py -registry $VULKAN_REGISTRY_XML_DIR/vk.xml cereal -o $CEREAL_OUTPUT_DIR
61//
62"""
63
64autogeneratedMkTemplate = """
65# Autogenerated makefile
66# %s
67# Please do not modify directly;
68# re-run gfxstream-protocols/scripts/generate-vulkan-sources.sh,
69# or directly from Python by defining:
70# VULKAN_REGISTRY_XML_DIR : Directory containing vk.xml
71# VULKAN_REGISTRY_SCRIPTS_DIR : Directory containing genvk.py
72# CEREAL_OUTPUT_DIR: Where to put the generated sources.
73# python3 $VULKAN_REGISTRY_SCRIPTS_DIR/genvk.py -registry $VULKAN_REGISTRY_XML_DIR/vk.xml cereal -o $CEREAL_OUTPUT_DIR
74"""
75
76def banner_command(argv):
77    """Return sanitized command-line description.
78       |argv| must be a list of command-line parameters, e.g. sys.argv.
79       Return a string corresponding to the command, with platform-specific
80       paths removed."""
81
82    def makePosixRelative(someArg):
83        if os.path.exists(someArg):
84            return str(PurePosixPath(Path(os.path.relpath(someArg))))
85        return someArg
86
87    return ' '.join(map(makePosixRelative, argv))
88
89suppressEnabled = False
90suppressExceptModule = None
91
92def envGetOrDefault(key, default=None):
93    if key in os.environ:
94        return os.environ[key]
95    print("envGetOrDefault: notfound: %s" % key)
96    return default
97
98def init_suppress_option():
99    global suppressEnabled
100    global suppressExceptModule
101
102    if "ANDROID_EMU_VK_CEREAL_SUPPRESS" in os.environ:
103        option = os.environ["ANDROID_EMU_VK_CEREAL_SUPPRESS"]
104
105        if option != "":
106            suppressExceptModule = option
107            suppressEnabled = True
108            print("suppressEnabled: %s" % suppressExceptModule)
109
110# ---- methods overriding base class ----
111# beginFile(genOpts)
112# endFile()
113# beginFeature(interface, emit)
114# endFeature()
115# genType(typeinfo,name)
116# genStruct(typeinfo,name)
117# genGroup(groupinfo,name)
118# genEnum(enuminfo, name)
119# genCmd(cmdinfo)
120class CerealGenerator(OutputGenerator):
121
122    """Generate serialization code"""
123    def __init__(self, errFile = sys.stderr,
124                       warnFile = sys.stderr,
125                       diagFile = sys.stdout):
126        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
127
128        init_suppress_option()
129
130        self.typeInfo = cereal.VulkanTypeInfo(self)
131
132        self.modules = {}
133        self.protos = {}
134        self.moduleList = []
135        self.protoList = []
136
137        self.wrappers = []
138
139        self.codegen = cereal.CodeGen()
140
141        self.guestBaseLibDirPrefix = \
142            envGetOrDefault("VK_CEREAL_GUEST_BASELIB_PREFIX", "android/base")
143        self.baseLibDirPrefix = \
144            envGetOrDefault("VK_CEREAL_BASELIB_PREFIX", "android/base")
145        self.baseLibLinkName = \
146            envGetOrDefault("VK_CEREAL_BASELIB_LINKNAME", "android-emu-base")
147        self.vulkanHeaderTargetName = envGetOrDefault("VK_CEREAL_VK_HEADER_TARGET", "")
148
149        # THe host always needs all possible guest struct definitions, while the guest only needs
150        # platform sepcific headers.
151        self.hostCommonExtraVulkanHeaders = '#include "vk_android_native_buffer.h"'
152        self.host_cmake_generator = lambda cppFiles: f"""{autogeneratedMkTemplate % banner_command(sys.argv)}
153add_library(OpenglRender_vulkan_cereal {cppFiles})
154target_compile_definitions(OpenglRender_vulkan_cereal PRIVATE -DVK_GOOGLE_gfxstream)
155if (WIN32)
156    target_compile_definitions(OpenglRender_vulkan_cereal PRIVATE -DVK_USE_PLATFORM_WIN32_KHR)
157endif()
158target_link_libraries(OpenglRender_vulkan_cereal PUBLIC {self.baseLibLinkName} {self.vulkanHeaderTargetName})
159
160target_include_directories(OpenglRender_vulkan_cereal
161                           PUBLIC
162                           .
163                           PRIVATE
164                           ..
165                           ../..
166                           ../../../include)
167"""
168
169        encoderInclude = """
170#include "android/base/AndroidHealthMonitor.h"
171#include "goldfish_vk_private_defs.h"
172#include <memory>
173class IOStream;
174"""
175        encoderImplInclude = f"""
176#include "EncoderDebug.h"
177#include "IOStream.h"
178#include "Resources.h"
179#include "ResourceTracker.h"
180#include "Validation.h"
181#include "%s.h"
182
183#include "{self.guestBaseLibDirPrefix}/AlignedBuf.h"
184#include "{self.guestBaseLibDirPrefix}/BumpPool.h"
185#include "{self.guestBaseLibDirPrefix}/synchronization/AndroidLock.h"
186
187#include <cutils/properties.h>
188
189#include "goldfish_vk_marshaling_guest.h"
190#include "goldfish_vk_reserved_marshaling_guest.h"
191#include "goldfish_vk_deepcopy_guest.h"
192#include "goldfish_vk_counting_guest.h"
193#include "goldfish_vk_handlemap_guest.h"
194#include "goldfish_vk_private_defs.h"
195#include "goldfish_vk_transform_guest.h"
196
197#include <memory>
198#include <optional>
199#include <unordered_map>
200#include <string>
201#include <vector>
202
203""" % VULKAN_STREAM_TYPE_GUEST
204
205        functableImplInclude = """
206#include "VkEncoder.h"
207#include "../OpenglSystemCommon/HostConnection.h"
208#include "ResourceTracker.h"
209
210#include "goldfish_vk_private_defs.h"
211
212#include <log/log.h>
213#include <cstring>
214
215// Stuff we are not going to use but if included,
216// will cause compile errors. These are Android Vulkan
217// required extensions, but the approach will be to
218// implement them completely on the guest side.
219#undef VK_KHR_android_surface
220"""
221        marshalIncludeGuest = """
222#include "goldfish_vk_marshaling_guest.h"
223#include "goldfish_vk_private_defs.h"
224#include "%s.h"
225
226// Stuff we are not going to use but if included,
227// will cause compile errors. These are Android Vulkan
228// required extensions, but the approach will be to
229// implement them completely on the guest side.
230#undef VK_KHR_android_surface
231#undef VK_ANDROID_external_memory_android_hardware_buffer
232""" % VULKAN_STREAM_TYPE_GUEST
233
234        reservedmarshalIncludeGuest = """
235#include "goldfish_vk_marshaling_guest.h"
236#include "goldfish_vk_private_defs.h"
237#include "%s.h"
238
239// Stuff we are not going to use but if included,
240// will cause compile errors. These are Android Vulkan
241// required extensions, but the approach will be to
242// implement them completely on the guest side.
243#undef VK_KHR_android_surface
244#undef VK_ANDROID_external_memory_android_hardware_buffer
245""" % VULKAN_STREAM_TYPE_GUEST
246
247        reservedmarshalImplIncludeGuest = """
248#include "Resources.h"
249"""
250
251        vulkanStreamIncludeHost = f"""
252{self.hostCommonExtraVulkanHeaders}
253#include "goldfish_vk_private_defs.h"
254
255#include "%s.h"
256#include "{self.baseLibDirPrefix}/files/StreamSerializing.h"
257""" % VULKAN_STREAM_TYPE
258
259        testingInclude = f"""
260{self.hostCommonExtraVulkanHeaders}
261#include "goldfish_vk_private_defs.h"
262#include <string.h>
263#include <functional>
264using OnFailCompareFunc = std::function<void(const char*)>;
265"""
266        poolInclude = f"""
267{self.hostCommonExtraVulkanHeaders}
268#include "goldfish_vk_private_defs.h"
269#include "{self.baseLibDirPrefix}/BumpPool.h"
270using android::base::Allocator;
271using android::base::BumpPool;
272"""
273        handleMapInclude = f"""
274{self.hostCommonExtraVulkanHeaders}
275#include "goldfish_vk_private_defs.h"
276#include "VulkanHandleMapping.h"
277"""
278        transformIncludeGuest = """
279#include "goldfish_vk_private_defs.h"
280"""
281        transformInclude = f"""
282{self.hostCommonExtraVulkanHeaders}
283#include "goldfish_vk_private_defs.h"
284#include "goldfish_vk_extension_structs.h"
285"""
286        transformImplIncludeGuest = """
287#include "ResourceTracker.h"
288"""
289        transformImplInclude = """
290#include "VkDecoderGlobalState.h"
291"""
292        deepcopyInclude = """
293#include "vk_util.h"
294"""
295        poolIncludeGuest = f"""
296#include "goldfish_vk_private_defs.h"
297#include "{self.guestBaseLibDirPrefix}/BumpPool.h"
298using android::base::Allocator;
299using android::base::BumpPool;
300// Stuff we are not going to use but if included,
301// will cause compile errors. These are Android Vulkan
302// required extensions, but the approach will be to
303// implement them completely on the guest side.
304#undef VK_KHR_android_surface
305#undef VK_ANDROID_external_memory_android_hardware_buffer
306"""
307        handleMapIncludeGuest = """
308#include "goldfish_vk_private_defs.h"
309#include "VulkanHandleMapping.h"
310// Stuff we are not going to use but if included,
311// will cause compile errors. These are Android Vulkan
312// required extensions, but the approach will be to
313// implement them completely on the guest side.
314#undef VK_KHR_android_surface
315#undef VK_ANDROID_external_memory_android_hardware_buffer
316"""
317        dispatchHeaderDefs = f"""
318{self.hostCommonExtraVulkanHeaders}
319#include "goldfish_vk_private_defs.h"
320namespace goldfish_vk {{
321
322struct VulkanDispatch;
323
324}} // namespace goldfish_vk
325using DlOpenFunc = void* (void);
326using DlSymFunc = void* (void*, const char*);
327"""
328
329        extensionStructsInclude = f"""
330{self.hostCommonExtraVulkanHeaders}
331#include "goldfish_vk_private_defs.h"
332"""
333
334        extensionStructsIncludeGuest = """
335#include "vk_platform_compat.h"
336#include "goldfish_vk_private_defs.h"
337// Stuff we are not going to use but if included,
338// will cause compile errors. These are Android Vulkan
339// required extensions, but the approach will be to
340// implement them completely on the guest side.
341#undef VK_KHR_android_surface
342#undef VK_ANDROID_external_memory_android_hardware_buffer
343"""
344        commonCerealImplIncludes = """
345#include "goldfish_vk_extension_structs.h"
346#include "goldfish_vk_private_defs.h"
347#include <string.h>
348"""
349        commonCerealIncludesGuest = """
350#include "vk_platform_compat.h"
351"""
352        commonCerealImplIncludesGuest = """
353#include "goldfish_vk_extension_structs_guest.h"
354#include "goldfish_vk_private_defs.h"
355
356#include <cstring>
357"""
358        countingIncludes = """
359#include "vk_platform_compat.h"
360#include "goldfish_vk_private_defs.h"
361"""
362
363        dispatchImplIncludes = """
364#include <stdio.h>
365#include <stdlib.h>
366#include <string.h>
367"""
368
369        decoderSnapshotHeaderIncludes = f"""
370#include <memory>
371#include "{self.baseLibDirPrefix}/GfxApiLogger.h"
372#include "{self.baseLibDirPrefix}/HealthMonitor.h"
373#include "common/goldfish_vk_private_defs.h"
374"""
375        decoderSnapshotImplIncludes = f"""
376#include "VulkanHandleMapping.h"
377#include "VkDecoderGlobalState.h"
378#include "VkReconstruction.h"
379
380#include "{self.baseLibDirPrefix}/synchronization/Lock.h"
381"""
382
383        decoderHeaderIncludes = f"""
384#include "VkDecoderContext.h"
385
386#include <memory>
387
388namespace android {{
389namespace base {{
390class BumpPool;
391}} // namespace android
392}} // namespace base
393
394"""
395
396        decoderImplIncludes = f"""
397#include "common/goldfish_vk_marshaling.h"
398#include "common/goldfish_vk_reserved_marshaling.h"
399#include "common/goldfish_vk_private_defs.h"
400#include "common/goldfish_vk_transform.h"
401
402#include "{self.baseLibDirPrefix}/BumpPool.h"
403#include "{self.baseLibDirPrefix}/system/System.h"
404#include "{self.baseLibDirPrefix}/Tracing.h"
405#include "{self.baseLibDirPrefix}/Metrics.h"
406#include "stream-servers/IOStream.h"
407#include "host-common/feature_control.h"
408#include "host-common/GfxstreamFatalError.h"
409#include "host-common/logging.h"
410
411#include "VkDecoderGlobalState.h"
412#include "VkDecoderSnapshot.h"
413
414#include "VulkanDispatch.h"
415#include "%s.h"
416
417#include <functional>
418#include <optional>
419#include <unordered_map>
420""" % VULKAN_STREAM_TYPE
421
422        def createVkExtensionStructureTypePreamble(extensionName: str) -> str:
423            return f"""
424#define {extensionName}_ENUM(type,id) \
425    ((type)(1000000000 + (1000 * ({extensionName}_NUMBER - 1)) + (id)))
426"""
427        self.guest_encoder_tag = "guest_encoder"
428        self.guest_hal_tag = "guest_hal"
429        self.host_tag = "host"
430
431        default_guest_abs_encoder_destination = \
432            os.path.join(
433                os.getcwd(),
434                "..", "..",
435                "device", "generic", "goldfish-opengl",
436                "system", "vulkan_enc")
437        self.guest_abs_encoder_destination = \
438            envGetOrDefault("VK_CEREAL_GUEST_ENCODER_DIR",
439                            default_guest_abs_encoder_destination)
440
441        default_guest_abs_hal_destination = \
442            os.path.join(
443                os.getcwd(),
444                "..", "..",
445                "device", "generic", "goldfish-opengl",
446                "system", "vulkan")
447        self.guest_abs_hal_destination = \
448            envGetOrDefault("VK_CEREAL_GUEST_HAL_DIR",
449                            default_guest_abs_hal_destination)
450
451        default_host_abs_decoder_destination = \
452            os.path.join(
453                os.getcwd(),
454                "android", "android-emugl", "host",
455                "libs", "libOpenglRender", "vulkan")
456        self.host_abs_decoder_destination = \
457            envGetOrDefault("VK_CEREAL_HOST_DECODER_DIR",
458                            default_host_abs_decoder_destination)
459        self.host_script_destination = envGetOrDefault("VK_CEREAL_HOST_SCRIPTS_DIR")
460        assert(self.host_script_destination is not None)
461
462        self.addGuestEncoderModule(
463            "VkEncoder",
464            extraHeader = encoderInclude,
465            extraImpl = encoderImplInclude)
466
467        self.addGuestEncoderModule("goldfish_vk_extension_structs_guest",
468                                   extraHeader=extensionStructsIncludeGuest)
469        self.addGuestEncoderModule("goldfish_vk_marshaling_guest",
470                                   extraHeader=commonCerealIncludesGuest + marshalIncludeGuest,
471                                   extraImpl=commonCerealImplIncludesGuest)
472        self.addGuestEncoderModule("goldfish_vk_reserved_marshaling_guest",
473                                   extraHeader=commonCerealIncludesGuest + reservedmarshalIncludeGuest,
474                                   extraImpl=commonCerealImplIncludesGuest + reservedmarshalImplIncludeGuest)
475        self.addGuestEncoderModule("goldfish_vk_deepcopy_guest",
476                                   extraHeader=commonCerealIncludesGuest + poolIncludeGuest,
477                                   extraImpl=commonCerealImplIncludesGuest + deepcopyInclude)
478        self.addGuestEncoderModule("goldfish_vk_counting_guest",
479                                   extraHeader=countingIncludes,
480                                   extraImpl=commonCerealImplIncludesGuest)
481        self.addGuestEncoderModule("goldfish_vk_handlemap_guest",
482                                   extraHeader=commonCerealIncludesGuest + handleMapIncludeGuest,
483                                   extraImpl=commonCerealImplIncludesGuest)
484        self.addGuestEncoderModule("goldfish_vk_transform_guest",
485                                   extraHeader=commonCerealIncludesGuest + transformIncludeGuest,
486                                   extraImpl=commonCerealImplIncludesGuest + transformImplIncludeGuest)
487        self.addGuestEncoderModule(
488            "vulkan_gfxstream_structure_type", headerOnly=True, suppressFeatureGuards=True,
489            moduleName="vulkan_gfxstream_structure_type_guest", useNamespace=False,
490            suppressVulkanHeaders=True,
491            extraHeader=createVkExtensionStructureTypePreamble('VK_GOOGLE_GFXSTREAM'))
492
493        self.addGuestEncoderModule("func_table", extraImpl=functableImplInclude)
494
495        self.addCppModule("common", "goldfish_vk_extension_structs",
496                       extraHeader=extensionStructsInclude)
497        self.addCppModule("common", "goldfish_vk_marshaling",
498                       extraHeader=vulkanStreamIncludeHost,
499                       extraImpl=commonCerealImplIncludes)
500        self.addCppModule("common", "goldfish_vk_reserved_marshaling",
501                       extraHeader=vulkanStreamIncludeHost,
502                       extraImpl=commonCerealImplIncludes)
503        self.addCppModule("common", "goldfish_vk_testing",
504                       extraHeader=testingInclude,
505                       extraImpl=commonCerealImplIncludes)
506        self.addCppModule("common", "goldfish_vk_deepcopy",
507                       extraHeader=poolInclude,
508                       extraImpl=commonCerealImplIncludes + deepcopyInclude)
509        self.addCppModule("common", "goldfish_vk_handlemap",
510                       extraHeader=handleMapInclude,
511                       extraImpl=commonCerealImplIncludes)
512        self.addCppModule("common", "goldfish_vk_dispatch",
513                       extraHeader=dispatchHeaderDefs,
514                       extraImpl=dispatchImplIncludes)
515        self.addCppModule("common", "goldfish_vk_transform",
516                       extraHeader=transformInclude,
517                       extraImpl=transformImplInclude)
518        self.addHostModule("VkDecoder",
519                           extraHeader=decoderHeaderIncludes,
520                           extraImpl=decoderImplIncludes,
521                           useNamespace=False)
522        self.addHostModule("VkDecoderSnapshot",
523                           extraHeader=decoderSnapshotHeaderIncludes,
524                           extraImpl=decoderSnapshotImplIncludes,
525                           useNamespace=False)
526        self.addHostModule("VkSubDecoder",
527                           extraHeader="",
528                           extraImpl="",
529                           useNamespace=False,
530                           implOnly=True)
531
532        self.addModule(cereal.PyScript(self.host_tag, "vulkan_printer", customAbsDir=Path(
533            self.host_script_destination) / "print_gfx_logs"), moduleName="ApiLogDecoder")
534        self.addHostModule(
535            "vulkan_gfxstream_structure_type", headerOnly=True, suppressFeatureGuards=True,
536            moduleName="vulkan_gfxstream_structure_type_host", useNamespace=False,
537            suppressVulkanHeaders=True,
538            extraHeader=createVkExtensionStructureTypePreamble('VK_GOOGLE_GFXSTREAM'))
539        self.addHostModule(
540            "vk_android_native_buffer_structure_type", headerOnly=True, suppressFeatureGuards=True,
541            useNamespace=False, suppressVulkanHeaders=True,
542            extraHeader=createVkExtensionStructureTypePreamble('VK_ANDROID_NATIVE_BUFFER'))
543
544        self.addWrapper(cereal.VulkanEncoder, "VkEncoder")
545        self.addWrapper(cereal.VulkanExtensionStructs, "goldfish_vk_extension_structs_guest")
546        self.addWrapper(cereal.VulkanMarshaling, "goldfish_vk_marshaling_guest", variant = "guest")
547        self.addWrapper(cereal.VulkanReservedMarshaling, "goldfish_vk_reserved_marshaling_guest", variant = "guest")
548        self.addWrapper(cereal.VulkanDeepcopy, "goldfish_vk_deepcopy_guest")
549        self.addWrapper(cereal.VulkanCounting, "goldfish_vk_counting_guest")
550        self.addWrapper(cereal.VulkanHandleMap, "goldfish_vk_handlemap_guest")
551        self.addWrapper(cereal.VulkanTransform, "goldfish_vk_transform_guest")
552        self.addWrapper(cereal.VulkanFuncTable, "func_table")
553        self.addWrapper(cereal.VulkanExtensionStructs, "goldfish_vk_extension_structs")
554        self.addWrapper(cereal.VulkanMarshaling, "goldfish_vk_marshaling")
555        self.addWrapper(cereal.VulkanReservedMarshaling, "goldfish_vk_reserved_marshaling", variant = "host")
556        self.addWrapper(cereal.VulkanTesting, "goldfish_vk_testing")
557        self.addWrapper(cereal.VulkanDeepcopy, "goldfish_vk_deepcopy")
558        self.addWrapper(cereal.VulkanHandleMap, "goldfish_vk_handlemap")
559        self.addWrapper(cereal.VulkanDispatch, "goldfish_vk_dispatch")
560        self.addWrapper(cereal.VulkanTransform, "goldfish_vk_transform", resourceTrackerTypeName="VkDecoderGlobalState")
561        self.addWrapper(cereal.VulkanDecoder, "VkDecoder")
562        self.addWrapper(cereal.VulkanDecoderSnapshot, "VkDecoderSnapshot")
563        self.addWrapper(cereal.VulkanSubDecoder, "VkSubDecoder")
564        self.addWrapper(cereal.ApiLogDecoder, "ApiLogDecoder")
565        self.addWrapper(cereal.VulkanGfxstreamStructureType,
566                        "vulkan_gfxstream_structure_type_guest")
567        self.addWrapper(cereal.VulkanGfxstreamStructureType, "vulkan_gfxstream_structure_type_host")
568        self.addWrapper(cereal.VulkanAndroidNativeBufferStructureType,
569                        "vk_android_native_buffer_structure_type")
570
571        self.guestAndroidMkCppFiles = ""
572        self.hostCMakeCppFiles = ""
573        self.hostDecoderCMakeCppFiles = ""
574
575        def addSrcEntry(m):
576            mkSrcEntry = m.getMakefileSrcEntry()
577            cmakeSrcEntry = m.getCMakeSrcEntry()
578            if m.directory == self.guest_encoder_tag:
579                self.guestAndroidMkCppFiles += mkSrcEntry
580            elif m.directory == self.host_tag:
581                self.hostDecoderCMakeCppFiles += cmakeSrcEntry
582            elif m.directory != self.guest_hal_tag:
583                self.hostCMakeCppFiles += cmakeSrcEntry
584
585        self.forEachModule(addSrcEntry)
586
587    def addGuestEncoderModule(
588            self, basename, extraHeader="", extraImpl="", useNamespace=True, headerOnly=False,
589            suppressFeatureGuards=False, moduleName=None, suppressVulkanHeaders=False):
590        if not os.path.exists(self.guest_abs_encoder_destination):
591            print("Path [%s] not found (guest encoder path), skipping" % self.guest_abs_encoder_destination)
592            return
593        self.addCppModule(self.guest_encoder_tag, basename, extraHeader=extraHeader,
594                       extraImpl=extraImpl, customAbsDir=self.guest_abs_encoder_destination,
595                       useNamespace=useNamespace, headerOnly=headerOnly,
596                       suppressFeatureGuards=suppressFeatureGuards, moduleName=moduleName,
597                       suppressVulkanHeaders=suppressVulkanHeaders)
598
599    def addGuestHalModule(self, basename, extraHeader = "", extraImpl = "", useNamespace = True):
600        if not os.path.exists(self.guest_abs_hal_destination):
601            print("Path [%s] not found (guest encoder path), skipping" % self.guest_abs_encoder_destination)
602            return
603        self.addCppModule(self.guest_hal_tag,
604                       basename,
605                       extraHeader = extraHeader,
606                       extraImpl = extraImpl,
607                       customAbsDir = self.guest_abs_hal_destination,
608                       useNamespace = useNamespace)
609
610    def addHostModule(
611            self, basename, extraHeader="", extraImpl="", useNamespace=True, implOnly=False,
612            suppress=False, headerOnly=False, suppressFeatureGuards=False, moduleName=None,
613            suppressVulkanHeaders=False):
614        if not os.path.exists(self.host_abs_decoder_destination):
615            print("Path [%s] not found (host encoder path), skipping" %
616                  self.host_abs_decoder_destination)
617            return
618        if not suppressVulkanHeaders:
619            extraHeader = self.hostCommonExtraVulkanHeaders + '\n' + extraHeader
620        self.addCppModule(
621            self.host_tag, basename, extraHeader=extraHeader, extraImpl=extraImpl,
622            customAbsDir=self.host_abs_decoder_destination, useNamespace=useNamespace,
623            implOnly=implOnly, suppress=suppress, headerOnly=headerOnly,
624            suppressFeatureGuards=suppressFeatureGuards, moduleName=moduleName,
625            suppressVulkanHeaders=suppressVulkanHeaders)
626
627    def addModule(self, module, moduleName=None):
628        if moduleName is None:
629            moduleName = module.basename
630        self.moduleList.append(moduleName)
631        self.modules[moduleName] = module
632
633    def addCppModule(
634            self, directory, basename, extraHeader="", extraImpl="", customAbsDir=None,
635            useNamespace=True, implOnly=False, suppress=False, headerOnly=False,
636            suppressFeatureGuards=False, moduleName=None, suppressVulkanHeaders=False):
637        module = cereal.Module(
638            directory, basename, customAbsDir=customAbsDir, suppress=suppress, implOnly=implOnly,
639            headerOnly=headerOnly, suppressFeatureGuards=suppressFeatureGuards)
640        self.addModule(module, moduleName=moduleName)
641        module.headerPreamble = copyrightHeader
642        module.headerPreamble += \
643                autogeneratedHeaderTemplate % \
644                (basename, "(header) generated by %s" % banner_command(sys.argv))
645
646        namespaceBegin = "namespace goldfish_vk {" if useNamespace else ""
647        namespaceEnd = "} // namespace goldfish_vk" if useNamespace else ""
648
649        module.headerPreamble += "#pragma once\n"
650        if (not suppressVulkanHeaders):
651            module.headerPreamble += "#include <vulkan/vulkan.h>\n"
652            module.headerPreamble += '#include "vulkan_gfxstream.h"\n'
653        module.headerPreamble += extraHeader + '\n'
654        if namespaceBegin:
655            module.headerPreamble += namespaceBegin + '\n'
656
657        module.implPreamble = copyrightHeader
658        module.implPreamble += \
659                autogeneratedHeaderTemplate % \
660                (basename, "(impl) generated by %s" % \
661                    banner_command(sys.argv))
662        if not implOnly:
663            module.implPreamble += """
664#include "%s.h"
665
666%s
667
668%s
669
670""" % (basename, extraImpl, namespaceBegin)
671
672        module.headerPostamble = """
673%s
674""" % namespaceEnd
675        module.implPostamble = """
676%s
677""" % namespaceEnd
678
679    def addWrapper(self, moduleType, moduleName, **kwargs):
680        if moduleName not in self.modules:
681            print(f'Unknown module: {moduleName}. All known modules are: {", ".join(self.modules)}.')
682            return
683        self.wrappers.append(
684            moduleType(
685                self.modules[moduleName],
686                self.typeInfo, **kwargs))
687
688    def forEachModule(self, func):
689        for moduleName in self.moduleList:
690            func(self.modules[moduleName])
691
692    def forEachWrapper(self, func):
693        for wrapper in self.wrappers:
694            func(wrapper)
695
696## Overrides####################################################################
697
698    def beginFile(self, genOpts):
699        OutputGenerator.beginFile(self, genOpts, suppressEnabled)
700
701        if suppressEnabled:
702            def enableSuppression(m):
703                m.suppress = True
704            self.forEachModule(enableSuppression)
705            self.modules[suppressExceptModule].suppress = False
706
707        if not suppressEnabled:
708            write(self.host_cmake_generator(self.hostCMakeCppFiles),
709                  file = self.outFile)
710
711            guestEncoderAndroidMkPath = \
712                os.path.join( \
713                    self.guest_abs_encoder_destination,
714                    "Android.mk")
715
716        self.forEachModule(lambda m: m.begin(self.genOpts.directory))
717        self.forEachWrapper(lambda w: w.onBegin())
718
719    def endFile(self):
720        OutputGenerator.endFile(self)
721
722        self.typeInfo.onEnd()
723
724        self.forEachWrapper(lambda w: w.onEnd())
725        self.forEachModule(lambda m: m.end())
726
727    def beginFeature(self, interface, emit):
728        # Start processing in superclass
729        OutputGenerator.beginFeature(self, interface, emit)
730
731        self.typeInfo.onBeginFeature(self.featureName, self.featureType)
732
733        self.forEachModule(
734            lambda m: m.appendHeader("#ifdef %s\n" % self.featureName)
735            if isinstance(m, cereal.Module) and not m.suppressFeatureGuards else None)
736        self.forEachModule(
737            lambda m: m.appendImpl("#ifdef %s\n" % self.featureName)
738            if isinstance(m, cereal.Module) and not m.suppressFeatureGuards else None)
739        self.forEachWrapper(lambda w: w.onBeginFeature(self.featureName, self.featureType))
740        # functable needs to understand the feature type (device vs instance) of each cmd
741        for features in interface.findall('require'):
742            for c in features.findall('command'):
743                self.forEachWrapper(lambda w: w.onFeatureNewCmd(c.get('name')))
744
745    def endFeature(self):
746        # Finish processing in superclass
747        OutputGenerator.endFeature(self)
748
749        self.typeInfo.onEndFeature()
750
751        self.forEachModule(lambda m: m.appendHeader("#endif\n") if isinstance(
752            m, cereal.Module) and not m.suppressFeatureGuards else None)
753        self.forEachModule(lambda m: m.appendImpl("#endif\n") if isinstance(
754            m, cereal.Module) and not m.suppressFeatureGuards else None)
755        self.forEachWrapper(lambda w: w.onEndFeature())
756
757    def genType(self, typeinfo: TypeInfo, name, alias):
758        OutputGenerator.genType(self, typeinfo, name, alias)
759        self.typeInfo.onGenType(typeinfo, name, alias)
760        self.forEachWrapper(lambda w: w.onGenType(typeinfo, name, alias))
761
762    def genStruct(self, typeinfo, typeName, alias):
763        OutputGenerator.genStruct(self, typeinfo, typeName, alias)
764        self.typeInfo.onGenStruct(typeinfo, typeName, alias)
765        self.forEachWrapper(lambda w: w.onGenStruct(typeinfo, typeName, alias))
766
767    def genGroup(self, groupinfo: GroupInfo, groupName, alias = None):
768        OutputGenerator.genGroup(self, groupinfo, groupName, alias)
769        self.typeInfo.onGenGroup(groupinfo, groupName, alias)
770        self.forEachWrapper(lambda w: w.onGenGroup(groupinfo, groupName, alias))
771
772    def genEnum(self, enuminfo: EnumInfo, name, alias):
773        OutputGenerator.genEnum(self, enuminfo, name, alias)
774        self.typeInfo.onGenEnum(enuminfo, name, alias)
775        self.forEachWrapper(lambda w: w.onGenEnum(enuminfo, name, alias))
776
777    def genCmd(self, cmdinfo, name, alias):
778        OutputGenerator.genCmd(self, cmdinfo, name, alias)
779        self.typeInfo.onGenCmd(cmdinfo, name, alias)
780        self.forEachWrapper(lambda w: w.onGenCmd(cmdinfo, name, alias))
781