# Copyright (c) 2018 The Android Open Source Project # Copyright (c) 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from .common.codegen import CodeGen from .common.vulkantypes import \ VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator from .wrapperdefs import VulkanWrapperGenerator from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE class HandleMapCodegen(VulkanTypeIterator): def __init__(self, cgen, inputVar, handlemapVarName, prefix, isHandleFunc): self.cgen = cgen self.inputVar = inputVar self.prefix = prefix self.handlemapVarName = handlemapVarName def makeAccess(varName, asPtr = True): return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr) def makeLengthAccess(varName): return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName) def makeLengthAccessGuard(varName): return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName) self.exprAccessor = makeAccess(self.inputVar) self.exprAccessorValue = makeAccess(self.inputVar, asPtr = False) self.lenAccessor = makeLengthAccess(self.inputVar) self.lenAccessorGuard = makeLengthAccessGuard(self.inputVar) self.checked = False self.isHandleFunc = isHandleFunc def needSkip(self, vulkanType): return False def makeCastExpr(self, vulkanType): return "(%s)" % ( self.cgen.makeCTypeDecl(vulkanType, useParamName=False)) def asNonConstCast(self, access, vulkanType): if vulkanType.staticArrExpr: casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access) elif vulkanType.accessibleAsPointer(): casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForNonConstAccess()), access) else: casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access) return casted def onCheck(self, vulkanType): pass def endCheck(self, vulkanType): pass def onCompoundType(self, vulkanType): if self.needSkip(vulkanType): self.cgen.line("// TODO: Unsupported : %s" % self.cgen.makeCTypeDecl(vulkanType)) return access = self.exprAccessor(vulkanType) lenAccess = self.lenAccessor(vulkanType) lenAccessGuard = self.lenAccessorGuard(vulkanType) isPtr = vulkanType.pointerIndirectionLevels > 0 if lenAccessGuard is not None: self.cgen.beginIf(lenAccessGuard) if isPtr: self.cgen.beginIf(access) if lenAccess is not None: loopVar = "i" access = "%s + %s" % (access, loopVar) forInit = "uint32_t %s = 0" % loopVar forCond = "%s < (uint32_t)%s" % (loopVar, lenAccess) forIncr = "++%s" % loopVar self.cgen.beginFor(forInit, forCond, forIncr) accessCasted = self.asNonConstCast(access, vulkanType) self.cgen.funcCall(None, self.prefix + vulkanType.typeName, [self.handlemapVarName, accessCasted]) if lenAccess is not None: self.cgen.endFor() if isPtr: self.cgen.endIf() if lenAccessGuard is not None: self.cgen.endIf() def onString(self, vulkanType): pass def onStringArray(self, vulkanType): pass def onStaticArr(self, vulkanType): if not self.isHandleFunc(vulkanType): return accessLhs = self.exprAccessor(vulkanType) lenAccess = self.lenAccessor(vulkanType) self.cgen.stmt("%s->mapHandles_%s(%s%s, %s)" % \ (self.handlemapVarName, vulkanType.typeName, self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), accessLhs, lenAccess)) def onStructExtension(self, vulkanType): access = self.exprAccessor(vulkanType) castedAccessExpr = "(%s)(%s)" % ("void*", access) self.cgen.beginIf(access) self.cgen.funcCall(None, self.prefix + "extension_struct", [self.handlemapVarName, castedAccessExpr]) self.cgen.endIf() def onPointer(self, vulkanType): if self.needSkip(vulkanType): return if not self.isHandleFunc(vulkanType): return access = self.exprAccessor(vulkanType) lenAccess = self.lenAccessor(vulkanType) lenAccess = "1" if lenAccess is None else lenAccess self.cgen.beginIf(access) self.cgen.stmt( \ "%s->mapHandles_%s(%s%s, %s)" % \ (self.handlemapVarName, vulkanType.typeName, self.makeCastExpr(vulkanType.getForNonConstAccess()), access, lenAccess)) self.cgen.endIf() def onValue(self, vulkanType): if not self.isHandleFunc(vulkanType): return access = self.exprAccessor(vulkanType) self.cgen.stmt( "%s->mapHandles_%s(%s%s)" % \ (self.handlemapVarName, vulkanType.typeName, self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)) class VulkanHandleMap(VulkanWrapperGenerator): def __init__(self, module, typeInfo): VulkanWrapperGenerator.__init__(self, module, typeInfo) self.codegen = CodeGen() self.handlemapPrefix = "handlemap_" self.toMapVar = "toMap" self.handlemapVarName = "handlemap" self.handlemapParam = \ makeVulkanTypeSimple(False, "VulkanHandleMapping", 1, self.handlemapVarName) self.voidType = makeVulkanTypeSimple(False, "void", 0) self.handlemapCodegen = \ HandleMapCodegen( None, self.toMapVar, self.handlemapVarName, self.handlemapPrefix, lambda vtype : typeInfo.isHandleType(vtype.typeName)) self.knownDefs = {} self.extensionHandlemapPrototype = \ VulkanAPI(self.handlemapPrefix + "extension_struct", self.voidType, [self.handlemapParam, STRUCT_EXTENSION_PARAM_FOR_WRITE]) def onBegin(self,): VulkanWrapperGenerator.onBegin(self) self.module.appendImpl(self.codegen.makeFuncDecl( self.extensionHandlemapPrototype)) def onGenType(self, typeXml, name, alias): VulkanWrapperGenerator.onGenType(self, typeXml, name, alias) if name in self.knownDefs: return category = self.typeInfo.categoryOf(name) if category in ["struct", "union"] and alias: self.module.appendHeader( self.codegen.makeFuncAlias(self.handlemapPrefix + name, self.handlemapPrefix + alias)) if category in ["struct", "union"] and not alias: structInfo = self.typeInfo.structs[name] typeFromName = \ lambda varname: \ makeVulkanTypeSimple(varname == "from", name, 1, varname) handlemapParams = \ [self.handlemapParam] + \ list(map(typeFromName, [self.toMapVar])) handlemapPrototype = \ VulkanAPI(self.handlemapPrefix + name, self.voidType, handlemapParams) def funcDefGenerator(cgen): self.handlemapCodegen.cgen = cgen for p in handlemapParams: cgen.stmt("(void)%s" % p.paramName) for member in structInfo.members: iterateVulkanType(self.typeInfo, member, self.handlemapCodegen) self.module.appendHeader( self.codegen.makeFuncDecl(handlemapPrototype)) self.module.appendImpl( self.codegen.makeFuncImpl(handlemapPrototype, funcDefGenerator)) def onGenCmd(self, cmdinfo, name, alias): VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias) def onEnd(self,): VulkanWrapperGenerator.onEnd(self) def forEachExtensionHandlemap(ext, castedAccess, cgen): cgen.funcCall(None, self.handlemapPrefix + ext.name, [self.handlemapVarName, castedAccess]) self.module.appendImpl( self.codegen.makeFuncImpl( self.extensionHandlemapPrototype, lambda cgen: self.emitForEachStructExtension( cgen, self.voidType, STRUCT_EXTENSION_PARAM_FOR_WRITE, forEachExtensionHandlemap)))