• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2018 The Android Open Source Project
2# Copyright (c) 2018 Google Inc.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16from .common.codegen import CodeGen
17from .common.vulkantypes import \
18        VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator
19
20from .wrapperdefs import VulkanWrapperGenerator
21from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE, EXTENSION_SIZE_API_NAME
22
23class DeepcopyCodegen(VulkanTypeIterator):
24    def __init__(self, cgen, inputVars, poolVarName, rootVarName, prefix, skipValues=False):
25        self.cgen = cgen
26        self.inputVars = inputVars
27        self.prefix = prefix
28        self.poolVarName = poolVarName
29        self.rootVarName = rootVarName
30        self.skipValues = skipValues
31
32        def makeAccess(varName, asPtr = True):
33            return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr)
34
35        def makeLengthAccess(varName):
36            return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName)
37
38        def makeLengthAccessGuard(varName):
39            return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName)
40
41        self.exprAccessorLhs = makeAccess(self.inputVars[0])
42        self.exprAccessorRhs = makeAccess(self.inputVars[1])
43
44        self.exprAccessorValueLhs = makeAccess(self.inputVars[0], asPtr = False)
45        self.exprAccessorValueRhs = makeAccess(self.inputVars[1], asPtr = False)
46
47        self.lenAccessorLhs = makeLengthAccess(self.inputVars[0])
48        self.lenAccessorRhs = makeLengthAccess(self.inputVars[1])
49
50        self.lenAccessorGuardLhs = makeLengthAccessGuard(self.inputVars[0])
51        self.lenAccessorGuardRhs = makeLengthAccessGuard(self.inputVars[1])
52
53        self.checked = False
54
55    def needSkip(self, vulkanType):
56        return False
57
58    def makeCastExpr(self, vulkanType):
59        return "(%s)" % (
60            self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
61
62    def makeNonConstCastForCopy(self, access, vulkanType):
63        if vulkanType.staticArrExpr:
64            casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
65        elif vulkanType.accessibleAsPointer():
66            casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForNonConstAccess()), access)
67        else:
68            casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
69        return casted
70
71    def makeAllocBytesExpr(self, lenAccess, vulkanType):
72        sizeof = self.cgen.sizeofExpr( \
73                     vulkanType.getForValueAccess())
74        if lenAccess:
75            bytesExpr = "%s * %s" % (lenAccess, sizeof)
76        else:
77            bytesExpr = sizeof
78
79        return bytesExpr
80
81    def onCheck(self, vulkanType):
82        pass
83
84    def endCheck(self, vulkanType):
85        pass
86
87    def onCompoundType(self, vulkanType):
88
89        if self.needSkip(vulkanType):
90            self.cgen.line("// TODO: Unsupported : %s" %
91                           self.cgen.makeCTypeDecl(vulkanType))
92            return
93
94        accessLhs = self.exprAccessorLhs(vulkanType)
95        accessRhs = self.exprAccessorRhs(vulkanType)
96
97        lenAccessLhs = self.lenAccessorLhs(vulkanType)
98        lenAccessRhs = self.lenAccessorRhs(vulkanType)
99
100        lenAccessorGuardLhs = self.lenAccessorGuardLhs(vulkanType)
101        lenAccessorGuardRhs = self.lenAccessorGuardRhs(vulkanType)
102
103        isPtr = vulkanType.pointerIndirectionLevels > 0
104
105        if lenAccessorGuardLhs is not None:
106            self.cgen.beginIf(lenAccessorGuardLhs)
107
108        if isPtr:
109            self.cgen.stmt("%s = nullptr" % accessRhs)
110            self.cgen.beginIf(accessLhs)
111
112            self.cgen.stmt( \
113                "%s = %s%s->alloc(%s)" % \
114                (accessRhs, self.makeCastExpr(vulkanType.getForNonConstAccess()),
115                 self.poolVarName, self.makeAllocBytesExpr(lenAccessLhs, vulkanType)))
116
117        if lenAccessLhs is not None:
118
119            loopVar = "i"
120            accessLhs = "%s + %s" % (accessLhs, loopVar)
121            forInit = "uint32_t %s = 0" % loopVar
122            forCond = "%s < (uint32_t)%s" % (loopVar, lenAccessLhs)
123            forIncr = "++%s" % loopVar
124
125            if isPtr:
126                # Avoid generating a self-assign.
127                if lenAccessRhs != lenAccessLhs:
128                    self.cgen.stmt("%s = %s" % (lenAccessRhs, lenAccessLhs))
129
130            accessRhs = "%s + %s" % (accessRhs, loopVar)
131            self.cgen.beginFor(forInit, forCond, forIncr)
132
133
134        accessRhsCasted = self.makeNonConstCastForCopy(accessRhs, vulkanType)
135
136        self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
137                           [self.poolVarName, self.rootVarName, accessLhs, accessRhsCasted])
138
139        if lenAccessLhs is not None:
140            self.cgen.endFor()
141
142        if isPtr:
143            self.cgen.endIf()
144
145        if lenAccessorGuardLhs is not None:
146            self.cgen.endIf()
147
148    def onString(self, vulkanType):
149        accessLhs = self.exprAccessorLhs(vulkanType)
150        accessRhs = self.exprAccessorRhs(vulkanType)
151
152        self.cgen.stmt("%s = nullptr" % accessRhs)
153        self.cgen.beginIf(accessLhs)
154
155        self.cgen.stmt( \
156            "%s = %s->strDup(%s)" % \
157            (accessRhs,
158             self.poolVarName,
159             accessLhs))
160
161        self.cgen.endIf()
162
163    def onStringArray(self, vulkanType):
164        accessLhs = self.exprAccessorLhs(vulkanType)
165        accessRhs = self.exprAccessorRhs(vulkanType)
166
167        lenAccessLhs = self.lenAccessorLhs(vulkanType)
168
169        self.cgen.stmt("%s = nullptr" % accessRhs)
170        self.cgen.beginIf("%s && %s" % (accessLhs, lenAccessLhs))
171
172        self.cgen.stmt( \
173            "%s = %s->strDupArray(%s, %s)" % \
174            (accessRhs,
175             self.poolVarName,
176             accessLhs,
177             lenAccessLhs))
178
179        self.cgen.endIf()
180
181    def onStaticArr(self, vulkanType):
182        accessLhs = self.exprAccessorValueLhs(vulkanType)
183        accessRhs = self.exprAccessorValueRhs(vulkanType)
184
185        lenAccessLhs = self.lenAccessorLhs(vulkanType)
186
187        bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType)
188        self.cgen.stmt("memcpy(%s, %s, %s)" % (accessRhs, accessLhs, bytesExpr))
189
190    def onStructExtension(self, vulkanType):
191
192        lhs = self.exprAccessorLhs(vulkanType)
193        rhs = self.exprAccessorRhs(vulkanType)
194
195        rhsExpr = "(%s)(%s)" % ("void*", rhs)
196
197        nextVar = "from_%s" % vulkanType.paramName
198        sizeVar = "%s_size" % vulkanType.paramName
199
200        self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" %
201                          self.rootVarName)
202        self.cgen.stmt("%s = from->sType" % self.rootVarName)
203        self.cgen.endIf()
204
205        self.cgen.stmt("const void* %s = %s" % (nextVar, self.inputVars[0]))
206        self.cgen.stmt("size_t %s = 0u" % sizeVar)
207        self.cgen.beginWhile("!%s && %s" % (sizeVar, nextVar))
208        self.cgen.stmt("%s = static_cast<const vk_struct_common*>(%s)->%s" % (
209            nextVar, nextVar, vulkanType.paramName
210        ))
211        self.cgen.stmt("%s = %s(%s, %s)" % (
212            sizeVar, EXTENSION_SIZE_API_NAME, self.rootVarName, nextVar))
213        self.cgen.endWhile()
214
215        self.cgen.stmt("%s = nullptr" % rhs)
216
217        self.cgen.beginIf(sizeVar)
218
219        self.cgen.stmt( \
220            "%s = %s%s->alloc(%s)" % \
221            (rhs, self.makeCastExpr(vulkanType.getForNonConstAccess()), self.poolVarName, sizeVar))
222
223        self.cgen.funcCall(None, self.prefix + "extension_struct",
224                           [self.poolVarName, self.rootVarName, nextVar, rhsExpr])
225
226        self.cgen.endIf()
227
228    def onPointer(self, vulkanType):
229
230        accessLhs = self.exprAccessorLhs(vulkanType)
231        accessRhs = self.exprAccessorRhs(vulkanType)
232
233        if self.needSkip(vulkanType):
234            self.cgen.stmt("%s = nullptr" % accessRhs)
235            return
236
237        lenAccessLhs = self.lenAccessorLhs(vulkanType)
238
239        self.cgen.stmt("%s = nullptr" % accessRhs)
240        self.cgen.beginIf(accessLhs)
241
242        bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType)
243
244        self.cgen.stmt( \
245            "%s = %s%s->dupArray(%s, %s)" % \
246            (accessRhs,
247             self.makeCastExpr(vulkanType.getForNonConstAccess()),
248             self.poolVarName,
249             accessLhs,
250             bytesExpr))
251
252        self.cgen.endIf()
253
254    def onValue(self, vulkanType):
255        if self.skipValues:
256            return
257
258        accessLhs = self.exprAccessorValueLhs(vulkanType)
259        accessRhs = self.exprAccessorValueRhs(vulkanType)
260
261        self.cgen.stmt("%s = %s" % (accessRhs, accessLhs))
262
263class VulkanDeepcopy(VulkanWrapperGenerator):
264
265    def __init__(self, module, typeInfo):
266        VulkanWrapperGenerator.__init__(self, module, typeInfo)
267
268        self.codegen = CodeGen()
269
270        self.deepcopyPrefix = "deepcopy_"
271        self.deepcopyVars = ["from", "to"]
272        self.deepcopyAllocatorVarName = "alloc"
273        self.deepcopyAllocatorParam = \
274            makeVulkanTypeSimple(False, "Allocator", 1,
275                                 self.deepcopyAllocatorVarName)
276        self.deepcopyRootVarName = "rootType"
277        self.deepcopyRootParam = \
278            makeVulkanTypeSimple(False, "VkStructureType",
279                                 0, self.deepcopyRootVarName)
280        self.voidType = makeVulkanTypeSimple(False, "void", 0)
281
282        self.deepcopyCodegen = \
283            DeepcopyCodegen(
284                None,
285                self.deepcopyVars,
286                self.deepcopyAllocatorVarName,
287                self.deepcopyRootVarName,
288                self.deepcopyPrefix,
289                skipValues=True)
290
291        self.knownDefs = {}
292
293        self.extensionDeepcopyPrototype = \
294            VulkanAPI(self.deepcopyPrefix + "extension_struct",
295                      self.voidType,
296                      [self.deepcopyAllocatorParam,
297                       self.deepcopyRootParam,
298                       STRUCT_EXTENSION_PARAM,
299                       STRUCT_EXTENSION_PARAM_FOR_WRITE])
300
301    def onBegin(self,):
302        VulkanWrapperGenerator.onBegin(self)
303        self.module.appendImpl(self.codegen.makeFuncDecl(
304            self.extensionDeepcopyPrototype))
305
306    def onGenType(self, typeXml, name, alias):
307        VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
308
309        if name in self.knownDefs:
310            return
311
312        category = self.typeInfo.categoryOf(name)
313
314        if category in ["struct", "union"] and alias:
315            self.module.appendHeader(
316                self.codegen.makeFuncAlias(self.deepcopyPrefix + name,
317                                           self.deepcopyPrefix + alias))
318
319        if category in ["struct", "union"] and not alias:
320
321            structInfo = self.typeInfo.structs[name]
322
323            typeFromName = \
324                lambda varname: \
325                    makeVulkanTypeSimple(varname == "from", name, 1, varname)
326
327            deepcopyParams = \
328                [self.deepcopyAllocatorParam, self.deepcopyRootParam] + \
329                 list(map(typeFromName, self.deepcopyVars))
330
331            deepcopyPrototype = \
332                VulkanAPI(self.deepcopyPrefix + name,
333                          self.voidType,
334                          deepcopyParams)
335
336            def structDeepcopyDef(cgen):
337                self.deepcopyCodegen.cgen = cgen
338                canSimplyAssign = True
339                for member in structInfo.members:
340                    if not member.isSimpleValueType(self.typeInfo):
341                        canSimplyAssign = False
342
343                cgen.stmt("(void)%s" % self.deepcopyAllocatorVarName)
344                cgen.stmt("(void)%s" % self.deepcopyRootVarName)
345                cgen.stmt("*to = *from")
346                if canSimplyAssign:
347                    pass
348                else:
349                    for member in structInfo.members:
350                        iterateVulkanType(self.typeInfo, member,
351                                          self.deepcopyCodegen)
352
353            self.module.appendHeader(
354                self.codegen.makeFuncDecl(deepcopyPrototype))
355            self.module.appendImpl(
356                self.codegen.makeFuncImpl(deepcopyPrototype, structDeepcopyDef))
357
358    def onGenCmd(self, cmdinfo, name, alias):
359        VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
360
361    def onEnd(self,):
362        VulkanWrapperGenerator.onEnd(self)
363
364        def deepcopyDstExpr(cgen, typeName):
365            return cgen.makeReinterpretCast( \
366                       STRUCT_EXTENSION_PARAM_FOR_WRITE.paramName,
367                       typeName, const=False)
368
369        def forEachExtensionDeepcopy(ext, castedAccess, cgen):
370            cgen.funcCall(None, self.deepcopyPrefix + ext.name,
371                          [self.deepcopyAllocatorVarName,
372                           self.deepcopyRootVarName,
373                           castedAccess, deepcopyDstExpr(cgen, ext.name)])
374
375        self.module.appendImpl(
376            self.codegen.makeFuncImpl(
377                self.extensionDeepcopyPrototype,
378                lambda cgen: self.emitForEachStructExtension(
379                    cgen,
380                    self.voidType,
381                    STRUCT_EXTENSION_PARAM,
382                    forEachExtensionDeepcopy,
383                    rootTypeVar=self.deepcopyRootParam)))
384