• 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.
15from copy import copy
16
17from .common.codegen import CodeGen, VulkanAPIWrapper
18from .common.vulkantypes import \
19        VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator, Atom, FuncExpr, FuncExprVal, FuncLambda
20
21from .wrapperdefs import VulkanWrapperGenerator
22from .wrapperdefs import VULKAN_STREAM_VAR_NAME
23from .wrapperdefs import ROOT_TYPE_VAR_NAME, ROOT_TYPE_PARAM
24from .wrapperdefs import STREAM_RET_TYPE
25from .wrapperdefs import MARSHAL_INPUT_VAR_NAME
26from .wrapperdefs import UNMARSHAL_INPUT_VAR_NAME
27from .wrapperdefs import PARAMETERS_MARSHALING
28from .wrapperdefs import PARAMETERS_MARSHALING_GUEST
29from .wrapperdefs import STYPE_OVERRIDE
30from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME
31from .wrapperdefs import API_PREFIX_RESERVEDMARSHAL
32from .wrapperdefs import API_PREFIX_RESERVEDUNMARSHAL
33
34from .marshalingdefs import CUSTOM_MARSHAL_TYPES
35class VulkanReservedMarshalingCodegen(VulkanTypeIterator):
36    def __init__(self,
37                 cgen,
38                 streamVarName,
39                 rootTypeVarName,
40                 inputVarName,
41                 ptrVarName,
42                 marshalPrefix,
43                 handlemapPrefix,
44                 direction = "write",
45                 forApiOutput = False,
46                 dynAlloc = False,
47                 mapHandles = True,
48                 handleMapOverwrites = False,
49                 doFiltering = True,
50                 stackVar=None,
51                 stackArrSize=None):
52        self.cgen = cgen
53        self.direction = direction
54        self.processSimple = "write" if self.direction == "write" else "read"
55        self.forApiOutput = forApiOutput
56
57        self.checked = False
58
59        self.streamVarName = streamVarName
60        self.rootTypeVarName = rootTypeVarName
61        self.inputVarName = inputVarName
62        self.ptrVar = ptrVarName
63        self.marshalPrefix = marshalPrefix
64        self.handlemapPrefix = handlemapPrefix
65
66        self.exprAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = True)
67        self.exprValueAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = False)
68        self.exprPrimitiveValueAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = False)
69        self.lenAccessor = lambda t: self.cgen.generalLengthAccess(t, parentVarName = self.inputVarName)
70        self.lenAccessorGuard = lambda t: self.cgen.generalLengthAccessGuard(
71            t, parentVarName=self.inputVarName)
72        self.filterVarAccessor = lambda t: self.cgen.filterVarAccess(t, parentVarName = self.inputVarName)
73
74        self.dynAlloc = dynAlloc
75        self.mapHandles = mapHandles
76        self.handleMapOverwrites = handleMapOverwrites
77        self.doFiltering = doFiltering
78
79        self.stackVar = stackVar
80        self.stackArrSize = stackArrSize
81
82    def getTypeForStreaming(self, vulkanType):
83        res = copy(vulkanType)
84
85        if not vulkanType.accessibleAsPointer():
86            res = res.getForAddressAccess()
87
88        if vulkanType.staticArrExpr:
89            res = res.getForAddressAccess()
90
91        if self.direction == "write":
92            return res
93        else:
94            return res.getForNonConstAccess()
95
96    def makeCastExpr(self, vulkanType):
97        return "(%s)" % (
98            self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
99
100    def genPtrIncr(self, sizeExpr):
101        self.cgen.stmt("*%s += %s" % (self.ptrVar, sizeExpr))
102
103    def genMemcpyAndIncr(self, varname, cast, toStreamExpr, sizeExpr, toBe = False, actualSize = 4):
104        if self.direction == "write":
105            self.cgen.stmt("memcpy(*%s, %s%s, %s)" % (varname, cast, toStreamExpr, sizeExpr))
106        else:
107            self.cgen.stmt("memcpy(%s%s, *%s, %s)" % (cast, toStreamExpr, varname, sizeExpr))
108
109        if toBe:
110            streamPrefix = "to"
111            if "read" == self.direction:
112                streamPrefix = "from"
113
114            streamMethod = streamPrefix
115
116            if 1 == actualSize:
117                streamMethod += "Byte"
118            elif 2 == actualSize:
119                streamMethod += "Be16"
120            elif 4 == actualSize:
121                streamMethod += "Be32"
122            elif 8 == actualSize:
123                streamMethod += "Be64"
124            else:
125                pass
126
127            if self.direction == "write":
128                self.cgen.stmt("android::base::Stream::%s((uint8_t*)*%s)" % (streamMethod, varname))
129            else:
130                self.cgen.stmt("android::base::Stream::%s((uint8_t*)%s)" % (streamMethod, toStreamExpr))
131
132        self.genPtrIncr(sizeExpr)
133
134    def genStreamCall(self, vulkanType, toStreamExpr, sizeExpr):
135        varname = self.ptrVar
136        cast = self.makeCastExpr(self.getTypeForStreaming(vulkanType))
137        self.genMemcpyAndIncr(varname, cast, toStreamExpr, sizeExpr)
138
139    def genPrimitiveStreamCall(self, vulkanType, access):
140        varname = self.ptrVar
141        self.cgen.memcpyPrimitive(
142            self.typeInfo,
143            "(*" + varname + ")",
144            access,
145            vulkanType,
146            direction=self.direction)
147        self.genPtrIncr(str(self.cgen.countPrimitive(
148            self.typeInfo,
149            vulkanType)))
150
151    def genHandleMappingCall(self, vulkanType, access, lenAccess, lenAccessGuard):
152
153        if lenAccess is None:
154            lenAccess = "1"
155            handle64Bytes = "8"
156        else:
157            handle64Bytes = "%s * 8" % lenAccess
158
159        handle64Var = self.cgen.var()
160        if lenAccess != "1":
161            self.cgen.beginIf(lenAccess)
162            self.cgen.stmt("uint8_t* %s_ptr = (uint8_t*)(*%s)" % (handle64Var, self.ptrVar))
163            handle64VarAccess = handle64Var
164            handle64VarType = \
165                makeVulkanTypeSimple(False, "uint64_t", 1, paramName=handle64Var)
166        else:
167            self.cgen.stmt("uint64_t %s" % handle64Var)
168            handle64VarAccess = "&%s" % handle64Var
169            handle64VarType = \
170                makeVulkanTypeSimple(False, "uint64_t", 0, paramName=handle64Var)
171
172        if "" == self.handlemapPrefix:
173            mapFunc = ("(%s)" % vulkanType.typeName)
174            mapFunc64 = ("(%s)" % "uint64_t")
175        else:
176            mapFunc = self.handlemapPrefix + vulkanType.typeName
177            mapFunc64 = mapFunc
178
179        if self.direction == "write":
180            if self.handleMapOverwrites:
181                self.cgen.stmt(
182                    "static_assert(8 == sizeof(%s), \"handle map overwrite requres %s to be 8 bytes long\")" % \
183                            (vulkanType.typeName, vulkanType.typeName))
184                if "1" == lenAccess:
185                    self.cgen.stmt("*%s = (%s)%s(*%s)" % (access, vulkanType.typeName, mapFunc, access))
186                    self.genStreamCall(vulkanType, access, "8 * %s" % lenAccess)
187                else:
188                    if lenAccessGuard is not None:
189                        self.cgen.beginIf(lenAccessGuard)
190                    self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k")
191                    self.cgen.stmt("%s[k] = (%s)%s(%s[k])" % (access, vulkanType.typeName, mapFunc, access))
192                    self.cgen.endFor()
193                    if lenAccessGuard is not None:
194                        self.cgen.endIf()
195                    self.genPtrIncr("8 * %s" % lenAccess)
196            else:
197                if "1" == lenAccess:
198                    self.cgen.stmt("*%s = %s((*%s))" % (handle64VarAccess, mapFunc64, access))
199                    self.genStreamCall(handle64VarType, handle64VarAccess, handle64Bytes)
200                else:
201                    if lenAccessGuard is not None:
202                        self.cgen.beginIf(lenAccessGuard)
203                    self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k")
204                    self.cgen.stmt("uint64_t tmpval = %s(%s[k])" % (mapFunc64, access))
205                    self.cgen.stmt("memcpy(%s_ptr + k * 8, &tmpval, sizeof(uint64_t))" % (handle64Var))
206                    self.cgen.endFor()
207                    if lenAccessGuard is not None:
208                        self.cgen.endIf()
209                    self.genPtrIncr("8 * %s" % lenAccess)
210        else:
211            if "1" == lenAccess:
212                self.genStreamCall(handle64VarType, handle64VarAccess, handle64Bytes)
213                self.cgen.stmt("*%s%s = (%s)%s((%s)(*%s))" % (
214                    self.makeCastExpr(vulkanType.getForNonConstAccess()), access,
215                    vulkanType.typeName, mapFunc, vulkanType.typeName, handle64VarAccess))
216            else:
217                self.genPtrIncr("8 * %s" % lenAccess)
218                if lenAccessGuard is not None:
219                    self.cgen.beginIf(lenAccessGuard)
220                self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k")
221                self.cgen.stmt("uint64_t tmpval; memcpy(&tmpval, %s_ptr + k * 8, sizeof(uint64_t))" % handle64Var)
222                self.cgen.stmt("*((%s%s) + k) = (%s)%s((%s)tmpval)" % (
223                    self.makeCastExpr(vulkanType.getForNonConstAccess()), access,
224                    vulkanType.typeName, mapFunc, vulkanType.typeName))
225                if lenAccessGuard is not None:
226                    self.cgen.endIf()
227                self.cgen.endFor()
228
229        if lenAccess != "1":
230            self.cgen.endIf()
231
232    def doAllocSpace(self, vulkanType):
233        if self.dynAlloc and self.direction == "read":
234            access = self.exprAccessor(vulkanType)
235            lenAccess = self.lenAccessor(vulkanType)
236            sizeof = self.cgen.sizeofExpr(vulkanType.getForValueAccess())
237            if lenAccess:
238                bytesExpr = "%s * %s" % (lenAccess, sizeof)
239            else:
240                bytesExpr = sizeof
241                lenAccess = "1"
242
243            if self.stackVar:
244                if self.stackArrSize != lenAccess:
245                    self.cgen.beginIf("%s <= %s" % (lenAccess, self.stackArrSize))
246
247                self.cgen.stmt(
248                        "%s = %s%s" % (access, self.makeCastExpr(vulkanType.getForNonConstAccess()), self.stackVar))
249
250                if self.stackArrSize != lenAccess:
251                    self.cgen.endIf()
252                    self.cgen.beginElse()
253
254                if self.stackArrSize != lenAccess:
255                    self.cgen.stmt(
256                            "%s->alloc((void**)&%s, %s)" %
257                            (self.streamVarName,
258                                access, bytesExpr))
259
260                if self.stackArrSize != lenAccess:
261                    self.cgen.endIf()
262            else:
263                self.cgen.stmt(
264                        "%s->alloc((void**)&%s, %s)" %
265                        (self.streamVarName,
266                            access, bytesExpr))
267
268    def getOptionalStringFeatureExpr(self, vulkanType):
269        if vulkanType.optionalStr is not None:
270            if vulkanType.optionalStr.startswith("streamFeature:"):
271                splitted = vulkanType.optionalStr.split(":")
272                featureExpr = "%s->getFeatureBits() & %s" % (self.streamVarName, splitted[1])
273                return featureExpr
274        return None
275
276    def onCheck(self, vulkanType):
277        if self.forApiOutput:
278            return
279
280        featureExpr = self.getOptionalStringFeatureExpr(vulkanType)
281        self.checked = True
282        access = self.exprAccessor(vulkanType)
283        needConsistencyCheck = False
284
285        self.cgen.line("// WARNING PTR CHECK")
286        if (self.dynAlloc and self.direction == "read") or self.direction == "write":
287            checkAccess = self.exprAccessor(vulkanType)
288            addrExpr = "&" + checkAccess
289            sizeExpr = self.cgen.sizeofExpr(vulkanType)
290        else:
291            checkName = "check_%s" % vulkanType.paramName
292            self.cgen.stmt("%s %s" % (
293                self.cgen.makeCTypeDecl(vulkanType, useParamName = False), checkName))
294            checkAccess = checkName
295            addrExpr = "&" + checkAccess
296            sizeExpr = self.cgen.sizeofExpr(vulkanType)
297            needConsistencyCheck = True
298
299        if featureExpr is not None:
300            self.cgen.beginIf(featureExpr)
301
302        self.genPrimitiveStreamCall(
303            vulkanType,
304            checkAccess)
305
306        if featureExpr is not None:
307            self.cgen.endIf()
308
309        if featureExpr is not None:
310            self.cgen.beginIf("(!(%s) || %s)" % (featureExpr, access))
311        else:
312            self.cgen.beginIf(access)
313
314        if needConsistencyCheck and featureExpr is None:
315            self.cgen.beginIf("!(%s)" % checkName)
316            self.cgen.stmt(
317                "fprintf(stderr, \"fatal: %s inconsistent between guest and host\\n\")" % (access))
318            self.cgen.endIf()
319
320    def onCheckWithNullOptionalStringFeature(self, vulkanType):
321        self.cgen.beginIf("%s->getFeatureBits() & VULKAN_STREAM_FEATURE_NULL_OPTIONAL_STRINGS_BIT" % self.streamVarName)
322        self.onCheck(vulkanType)
323
324    def endCheckWithNullOptionalStringFeature(self, vulkanType):
325        self.endCheck(vulkanType)
326        self.cgen.endIf()
327        self.cgen.beginElse()
328
329    def finalCheckWithNullOptionalStringFeature(self, vulkanType):
330        self.cgen.endElse()
331
332    def endCheck(self, vulkanType):
333
334        if self.checked:
335            self.cgen.endIf()
336            self.checked = False
337
338    def genFilterFunc(self, filterfunc, env):
339
340        def loop(expr, lambdaEnv={}):
341            def do_func(expr):
342                fnamestr = expr.name.name
343                if "not" == fnamestr:
344                    return "!(%s)" % (loop(expr.args[0], lambdaEnv))
345                if "eq" == fnamestr:
346                    return "(%s == %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
347                if "and" == fnamestr:
348                    return "(%s && %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
349                if "or" == fnamestr:
350                    return "(%s || %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
351                if "bitwise_and" == fnamestr:
352                    return "(%s & %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
353                if "getfield" == fnamestr:
354                    ptrlevels = get_ptrlevels(expr.args[0].val.name)
355                    if ptrlevels == 0:
356                        return "%s.%s" % (loop(expr.args[0], lambdaEnv), expr.args[1].val)
357                    else:
358                        return "(%s(%s)).%s" % ("*" * ptrlevels, loop(expr.args[0], lambdaEnv), expr.args[1].val)
359
360                if "if" == fnamestr:
361                    return "((%s) ? (%s) : (%s))" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv), loop(expr.args[2], lambdaEnv))
362
363                return "%s(%s)" % (fnamestr, ", ".join(map(lambda e: loop(e, lambdaEnv), expr.args)))
364
365            def do_expratom(atomname, lambdaEnv= {}):
366                if lambdaEnv.get(atomname, None) is not None:
367                    return atomname
368
369                enventry = env.get(atomname, None)
370                if None != enventry:
371                    return self.getEnvAccessExpr(atomname)
372                return atomname
373
374            def get_ptrlevels(atomname, lambdaEnv= {}):
375                if lambdaEnv.get(atomname, None) is not None:
376                    return 0
377
378                enventry = env.get(atomname, None)
379                if None != enventry:
380                    return self.getPointerIndirectionLevels(atomname)
381
382                return 0
383
384            def do_exprval(expr, lambdaEnv= {}):
385                expratom = expr.val
386
387                if Atom == type(expratom):
388                    return do_expratom(expratom.name, lambdaEnv)
389
390                return "%s" % expratom
391
392            def do_lambda(expr, lambdaEnv= {}):
393                params = expr.vs
394                body = expr.body
395                newEnv = {}
396
397                for (k, v) in lambdaEnv.items():
398                    newEnv[k] = v
399
400                for p in params:
401                    newEnv[p.name] = p.typ
402
403                return "[](%s) { return %s; }" % (", ".join(list(map(lambda p: "%s %s" % (p.typ, p.name), params))), loop(body, lambdaEnv=newEnv))
404
405            if FuncExpr == type(expr):
406                return do_func(expr)
407            if FuncLambda == type(expr):
408                return do_lambda(expr)
409            elif FuncExprVal == type(expr):
410                return do_exprval(expr)
411
412        return loop(filterfunc)
413
414    def beginFilterGuard(self, vulkanType):
415        if vulkanType.filterVar == None:
416            return
417
418        if self.doFiltering == False:
419            return
420
421        filterVarAccess = self.getEnvAccessExpr(vulkanType.filterVar)
422
423        filterValsExpr = None
424        filterFuncExpr = None
425        filterExpr = None
426
427        filterFeature = "%s->getFeatureBits() & VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT" % self.streamVarName
428
429        if None != vulkanType.filterVals:
430            filterValsExpr = " || ".join(map(lambda filterval: "(%s == %s)" % (filterval, filterVarAccess), vulkanType.filterVals))
431
432        if None != vulkanType.filterFunc:
433            filterFuncExpr = self.genFilterFunc(vulkanType.filterFunc, self.currentStructInfo.environment)
434
435        if None != filterValsExpr and None != filterFuncExpr:
436            filterExpr = "%s || %s" % (filterValsExpr, filterFuncExpr)
437        elif None == filterValsExpr and None == filterFuncExpr:
438            # Assume is bool
439            self.cgen.beginIf(filterVarAccess)
440        elif None != filterValsExpr:
441            self.cgen.beginIf("(!(%s) || (%s))" % (filterFeature, filterValsExpr))
442        elif None != filterFuncExpr:
443            self.cgen.beginIf("(!(%s) || (%s))" % (filterFeature, filterFuncExpr))
444
445    def endFilterGuard(self, vulkanType, cleanupExpr=None):
446        if vulkanType.filterVar == None:
447            return
448
449        if self.doFiltering == False:
450            return
451
452        if cleanupExpr == None:
453            self.cgen.endIf()
454        else:
455            self.cgen.endIf()
456            self.cgen.beginElse()
457            self.cgen.stmt(cleanupExpr)
458            self.cgen.endElse()
459
460    def getEnvAccessExpr(self, varName):
461        parentEnvEntry = self.currentStructInfo.environment.get(varName, None)
462
463        if parentEnvEntry != None:
464            isParentMember = parentEnvEntry["structmember"]
465
466            if isParentMember:
467                envAccess = self.exprValueAccessor(list(filter(lambda member: member.paramName == varName, self.currentStructInfo.members))[0])
468            else:
469                envAccess = varName
470            return envAccess
471
472        return None
473
474    def getPointerIndirectionLevels(self, varName):
475        parentEnvEntry = self.currentStructInfo.environment.get(varName, None)
476
477        if parentEnvEntry != None:
478            isParentMember = parentEnvEntry["structmember"]
479
480            if isParentMember:
481                return list(filter(lambda member: member.paramName == varName, self.currentStructInfo.members))[0].pointerIndirectionLevels
482            else:
483                return 0
484            return 0
485
486        return 0
487
488
489    def onCompoundType(self, vulkanType):
490
491        access = self.exprAccessor(vulkanType)
492        lenAccess = self.lenAccessor(vulkanType)
493
494        self.beginFilterGuard(vulkanType)
495
496        if vulkanType.pointerIndirectionLevels > 0:
497            self.doAllocSpace(vulkanType)
498
499        if lenAccess is not None:
500            loopVar = "i"
501            access = "%s + %s" % (access, loopVar)
502            forInit = "uint32_t %s = 0" % loopVar
503            forCond = "%s < (uint32_t)%s" % (loopVar, lenAccess)
504            forIncr = "++%s" % loopVar
505            self.cgen.beginFor(forInit, forCond, forIncr)
506
507        accessWithCast = "%s(%s)" % (self.makeCastExpr(
508            self.getTypeForStreaming(vulkanType)), access)
509
510        callParams = [self.streamVarName, self.rootTypeVarName, accessWithCast, self.ptrVar]
511
512        for (bindName, localName) in vulkanType.binds.items():
513            callParams.append(self.getEnvAccessExpr(localName))
514
515        self.cgen.funcCall(None, self.marshalPrefix + vulkanType.typeName,
516                           callParams)
517
518        if lenAccess is not None:
519            self.cgen.endFor()
520
521        if self.direction == "read":
522            self.endFilterGuard(vulkanType, "%s = 0" % self.exprAccessor(vulkanType))
523        else:
524            self.endFilterGuard(vulkanType)
525
526    def onString(self, vulkanType):
527        access = self.exprAccessor(vulkanType)
528
529        if self.direction == "write":
530            self.cgen.beginBlock()
531            self.cgen.stmt("uint32_t l = %s ? strlen(%s): 0" % (access, access))
532            self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&l", "sizeof(uint32_t)", toBe = True, actualSize = 4)
533            self.genMemcpyAndIncr(self.ptrVar, "(char*)", access, "l")
534            self.cgen.endBlock()
535        else:
536            castExpr = \
537                self.makeCastExpr( \
538                    self.getTypeForStreaming( \
539                        vulkanType.getForAddressAccess()))
540            self.cgen.stmt( \
541                "%s->loadStringInPlaceWithStreamPtr(%s&%s, %s)" % (self.streamVarName, castExpr, access, self.ptrVar))
542
543    def onStringArray(self, vulkanType):
544        access = self.exprAccessor(vulkanType)
545        lenAccess = self.lenAccessor(vulkanType)
546        lenAccessGuard = self.lenAccessorGuard(vulkanType)
547
548        if self.direction == "write":
549            self.cgen.beginBlock()
550
551            self.cgen.stmt("uint32_t c = 0")
552            if lenAccessGuard is not None:
553                self.cgen.beginIf(lenAccessGuard)
554            self.cgen.stmt("c = %s" % (lenAccess))
555            if lenAccessGuard is not None:
556                self.cgen.endIf()
557            self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&c", "sizeof(uint32_t)", toBe = True, actualSize = 4)
558
559            self.cgen.beginFor("uint32_t i = 0", "i < c", "++i")
560            self.cgen.stmt("uint32_t l = %s ? strlen(%s[i]): 0" % (access, access))
561            self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&l", "sizeof(uint32_t)", toBe = True, actualSize = 4)
562            self.cgen.beginIf("l")
563            self.genMemcpyAndIncr(self.ptrVar, "(char*)", "(%s[i])" % access, "l")
564            self.cgen.endIf()
565            self.cgen.endFor()
566
567            self.cgen.endBlock()
568        else:
569            castExpr = \
570                self.makeCastExpr( \
571                    self.getTypeForStreaming( \
572                        vulkanType.getForAddressAccess()))
573
574            self.cgen.stmt("%s->loadStringArrayInPlaceWithStreamPtr(%s&%s, %s)" % (self.streamVarName, castExpr, access, self.ptrVar))
575
576    def onStaticArr(self, vulkanType):
577        access = self.exprValueAccessor(vulkanType)
578        lenAccess = self.lenAccessor(vulkanType)
579        finalLenExpr = "%s * %s" % (lenAccess, self.cgen.sizeofExpr(vulkanType))
580        self.genStreamCall(vulkanType, access, finalLenExpr)
581
582    # Old version VkEncoder may have some sType values conflict with VkDecoder
583    # of new versions. For host decoder, it should not carry the incorrect old
584    # sType values to the |forUnmarshaling| struct. Instead it should overwrite
585    # the sType value.
586    def overwriteSType(self, vulkanType):
587        if self.direction == "read":
588            sTypeParam = copy(vulkanType)
589            sTypeParam.paramName = "sType"
590            sTypeAccess = self.exprAccessor(sTypeParam)
591
592            typeName = vulkanType.parent.typeName
593            if typeName in STYPE_OVERRIDE:
594                self.cgen.stmt("%s = %s" %
595                               (sTypeAccess, STYPE_OVERRIDE[typeName]))
596
597    def onStructExtension(self, vulkanType):
598        self.overwriteSType(vulkanType)
599
600        sTypeParam = copy(vulkanType)
601        sTypeParam.paramName = "sType"
602
603        access = self.exprAccessor(vulkanType)
604        sizeVar = "%s_size" % vulkanType.paramName
605
606        if self.direction == "read":
607            castedAccessExpr = "(%s)(%s)" % ("void*", access)
608        else:
609            castedAccessExpr = access
610
611        sTypeAccess = self.exprAccessor(sTypeParam)
612        self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" % self.rootTypeVarName)
613        self.cgen.stmt("%s = %s" % (self.rootTypeVarName, sTypeAccess))
614        self.cgen.endIf()
615
616        if self.direction == "read" and self.dynAlloc:
617            self.cgen.stmt("uint32_t %s" % sizeVar)
618
619            self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)", "&" + sizeVar, "sizeof(uint32_t)", toBe = True, actualSize = 4)
620
621            self.cgen.stmt("%s = nullptr" % access)
622            self.cgen.beginIf(sizeVar)
623            self.cgen.stmt( \
624                    "%s->alloc((void**)&%s, sizeof(VkStructureType))" %
625                    (self.streamVarName, access))
626
627            self.genStreamCall(vulkanType, access, "sizeof(VkStructureType)")
628            self.cgen.stmt("VkStructureType extType = *(VkStructureType*)(%s)" % access)
629            self.cgen.stmt( \
630                    "%s->alloc((void**)&%s, %s(%s->getFeatureBits(), %s, %s))" %
631                    (self.streamVarName, access, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME, self.streamVarName, self.rootTypeVarName, access))
632            self.cgen.stmt("*(VkStructureType*)%s = extType" % access)
633
634            self.cgen.funcCall(None, self.marshalPrefix + "extension_struct",
635                [self.streamVarName, self.rootTypeVarName, castedAccessExpr, self.ptrVar])
636            self.cgen.endIf()
637        else:
638
639            self.cgen.funcCall(None, self.marshalPrefix + "extension_struct",
640                [self.streamVarName, self.rootTypeVarName, castedAccessExpr, self.ptrVar])
641
642    def onPointer(self, vulkanType):
643        access = self.exprAccessor(vulkanType)
644
645        lenAccess = self.lenAccessor(vulkanType)
646        lenAccessGuard = self.lenAccessorGuard(vulkanType)
647
648        self.beginFilterGuard(vulkanType)
649        self.doAllocSpace(vulkanType)
650
651        if vulkanType.filterVar != None:
652            print("onPointer Needs filter: %s filterVar %s" % (access, vulkanType.filterVar))
653
654        if vulkanType.isHandleType() and self.mapHandles:
655            self.genHandleMappingCall(
656                vulkanType, access, lenAccess, lenAccessGuard)
657        else:
658            if self.typeInfo.isNonAbiPortableType(vulkanType.typeName):
659                if lenAccess is not None:
660                    if lenAccessGuard is not None:
661                        self.cgen.beginIf(lenAccessGuard)
662                    self.cgen.beginFor("uint32_t i = 0", "i < (uint32_t)%s" % lenAccess, "++i")
663                    self.genPrimitiveStreamCall(vulkanType.getForValueAccess(), "%s[i]" % access)
664                    self.cgen.endFor()
665                    if lenAccessGuard is not None:
666                        self.cgen.endIf()
667                else:
668                    self.genPrimitiveStreamCall(vulkanType.getForValueAccess(), "(*%s)" % access)
669            else:
670                if lenAccess is not None:
671                    finalLenExpr = "%s * %s" % (
672                        lenAccess, self.cgen.sizeofExpr(vulkanType.getForValueAccess()))
673                else:
674                    finalLenExpr = "%s" % (
675                        self.cgen.sizeofExpr(vulkanType.getForValueAccess()))
676                self.genStreamCall(vulkanType, access, finalLenExpr)
677
678        if self.direction == "read":
679            self.endFilterGuard(vulkanType, "%s = 0" % access)
680        else:
681            self.endFilterGuard(vulkanType)
682
683    def onValue(self, vulkanType):
684        self.beginFilterGuard(vulkanType)
685
686        if vulkanType.isHandleType() and self.mapHandles:
687            access = self.exprAccessor(vulkanType)
688            if vulkanType.filterVar != None:
689                print("onValue Needs filter: %s filterVar %s" % (access, vulkanType.filterVar))
690            self.genHandleMappingCall(
691                vulkanType.getForAddressAccess(), access, "1", None)
692        elif self.typeInfo.isNonAbiPortableType(vulkanType.typeName):
693            access = self.exprPrimitiveValueAccessor(vulkanType)
694            self.genPrimitiveStreamCall(vulkanType, access)
695        else:
696            access = self.exprAccessor(vulkanType)
697            self.genStreamCall(vulkanType, access, self.cgen.sizeofExpr(vulkanType))
698
699        self.endFilterGuard(vulkanType)
700
701    def streamLetParameter(self, structInfo, letParamInfo):
702        filterFeature = "%s->getFeatureBits() & VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT" % self.streamVarName
703        self.cgen.stmt("%s %s = 1" % (letParamInfo.typeName, letParamInfo.paramName))
704
705        self.cgen.beginIf(filterFeature)
706
707        if self.direction == "write":
708            bodyExpr = self.currentStructInfo.environment[letParamInfo.paramName]["body"]
709            self.cgen.stmt("%s = %s" % (letParamInfo.paramName, self.genFilterFunc(bodyExpr, self.currentStructInfo.environment)))
710
711        self.genPrimitiveStreamCall(letParamInfo, letParamInfo.paramName)
712
713        self.cgen.endIf()
714
715class VulkanReservedMarshaling(VulkanWrapperGenerator):
716
717    def __init__(self, module, typeInfo, variant="host"):
718        VulkanWrapperGenerator.__init__(self, module, typeInfo)
719
720        self.cgenHeader = CodeGen()
721        self.cgenImpl = CodeGen()
722
723        self.variant = variant
724
725        self.currentFeature = None
726        self.apiOpcodes = {}
727        self.dynAlloc = self.variant != "guest"
728        self.ptrVarName = "ptr"
729        self.ptrVarType = makeVulkanTypeSimple(False, "uint8_t", 2, self.ptrVarName)
730        self.ptrVarTypeUnmarshal = makeVulkanTypeSimple(False, "uint8_t", 2, self.ptrVarName)
731
732        if self.variant == "guest":
733            self.marshalingParams = PARAMETERS_MARSHALING_GUEST
734        else:
735            self.marshalingParams = PARAMETERS_MARSHALING
736
737        self.writeCodegen = \
738            VulkanReservedMarshalingCodegen(
739                None,
740                VULKAN_STREAM_VAR_NAME,
741                ROOT_TYPE_VAR_NAME,
742                MARSHAL_INPUT_VAR_NAME,
743                self.ptrVarName,
744                API_PREFIX_RESERVEDMARSHAL,
745                "get_host_u64_" if "guest" == self.variant else "",
746                direction = "write")
747
748        self.readCodegen = \
749            VulkanReservedMarshalingCodegen(
750                None,
751                VULKAN_STREAM_VAR_NAME,
752                ROOT_TYPE_VAR_NAME,
753                UNMARSHAL_INPUT_VAR_NAME,
754                self.ptrVarName,
755                API_PREFIX_RESERVEDUNMARSHAL,
756                "unbox_" if "host" == self.variant else "",
757                direction = "read",
758                dynAlloc=self.dynAlloc)
759
760        self.knownDefs = {}
761
762        self.extensionMarshalPrototype = \
763            VulkanAPI(API_PREFIX_RESERVEDMARSHAL + "extension_struct",
764                      STREAM_RET_TYPE,
765                      self.marshalingParams +
766                      [STRUCT_EXTENSION_PARAM, self.ptrVarType])
767
768        self.extensionUnmarshalPrototype = \
769            VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + "extension_struct",
770                      STREAM_RET_TYPE,
771                      self.marshalingParams +
772                      [STRUCT_EXTENSION_PARAM_FOR_WRITE, self.ptrVarTypeUnmarshal])
773
774    def onBegin(self,):
775        VulkanWrapperGenerator.onBegin(self)
776        self.module.appendImpl(self.cgenImpl.makeFuncDecl(self.extensionMarshalPrototype))
777        self.module.appendImpl(self.cgenImpl.makeFuncDecl(self.extensionUnmarshalPrototype))
778
779    def onBeginFeature(self, featureName, featureType):
780        VulkanWrapperGenerator.onBeginFeature(self, featureName, featureType)
781        self.currentFeature = featureName
782
783    def onGenType(self, typeXml, name, alias):
784        VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
785
786        if name in self.knownDefs:
787            return
788
789        category = self.typeInfo.categoryOf(name)
790
791        if category in ["struct", "union"] and alias:
792            if self.variant != "host":
793                self.module.appendHeader(
794                    self.cgenHeader.makeFuncAlias(API_PREFIX_RESERVEDMARSHAL + name,
795                                                  API_PREFIX_RESERVEDMARSHAL + alias))
796            if self.variant != "guest":
797                self.module.appendHeader(
798                    self.cgenHeader.makeFuncAlias(API_PREFIX_RESERVEDUNMARSHAL + name,
799                                                  API_PREFIX_RESERVEDUNMARSHAL + alias))
800
801        if category in ["struct", "union"] and not alias:
802
803            structInfo = self.typeInfo.structs[name]
804
805            marshalParams = self.marshalingParams + \
806                [makeVulkanTypeSimple(True, name, 1, MARSHAL_INPUT_VAR_NAME),
807                        self.ptrVarType]
808
809            freeParams = []
810            letParams = []
811
812            for (envname, bindingInfo) in list(sorted(structInfo.environment.items(), key = lambda kv: kv[0])):
813                if None == bindingInfo["binding"]:
814                    freeParams.append(makeVulkanTypeSimple(True, bindingInfo["type"], 0, envname))
815                else:
816                    if not bindingInfo["structmember"]:
817                        letParams.append(makeVulkanTypeSimple(True, bindingInfo["type"], 0, envname))
818
819            marshalPrototype = \
820                VulkanAPI(API_PREFIX_RESERVEDMARSHAL + name,
821                          STREAM_RET_TYPE,
822                          marshalParams + freeParams)
823
824            marshalPrototypeNoFilter = \
825                VulkanAPI(API_PREFIX_RESERVEDMARSHAL + name,
826                          STREAM_RET_TYPE,
827                          marshalParams)
828
829            def structMarshalingCustom(cgen):
830                self.writeCodegen.cgen = cgen
831                self.writeCodegen.currentStructInfo = structInfo
832                marshalingCode = \
833                    CUSTOM_MARSHAL_TYPES[name]["common"] + \
834                    CUSTOM_MARSHAL_TYPES[name]["reservedmarshaling"].format(
835                        streamVarName=self.writeCodegen.streamVarName,
836                        rootTypeVarName=self.writeCodegen.rootTypeVarName,
837                        inputVarName=self.writeCodegen.inputVarName,
838                        newInputVarName=self.writeCodegen.inputVarName + "_new")
839                for line in marshalingCode.split('\n'):
840                    cgen.line(line)
841
842            def structMarshalingDef(cgen):
843                self.writeCodegen.cgen = cgen
844                self.writeCodegen.currentStructInfo = structInfo
845                self.writeCodegen.cgen.stmt("(void)%s" % VULKAN_STREAM_VAR_NAME)
846                self.writeCodegen.cgen.stmt("(void)%s" % ROOT_TYPE_VAR_NAME)
847
848                if category == "struct":
849                    # marshal 'let' parameters first
850                    for letp in letParams:
851                        self.writeCodegen.streamLetParameter(self.typeInfo, letp)
852
853                    for member in structInfo.members:
854                        iterateVulkanType(self.typeInfo, member, self.writeCodegen)
855                if category == "union":
856                    iterateVulkanType(self.typeInfo, structInfo.members[0], self.writeCodegen)
857
858            def structMarshalingDefNoFilter(cgen):
859                self.writeCodegen.cgen = cgen
860                self.writeCodegen.currentStructInfo = structInfo
861                self.writeCodegen.doFiltering = False
862                self.writeCodegen.cgen.stmt("(void)%s" % VULKAN_STREAM_VAR_NAME)
863                self.writeCodegen.cgen.stmt("(void)%s" % ROOT_TYPE_VAR_NAME)
864
865                if category == "struct":
866                    # marshal 'let' parameters first
867                    for letp in letParams:
868                        self.writeCodegen.streamLetParameter(self.typeInfo, letp)
869
870                    for member in structInfo.members:
871                        iterateVulkanType(self.typeInfo, member, self.writeCodegen)
872                if category == "union":
873                    iterateVulkanType(self.typeInfo, structInfo.members[0], self.writeCodegen)
874                self.writeCodegen.doFiltering = True
875
876            if self.variant != "host":
877                self.module.appendHeader(
878                    self.cgenHeader.makeFuncDecl(marshalPrototype))
879
880                if name in CUSTOM_MARSHAL_TYPES:
881                    self.module.appendImpl(
882                        self.cgenImpl.makeFuncImpl(
883                            marshalPrototype, structMarshalingCustom))
884                else:
885                    self.module.appendImpl(
886                        self.cgenImpl.makeFuncImpl(
887                            marshalPrototype, structMarshalingDef))
888
889                if freeParams != []:
890                    self.module.appendHeader(
891                        self.cgenHeader.makeFuncDecl(marshalPrototypeNoFilter))
892                    self.module.appendImpl(
893                        self.cgenImpl.makeFuncImpl(
894                            marshalPrototypeNoFilter, structMarshalingDefNoFilter))
895
896            unmarshalPrototype = \
897                VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + name,
898                          STREAM_RET_TYPE,
899                          self.marshalingParams + [makeVulkanTypeSimple(False, name, 1, UNMARSHAL_INPUT_VAR_NAME), self.ptrVarTypeUnmarshal] + freeParams)
900
901            unmarshalPrototypeNoFilter = \
902                VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + name,
903                          STREAM_RET_TYPE,
904                          self.marshalingParams + [makeVulkanTypeSimple(False, name, 1, UNMARSHAL_INPUT_VAR_NAME), self.ptrVarTypeUnmarshal])
905
906            def structUnmarshalingCustom(cgen):
907                self.readCodegen.cgen = cgen
908                self.readCodegen.currentStructInfo = structInfo
909                unmarshalingCode = \
910                    CUSTOM_MARSHAL_TYPES[name]["common"] + \
911                    CUSTOM_MARSHAL_TYPES[name]["reservedunmarshaling"].format(
912                        streamVarName=self.readCodegen.streamVarName,
913                        rootTypeVarName=self.readCodegen.rootTypeVarName,
914                        inputVarName=self.readCodegen.inputVarName,
915                        newInputVarName=self.readCodegen.inputVarName + "_new")
916                for line in unmarshalingCode.split('\n'):
917                    cgen.line(line)
918
919            def structUnmarshalingDef(cgen):
920                self.readCodegen.cgen = cgen
921                self.readCodegen.currentStructInfo = structInfo
922                if category == "struct":
923                    # unmarshal 'let' parameters first
924                    for letp in letParams:
925                        self.readCodegen.streamLetParameter(self.typeInfo, letp)
926
927                    for member in structInfo.members:
928                        iterateVulkanType(self.typeInfo, member, self.readCodegen)
929                if category == "union":
930                    iterateVulkanType(self.typeInfo, structInfo.members[0], self.readCodegen)
931
932            def structUnmarshalingDefNoFilter(cgen):
933                self.readCodegen.cgen = cgen
934                self.readCodegen.currentStructInfo = structInfo
935                self.readCodegen.doFiltering = False
936                if category == "struct":
937                    # unmarshal 'let' parameters first
938                    for letp in letParams:
939                        iterateVulkanType(self.typeInfo, letp, self.readCodegen)
940                    for member in structInfo.members:
941                        iterateVulkanType(self.typeInfo, member, self.readCodegen)
942                if category == "union":
943                    iterateVulkanType(self.typeInfo, structInfo.members[0], self.readCodegen)
944                self.readCodegen.doFiltering = True
945
946            if self.variant != "guest":
947                self.module.appendHeader(
948                    self.cgenHeader.makeFuncDecl(unmarshalPrototype))
949
950                if name in CUSTOM_MARSHAL_TYPES:
951                    self.module.appendImpl(
952                        self.cgenImpl.makeFuncImpl(
953                            unmarshalPrototype, structUnmarshalingCustom))
954                else:
955                    self.module.appendImpl(
956                        self.cgenImpl.makeFuncImpl(
957                            unmarshalPrototype, structUnmarshalingDef))
958
959                if freeParams != []:
960                    self.module.appendHeader(
961                        self.cgenHeader.makeFuncDecl(unmarshalPrototypeNoFilter))
962                    self.module.appendImpl(
963                        self.cgenImpl.makeFuncImpl(
964                            unmarshalPrototypeNoFilter, structUnmarshalingDefNoFilter))
965
966    def onGenCmd(self, cmdinfo, name, alias):
967        VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
968
969    def doExtensionStructMarshalingCodegen(self, cgen, retType, extParam, forEach, funcproto, direction):
970        accessVar = "structAccess"
971        sizeVar = "currExtSize"
972        cgen.stmt("VkInstanceCreateInfo* %s = (VkInstanceCreateInfo*)(%s)" % (accessVar, extParam.paramName))
973        cgen.stmt("uint32_t %s = %s(%s->getFeatureBits(), %s, %s)" % (sizeVar, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME, VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, extParam.paramName))
974
975        cgen.beginIf("!%s && %s" % (sizeVar, extParam.paramName))
976
977        cgen.line("// unknown struct extension; skip and call on its pNext field");
978        cgen.funcCall(None, funcproto.name, ["vkStream", ROOT_TYPE_VAR_NAME, "(void*)%s->pNext" % accessVar, self.ptrVarName])
979        cgen.stmt("return")
980
981        cgen.endIf()
982        cgen.beginElse()
983
984        cgen.line("// known or null extension struct")
985
986        if direction == "write":
987            cgen.stmt("memcpy(*%s, &%s, sizeof(uint32_t));" % (self.ptrVarName, sizeVar))
988            cgen.stmt("android::base::Stream::toBe32((uint8_t*)*%s); *%s += sizeof(uint32_t)" % (self.ptrVarName, self.ptrVarName))
989        elif not self.dynAlloc:
990            cgen.stmt("memcpy(&%s, *%s, sizeof(uint32_t));" % (sizeVar, self.ptrVarName))
991            cgen.stmt("android::base::Stream::fromBe32((uint8_t*)&%s); *%s += sizeof(uint32_t)" % (sizeVar, self.ptrVarName))
992
993        cgen.beginIf("!%s" % (sizeVar))
994        cgen.line("// exit if this was a null extension struct (size == 0 in this branch)")
995        cgen.stmt("return")
996        cgen.endIf()
997
998        cgen.endIf()
999
1000        # Now we can do stream stuff
1001        if direction == "write":
1002            cgen.stmt("memcpy(*%s, %s, sizeof(VkStructureType)); *%s += sizeof(VkStructureType)" % (self.ptrVarName, extParam.paramName, self.ptrVarName))
1003        elif not self.dynAlloc:
1004            cgen.stmt("uint64_t pNext_placeholder")
1005            placeholderAccess = "(&pNext_placeholder)"
1006            cgen.stmt("memcpy(%s, *%s, sizeof(VkStructureType)); *%s += sizeof(VkStructureType)" % (placeholderAccess, self.ptrVarName, self.ptrVarName))
1007            cgen.stmt("(void)pNext_placeholder")
1008
1009        def fatalDefault(cgen):
1010            cgen.line("// fatal; the switch is only taken if the extension struct is known");
1011            cgen.stmt("abort()")
1012            pass
1013
1014        self.emitForEachStructExtension(
1015            cgen,
1016            retType,
1017            extParam,
1018            forEach,
1019            defaultEmit=fatalDefault,
1020            rootTypeVar=ROOT_TYPE_PARAM)
1021
1022    def onEnd(self,):
1023        VulkanWrapperGenerator.onEnd(self)
1024
1025        def forEachExtensionMarshal(ext, castedAccess, cgen):
1026            cgen.funcCall(None, API_PREFIX_RESERVEDMARSHAL + ext.name,
1027                          [VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, castedAccess, self.ptrVarName])
1028
1029        def forEachExtensionUnmarshal(ext, castedAccess, cgen):
1030            cgen.funcCall(None, API_PREFIX_RESERVEDUNMARSHAL + ext.name,
1031                          [VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, castedAccess, self.ptrVarName])
1032
1033        if self.variant != "host":
1034            self.module.appendImpl(
1035                self.cgenImpl.makeFuncImpl(
1036                    self.extensionMarshalPrototype,
1037                    lambda cgen: self.doExtensionStructMarshalingCodegen(
1038                        cgen,
1039                        STREAM_RET_TYPE,
1040                        STRUCT_EXTENSION_PARAM,
1041                        forEachExtensionMarshal,
1042                        self.extensionMarshalPrototype,
1043                        "write")))
1044
1045        if self.variant != "guest":
1046            self.module.appendImpl(
1047                self.cgenImpl.makeFuncImpl(
1048                    self.extensionUnmarshalPrototype,
1049                    lambda cgen: self.doExtensionStructMarshalingCodegen(
1050                        cgen,
1051                        STREAM_RET_TYPE,
1052                        STRUCT_EXTENSION_PARAM_FOR_WRITE,
1053                        forEachExtensionUnmarshal,
1054                        self.extensionUnmarshalPrototype,
1055                        "read")))
1056