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