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