• 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", "aemu/base")
143        self.baseLibDirPrefix = \
144            envGetOrDefault("VK_CEREAL_BASELIB_PREFIX", "aemu/base")
145        self.baseLibLinkName = \
146            envGetOrDefault("VK_CEREAL_BASELIB_LINKNAME", "android-emu-base")
147        self.vulkanHeaderTargetName = envGetOrDefault("VK_CEREAL_VK_HEADER_TARGET", "")
148        self.utilsHeader = envGetOrDefault("VK_CEREAL_UTILS_LINKNAME", "")
149        self.utilsHeaderDirPrefix = envGetOrDefault("VK_CEREAL_UTILS_PREFIX", "utils")
150
151        # THe host always needs all possible guest struct definitions, while the guest only needs
152        # platform sepcific headers.
153        self.hostCommonExtraVulkanHeaders = '#include "vk_android_native_buffer.h"'
154        self.host_cmake_generator = lambda cppFiles: f"""{autogeneratedMkTemplate % banner_command(sys.argv)}
155add_library(OpenglRender_vulkan_cereal {cppFiles})
156target_compile_definitions(OpenglRender_vulkan_cereal PRIVATE -DVK_GOOGLE_gfxstream)
157if (WIN32)
158    target_compile_definitions(OpenglRender_vulkan_cereal PRIVATE -DVK_USE_PLATFORM_WIN32_KHR)
159endif()
160target_link_libraries(
161    OpenglRender_vulkan_cereal
162    PUBLIC
163    {self.baseLibLinkName}
164    {self.vulkanHeaderTargetName}
165    PRIVATE
166    {self.utilsHeader})
167
168target_include_directories(OpenglRender_vulkan_cereal
169                           PUBLIC
170                           .
171                           PRIVATE
172                           ..
173                           ../..
174                           ../../../include)
175"""
176
177        encoderInclude = f"""
178#include "{self.guestBaseLibDirPrefix}/AndroidHealthMonitor.h"
179#include "goldfish_vk_private_defs.h"
180#include <memory>
181class IOStream;
182"""
183        encoderImplInclude = f"""
184#include "EncoderDebug.h"
185#include "IOStream.h"
186#include "Resources.h"
187#include "ResourceTracker.h"
188#include "Validation.h"
189#include "%s.h"
190
191#include "{self.guestBaseLibDirPrefix}/AlignedBuf.h"
192#include "{self.guestBaseLibDirPrefix}/BumpPool.h"
193#include "{self.guestBaseLibDirPrefix}/synchronization/AndroidLock.h"
194
195#include <cutils/properties.h>
196
197#include "goldfish_vk_marshaling_guest.h"
198#include "goldfish_vk_reserved_marshaling_guest.h"
199#include "goldfish_vk_deepcopy_guest.h"
200#include "goldfish_vk_counting_guest.h"
201#include "goldfish_vk_handlemap_guest.h"
202#include "goldfish_vk_private_defs.h"
203#include "goldfish_vk_transform_guest.h"
204
205#include <memory>
206#include <optional>
207#include <unordered_map>
208#include <string>
209#include <vector>
210
211""" % VULKAN_STREAM_TYPE_GUEST
212
213        functableImplInclude = """
214#include "VkEncoder.h"
215#include "../OpenglSystemCommon/HostConnection.h"
216#include "ResourceTracker.h"
217
218#include "goldfish_vk_private_defs.h"
219
220#include <log/log.h>
221#include <cstring>
222
223// Stuff we are not going to use but if included,
224// will cause compile errors. These are Android Vulkan
225// required extensions, but the approach will be to
226// implement them completely on the guest side.
227#undef VK_KHR_android_surface
228"""
229        marshalIncludeGuest = """
230#include "goldfish_vk_marshaling_guest.h"
231#include "goldfish_vk_private_defs.h"
232#include "%s.h"
233
234// Stuff we are not going to use but if included,
235// will cause compile errors. These are Android Vulkan
236// required extensions, but the approach will be to
237// implement them completely on the guest side.
238#undef VK_KHR_android_surface
239#undef VK_ANDROID_external_memory_android_hardware_buffer
240""" % VULKAN_STREAM_TYPE_GUEST
241
242        reservedmarshalIncludeGuest = """
243#include "goldfish_vk_marshaling_guest.h"
244#include "goldfish_vk_private_defs.h"
245#include "%s.h"
246
247// Stuff we are not going to use but if included,
248// will cause compile errors. These are Android Vulkan
249// required extensions, but the approach will be to
250// implement them completely on the guest side.
251#undef VK_KHR_android_surface
252#undef VK_ANDROID_external_memory_android_hardware_buffer
253""" % VULKAN_STREAM_TYPE_GUEST
254
255        reservedmarshalImplIncludeGuest = """
256#include "Resources.h"
257"""
258
259        vulkanStreamIncludeHost = f"""
260{self.hostCommonExtraVulkanHeaders}
261#include "goldfish_vk_private_defs.h"
262
263#include "%s.h"
264#include "{self.baseLibDirPrefix}/files/StreamSerializing.h"
265""" % VULKAN_STREAM_TYPE
266
267        testingInclude = f"""
268{self.hostCommonExtraVulkanHeaders}
269#include "goldfish_vk_private_defs.h"
270#include <string.h>
271#include <functional>
272using OnFailCompareFunc = std::function<void(const char*)>;
273"""
274        poolInclude = f"""
275{self.hostCommonExtraVulkanHeaders}
276#include "goldfish_vk_private_defs.h"
277#include "{self.baseLibDirPrefix}/BumpPool.h"
278using android::base::Allocator;
279using android::base::BumpPool;
280"""
281        handleMapInclude = f"""
282{self.hostCommonExtraVulkanHeaders}
283#include "goldfish_vk_private_defs.h"
284#include "VulkanHandleMapping.h"
285"""
286        transformIncludeGuest = """
287#include "goldfish_vk_private_defs.h"
288"""
289        transformInclude = f"""
290{self.hostCommonExtraVulkanHeaders}
291#include "goldfish_vk_private_defs.h"
292#include "goldfish_vk_extension_structs.h"
293"""
294        transformImplIncludeGuest = """
295#include "ResourceTracker.h"
296"""
297        transformImplInclude = """
298#include "VkDecoderGlobalState.h"
299"""
300        deepcopyInclude = """
301#include "vk_util.h"
302"""
303        poolIncludeGuest = f"""
304#include "goldfish_vk_private_defs.h"
305#include "{self.guestBaseLibDirPrefix}/BumpPool.h"
306using android::base::Allocator;
307using android::base::BumpPool;
308// Stuff we are not going to use but if included,
309// will cause compile errors. These are Android Vulkan
310// required extensions, but the approach will be to
311// implement them completely on the guest side.
312#undef VK_KHR_android_surface
313#undef VK_ANDROID_external_memory_android_hardware_buffer
314"""
315        handleMapIncludeGuest = """
316#include "goldfish_vk_private_defs.h"
317#include "VulkanHandleMapping.h"
318// Stuff we are not going to use but if included,
319// will cause compile errors. These are Android Vulkan
320// required extensions, but the approach will be to
321// implement them completely on the guest side.
322#undef VK_KHR_android_surface
323#undef VK_ANDROID_external_memory_android_hardware_buffer
324"""
325        dispatchHeaderDefs = f"""
326{self.hostCommonExtraVulkanHeaders}
327#include "goldfish_vk_private_defs.h"
328namespace gfxstream {{
329namespace vk {{
330
331struct VulkanDispatch;
332
333}} // namespace vk
334}} // namespace gfxstream
335using DlOpenFunc = void* (void);
336using DlSymFunc = void* (void*, const char*);
337"""
338
339        extensionStructsInclude = f"""
340{self.hostCommonExtraVulkanHeaders}
341#include "goldfish_vk_private_defs.h"
342"""
343
344        extensionStructsIncludeGuest = """
345#include "vk_platform_compat.h"
346#include "goldfish_vk_private_defs.h"
347// Stuff we are not going to use but if included,
348// will cause compile errors. These are Android Vulkan
349// required extensions, but the approach will be to
350// implement them completely on the guest side.
351#undef VK_KHR_android_surface
352#undef VK_ANDROID_external_memory_android_hardware_buffer
353"""
354        commonCerealImplIncludes = """
355#include "goldfish_vk_extension_structs.h"
356#include "goldfish_vk_private_defs.h"
357#include <string.h>
358"""
359        commonCerealIncludesGuest = """
360#include "vk_platform_compat.h"
361"""
362        commonCerealImplIncludesGuest = """
363#include "goldfish_vk_extension_structs_guest.h"
364#include "goldfish_vk_private_defs.h"
365
366#include <cstring>
367"""
368        countingIncludes = """
369#include "vk_platform_compat.h"
370#include "goldfish_vk_private_defs.h"
371"""
372
373        dispatchImplIncludes = """
374#include <stdio.h>
375#include <stdlib.h>
376#include <string.h>
377"""
378
379        decoderSnapshotHeaderIncludes = f"""
380#include <memory>
381#include "{self.utilsHeaderDirPrefix}/GfxApiLogger.h"
382#include "{self.baseLibDirPrefix}/HealthMonitor.h"
383#include "common/goldfish_vk_private_defs.h"
384"""
385        decoderSnapshotImplIncludes = f"""
386#include "VulkanHandleMapping.h"
387#include "VkDecoderGlobalState.h"
388#include "VkReconstruction.h"
389
390#include "{self.baseLibDirPrefix}/synchronization/Lock.h"
391"""
392
393        decoderHeaderIncludes = f"""
394#include "VkDecoderContext.h"
395
396#include <memory>
397
398namespace android {{
399namespace base {{
400class BumpPool;
401}} // namespace android
402}} // namespace base
403
404"""
405
406        decoderImplIncludes = f"""
407#include "common/goldfish_vk_marshaling.h"
408#include "common/goldfish_vk_reserved_marshaling.h"
409#include "common/goldfish_vk_private_defs.h"
410#include "common/goldfish_vk_transform.h"
411
412#include "{self.baseLibDirPrefix}/BumpPool.h"
413#include "{self.baseLibDirPrefix}/system/System.h"
414#include "{self.baseLibDirPrefix}/Tracing.h"
415#include "{self.baseLibDirPrefix}/Metrics.h"
416#include "stream-servers/FrameBuffer.h"
417#include "stream-servers/IOStream.h"
418#include "host-common/feature_control.h"
419#include "host-common/GfxstreamFatalError.h"
420#include "host-common/logging.h"
421
422#include "VkDecoderGlobalState.h"
423#include "VkDecoderSnapshot.h"
424
425#include "VulkanDispatch.h"
426#include "%s.h"
427
428#include <functional>
429#include <optional>
430#include <unordered_map>
431""" % VULKAN_STREAM_TYPE
432
433        def createVkExtensionStructureTypePreamble(extensionName: str) -> str:
434            return f"""
435#define {extensionName}_ENUM(type,id) \
436    ((type)(1000000000 + (1000 * ({extensionName}_NUMBER - 1)) + (id)))
437"""
438        self.guest_encoder_tag = "guest_encoder"
439        self.guest_hal_tag = "guest_hal"
440        self.host_tag = "host"
441
442        default_guest_abs_encoder_destination = \
443            os.path.join(
444                os.getcwd(),
445                "..", "..",
446                "device", "generic", "goldfish-opengl",
447                "system", "vulkan_enc")
448        self.guest_abs_encoder_destination = \
449            envGetOrDefault("VK_CEREAL_GUEST_ENCODER_DIR",
450                            default_guest_abs_encoder_destination)
451
452        default_guest_abs_hal_destination = \
453            os.path.join(
454                os.getcwd(),
455                "..", "..",
456                "device", "generic", "goldfish-opengl",
457                "system", "vulkan")
458        self.guest_abs_hal_destination = \
459            envGetOrDefault("VK_CEREAL_GUEST_HAL_DIR",
460                            default_guest_abs_hal_destination)
461
462        default_host_abs_decoder_destination = \
463            os.path.join(
464                os.getcwd(),
465                "android", "android-emugl", "host",
466                "libs", "libOpenglRender", "vulkan")
467        self.host_abs_decoder_destination = \
468            envGetOrDefault("VK_CEREAL_HOST_DECODER_DIR",
469                            default_host_abs_decoder_destination)
470        self.host_script_destination = envGetOrDefault("VK_CEREAL_HOST_SCRIPTS_DIR")
471        assert(self.host_script_destination is not None)
472
473        self.addGuestEncoderModule(
474            "VkEncoder",
475            extraHeader = encoderInclude,
476            extraImpl = encoderImplInclude)
477
478        self.addGuestEncoderModule("goldfish_vk_extension_structs_guest",
479                                   extraHeader=extensionStructsIncludeGuest)
480        self.addGuestEncoderModule("goldfish_vk_marshaling_guest",
481                                   extraHeader=commonCerealIncludesGuest + marshalIncludeGuest,
482                                   extraImpl=commonCerealImplIncludesGuest)
483        self.addGuestEncoderModule("goldfish_vk_reserved_marshaling_guest",
484                                   extraHeader=commonCerealIncludesGuest + reservedmarshalIncludeGuest,
485                                   extraImpl=commonCerealImplIncludesGuest + reservedmarshalImplIncludeGuest)
486        self.addGuestEncoderModule("goldfish_vk_deepcopy_guest",
487                                   extraHeader=commonCerealIncludesGuest + poolIncludeGuest,
488                                   extraImpl=commonCerealImplIncludesGuest + deepcopyInclude)
489        self.addGuestEncoderModule("goldfish_vk_counting_guest",
490                                   extraHeader=countingIncludes,
491                                   extraImpl=commonCerealImplIncludesGuest)
492        self.addGuestEncoderModule("goldfish_vk_handlemap_guest",
493                                   extraHeader=commonCerealIncludesGuest + handleMapIncludeGuest,
494                                   extraImpl=commonCerealImplIncludesGuest)
495        self.addGuestEncoderModule("goldfish_vk_transform_guest",
496                                   extraHeader=commonCerealIncludesGuest + transformIncludeGuest,
497                                   extraImpl=commonCerealImplIncludesGuest + transformImplIncludeGuest)
498        self.addGuestEncoderModule(
499            "vulkan_gfxstream_structure_type", headerOnly=True, suppressFeatureGuards=True,
500            moduleName="vulkan_gfxstream_structure_type_guest", useNamespace=False,
501            suppressVulkanHeaders=True,
502            extraHeader=createVkExtensionStructureTypePreamble('VK_GOOGLE_GFXSTREAM'))
503
504        self.addGuestEncoderModule("func_table", extraImpl=functableImplInclude)
505
506        self.addCppModule("common", "goldfish_vk_extension_structs",
507                       extraHeader=extensionStructsInclude)
508        self.addCppModule("common", "goldfish_vk_marshaling",
509                       extraHeader=vulkanStreamIncludeHost,
510                       extraImpl=commonCerealImplIncludes)
511        self.addCppModule("common", "goldfish_vk_reserved_marshaling",
512                       extraHeader=vulkanStreamIncludeHost,
513                       extraImpl=commonCerealImplIncludes)
514        self.addCppModule("common", "goldfish_vk_testing",
515                       extraHeader=testingInclude,
516                       extraImpl=commonCerealImplIncludes)
517        self.addCppModule("common", "goldfish_vk_deepcopy",
518                       extraHeader=poolInclude,
519                       extraImpl=commonCerealImplIncludes + deepcopyInclude)
520        self.addCppModule("common", "goldfish_vk_handlemap",
521                       extraHeader=handleMapInclude,
522                       extraImpl=commonCerealImplIncludes)
523        self.addCppModule("common", "goldfish_vk_dispatch",
524                       extraHeader=dispatchHeaderDefs,
525                       extraImpl=dispatchImplIncludes)
526        self.addCppModule("common", "goldfish_vk_transform",
527                       extraHeader=transformInclude,
528                       extraImpl=transformImplInclude)
529        self.addHostModule("VkDecoder",
530                           extraHeader=decoderHeaderIncludes,
531                           extraImpl=decoderImplIncludes,
532                           useNamespace=False)
533        self.addHostModule("VkDecoderSnapshot",
534                           extraHeader=decoderSnapshotHeaderIncludes,
535                           extraImpl=decoderSnapshotImplIncludes,
536                           useNamespace=False)
537        self.addHostModule("VkSubDecoder",
538                           extraHeader="",
539                           extraImpl="",
540                           useNamespace=False,
541                           implOnly=True)
542
543        self.addModule(cereal.PyScript(self.host_tag, "vulkan_printer", customAbsDir=Path(
544            self.host_script_destination) / "print_gfx_logs"), moduleName="ApiLogDecoder")
545        self.addHostModule(
546            "vulkan_gfxstream_structure_type", headerOnly=True, suppressFeatureGuards=True,
547            moduleName="vulkan_gfxstream_structure_type_host", useNamespace=False,
548            suppressVulkanHeaders=True,
549            extraHeader=createVkExtensionStructureTypePreamble('VK_GOOGLE_GFXSTREAM'))
550        self.addHostModule(
551            "vk_android_native_buffer_structure_type", headerOnly=True, suppressFeatureGuards=True,
552            useNamespace=False, suppressVulkanHeaders=True,
553            extraHeader=createVkExtensionStructureTypePreamble('VK_ANDROID_NATIVE_BUFFER'))
554
555        self.addWrapper(cereal.VulkanEncoder, "VkEncoder")
556        self.addWrapper(cereal.VulkanExtensionStructs, "goldfish_vk_extension_structs_guest")
557        self.addWrapper(cereal.VulkanMarshaling, "goldfish_vk_marshaling_guest", variant = "guest")
558        self.addWrapper(cereal.VulkanReservedMarshaling, "goldfish_vk_reserved_marshaling_guest", variant = "guest")
559        self.addWrapper(cereal.VulkanDeepcopy, "goldfish_vk_deepcopy_guest")
560        self.addWrapper(cereal.VulkanCounting, "goldfish_vk_counting_guest")
561        self.addWrapper(cereal.VulkanHandleMap, "goldfish_vk_handlemap_guest")
562        self.addWrapper(cereal.VulkanTransform, "goldfish_vk_transform_guest")
563        self.addWrapper(cereal.VulkanFuncTable, "func_table")
564        self.addWrapper(cereal.VulkanExtensionStructs, "goldfish_vk_extension_structs")
565        self.addWrapper(cereal.VulkanMarshaling, "goldfish_vk_marshaling")
566        self.addWrapper(cereal.VulkanReservedMarshaling, "goldfish_vk_reserved_marshaling", variant = "host")
567        self.addWrapper(cereal.VulkanTesting, "goldfish_vk_testing")
568        self.addWrapper(cereal.VulkanDeepcopy, "goldfish_vk_deepcopy")
569        self.addWrapper(cereal.VulkanHandleMap, "goldfish_vk_handlemap")
570        self.addWrapper(cereal.VulkanDispatch, "goldfish_vk_dispatch")
571        self.addWrapper(cereal.VulkanTransform, "goldfish_vk_transform", resourceTrackerTypeName="VkDecoderGlobalState")
572        self.addWrapper(cereal.VulkanDecoder, "VkDecoder")
573        self.addWrapper(cereal.VulkanDecoderSnapshot, "VkDecoderSnapshot")
574        self.addWrapper(cereal.VulkanSubDecoder, "VkSubDecoder")
575        self.addWrapper(cereal.ApiLogDecoder, "ApiLogDecoder")
576        self.addWrapper(cereal.VulkanGfxstreamStructureType,
577                        "vulkan_gfxstream_structure_type_guest")
578        self.addWrapper(cereal.VulkanGfxstreamStructureType, "vulkan_gfxstream_structure_type_host")
579        self.addWrapper(cereal.VulkanAndroidNativeBufferStructureType,
580                        "vk_android_native_buffer_structure_type")
581
582        self.guestAndroidMkCppFiles = ""
583        self.hostCMakeCppFiles = ""
584        self.hostDecoderCMakeCppFiles = ""
585
586        def addSrcEntry(m):
587            mkSrcEntry = m.getMakefileSrcEntry()
588            cmakeSrcEntry = m.getCMakeSrcEntry()
589            if m.directory == self.guest_encoder_tag:
590                self.guestAndroidMkCppFiles += mkSrcEntry
591            elif m.directory == self.host_tag:
592                self.hostDecoderCMakeCppFiles += cmakeSrcEntry
593            elif m.directory != self.guest_hal_tag:
594                self.hostCMakeCppFiles += cmakeSrcEntry
595
596        self.forEachModule(addSrcEntry)
597
598    def addGuestEncoderModule(
599            self, basename, extraHeader="", extraImpl="", useNamespace=True, headerOnly=False,
600            suppressFeatureGuards=False, moduleName=None, suppressVulkanHeaders=False):
601        if not os.path.exists(self.guest_abs_encoder_destination):
602            print("Path [%s] not found (guest encoder path), skipping" % self.guest_abs_encoder_destination)
603            return
604        self.addCppModule(self.guest_encoder_tag, basename, extraHeader=extraHeader,
605                       extraImpl=extraImpl, customAbsDir=self.guest_abs_encoder_destination,
606                       useNamespace=useNamespace, headerOnly=headerOnly,
607                       suppressFeatureGuards=suppressFeatureGuards, moduleName=moduleName,
608                       suppressVulkanHeaders=suppressVulkanHeaders)
609
610    def addGuestHalModule(self, basename, extraHeader = "", extraImpl = "", useNamespace = True):
611        if not os.path.exists(self.guest_abs_hal_destination):
612            print("Path [%s] not found (guest encoder path), skipping" % self.guest_abs_encoder_destination)
613            return
614        self.addCppModule(self.guest_hal_tag,
615                       basename,
616                       extraHeader = extraHeader,
617                       extraImpl = extraImpl,
618                       customAbsDir = self.guest_abs_hal_destination,
619                       useNamespace = useNamespace)
620
621    def addHostModule(
622            self, basename, extraHeader="", extraImpl="", useNamespace=True, implOnly=False,
623            suppress=False, headerOnly=False, suppressFeatureGuards=False, moduleName=None,
624            suppressVulkanHeaders=False):
625        if not os.path.exists(self.host_abs_decoder_destination):
626            print("Path [%s] not found (host encoder path), skipping" %
627                  self.host_abs_decoder_destination)
628            return
629        if not suppressVulkanHeaders:
630            extraHeader = self.hostCommonExtraVulkanHeaders + '\n' + extraHeader
631        self.addCppModule(
632            self.host_tag, basename, extraHeader=extraHeader, extraImpl=extraImpl,
633            customAbsDir=self.host_abs_decoder_destination, useNamespace=useNamespace,
634            implOnly=implOnly, suppress=suppress, headerOnly=headerOnly,
635            suppressFeatureGuards=suppressFeatureGuards, moduleName=moduleName,
636            suppressVulkanHeaders=suppressVulkanHeaders)
637
638    def addModule(self, module, moduleName=None):
639        if moduleName is None:
640            moduleName = module.basename
641        self.moduleList.append(moduleName)
642        self.modules[moduleName] = module
643
644    def addCppModule(
645            self, directory, basename, extraHeader="", extraImpl="", customAbsDir=None,
646            useNamespace=True, implOnly=False, suppress=False, headerOnly=False,
647            suppressFeatureGuards=False, moduleName=None, suppressVulkanHeaders=False):
648        module = cereal.Module(
649            directory, basename, customAbsDir=customAbsDir, suppress=suppress, implOnly=implOnly,
650            headerOnly=headerOnly, suppressFeatureGuards=suppressFeatureGuards)
651        self.addModule(module, moduleName=moduleName)
652        module.headerPreamble = copyrightHeader
653        module.headerPreamble += \
654                autogeneratedHeaderTemplate % \
655                (basename, "(header) generated by %s" % banner_command(sys.argv))
656
657
658        namespaceBegin = """
659namespace gfxstream {
660namespace vk {
661""" if useNamespace else ""
662
663        namespaceEnd = """
664}  // namespace vk"
665}  // namespace gfxstream
666""" if useNamespace else ""
667
668        module.headerPreamble += "#pragma once\n"
669        if (not suppressVulkanHeaders):
670            module.headerPreamble += "#include <vulkan/vulkan.h>\n"
671            module.headerPreamble += '#include "vulkan_gfxstream.h"\n'
672        module.headerPreamble += extraHeader + '\n'
673        if namespaceBegin:
674            module.headerPreamble += namespaceBegin + '\n'
675
676        module.implPreamble = copyrightHeader
677        module.implPreamble += \
678                autogeneratedHeaderTemplate % \
679                (basename, "(impl) generated by %s" % \
680                    banner_command(sys.argv))
681        if not implOnly:
682            module.implPreamble += """
683#include "%s.h"
684
685%s
686
687%s
688
689""" % (basename, extraImpl, namespaceBegin)
690
691        module.headerPostamble = """
692%s
693""" % namespaceEnd
694        module.implPostamble = """
695%s
696""" % namespaceEnd
697
698    def addWrapper(self, moduleType, moduleName, **kwargs):
699        if moduleName not in self.modules:
700            print(f'Unknown module: {moduleName}. All known modules are: {", ".join(self.modules)}.')
701            return
702        self.wrappers.append(
703            moduleType(
704                self.modules[moduleName],
705                self.typeInfo, **kwargs))
706
707    def forEachModule(self, func):
708        for moduleName in self.moduleList:
709            func(self.modules[moduleName])
710
711    def forEachWrapper(self, func):
712        for wrapper in self.wrappers:
713            func(wrapper)
714
715## Overrides####################################################################
716
717    def beginFile(self, genOpts):
718        OutputGenerator.beginFile(self, genOpts, suppressEnabled)
719
720        if suppressEnabled:
721            def enableSuppression(m):
722                m.suppress = True
723            self.forEachModule(enableSuppression)
724            self.modules[suppressExceptModule].suppress = False
725
726        if not suppressEnabled:
727            write(self.host_cmake_generator(self.hostCMakeCppFiles),
728                  file = self.outFile)
729
730            guestEncoderAndroidMkPath = \
731                os.path.join( \
732                    self.guest_abs_encoder_destination,
733                    "Android.mk")
734
735        self.forEachModule(lambda m: m.begin(self.genOpts.directory))
736        self.forEachWrapper(lambda w: w.onBegin())
737
738    def endFile(self):
739        OutputGenerator.endFile(self)
740
741        self.typeInfo.onEnd()
742
743        self.forEachWrapper(lambda w: w.onEnd())
744        self.forEachModule(lambda m: m.end())
745
746    def beginFeature(self, interface, emit):
747        # Start processing in superclass
748        OutputGenerator.beginFeature(self, interface, emit)
749
750        self.typeInfo.onBeginFeature(self.featureName, self.featureType)
751
752        self.forEachModule(
753            lambda m: m.appendHeader("#ifdef %s\n" % self.featureName)
754            if isinstance(m, cereal.Module) and not m.suppressFeatureGuards else None)
755        self.forEachModule(
756            lambda m: m.appendImpl("#ifdef %s\n" % self.featureName)
757            if isinstance(m, cereal.Module) and not m.suppressFeatureGuards else None)
758        self.forEachWrapper(lambda w: w.onBeginFeature(self.featureName, self.featureType))
759        # functable needs to understand the feature type (device vs instance) of each cmd
760        for features in interface.findall('require'):
761            for c in features.findall('command'):
762                self.forEachWrapper(lambda w: w.onFeatureNewCmd(c.get('name')))
763
764    def endFeature(self):
765        # Finish processing in superclass
766        OutputGenerator.endFeature(self)
767
768        self.typeInfo.onEndFeature()
769
770        self.forEachModule(lambda m: m.appendHeader("#endif\n") if isinstance(
771            m, cereal.Module) and not m.suppressFeatureGuards else None)
772        self.forEachModule(lambda m: m.appendImpl("#endif\n") if isinstance(
773            m, cereal.Module) and not m.suppressFeatureGuards else None)
774        self.forEachWrapper(lambda w: w.onEndFeature())
775
776    def genType(self, typeinfo: TypeInfo, name, alias):
777        OutputGenerator.genType(self, typeinfo, name, alias)
778        self.typeInfo.onGenType(typeinfo, name, alias)
779        self.forEachWrapper(lambda w: w.onGenType(typeinfo, name, alias))
780
781    def genStruct(self, typeinfo, typeName, alias):
782        OutputGenerator.genStruct(self, typeinfo, typeName, alias)
783        self.typeInfo.onGenStruct(typeinfo, typeName, alias)
784        self.forEachWrapper(lambda w: w.onGenStruct(typeinfo, typeName, alias))
785
786    def genGroup(self, groupinfo: GroupInfo, groupName, alias = None):
787        OutputGenerator.genGroup(self, groupinfo, groupName, alias)
788        self.typeInfo.onGenGroup(groupinfo, groupName, alias)
789        self.forEachWrapper(lambda w: w.onGenGroup(groupinfo, groupName, alias))
790
791    def genEnum(self, enuminfo: EnumInfo, name, alias):
792        OutputGenerator.genEnum(self, enuminfo, name, alias)
793        self.typeInfo.onGenEnum(enuminfo, name, alias)
794        self.forEachWrapper(lambda w: w.onGenEnum(enuminfo, name, alias))
795
796    def genCmd(self, cmdinfo, name, alias):
797        OutputGenerator.genCmd(self, cmdinfo, name, alias)
798        self.typeInfo.onGenCmd(cmdinfo, name, alias)
799        self.forEachWrapper(lambda w: w.onGenCmd(cmdinfo, name, alias))
800