1057 lines
42 KiB
Python
Executable File
1057 lines
42 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright (C) 2020 Apple Inc. All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions
|
|
# are met:
|
|
#
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
|
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
# This script generates the source files for WebGL GPU process IPC.
|
|
#
|
|
# python3 -m black -l 150 Tools/Scripts/generate-gpup-webgl
|
|
# python3 -m mypy Tools/Scripts/generate-gpup-webgl
|
|
#
|
|
import argparse
|
|
import enum
|
|
import pathlib
|
|
import re
|
|
import sys
|
|
import collections
|
|
|
|
from typing import List, Dict, Iterable, Callable, Tuple, Set, Optional, Generator, Iterator, Counter
|
|
|
|
root_dir = (pathlib.Path(__file__).parent / ".." / "..").resolve()
|
|
extensions_input_fn = root_dir / "Source" / "WebCore" / "platform" / "graphics" / "ExtensionsGL.h"
|
|
|
|
functions_input_fns = [
|
|
root_dir / "Source" / "WebKit" / "WebProcess" / "GPU" / "graphics" / "RemoteGraphicsContextGLProxy.h"
|
|
]
|
|
types_input_fn = root_dir / "Source" / "WebKit" / "WebProcess" / "GPU" / "graphics" / "RemoteGraphicsContextGLProxy.h"
|
|
|
|
|
|
template_preamble = """/* Copyright (C) 2020 Apple Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
// This file is generated by generate-gpup-webgl. Do not edit.
|
|
"""
|
|
context_functions_fn = root_dir / "Source" / "WebKit" / "GPUProcess" / "graphics" / "RemoteGraphicsContextGLFunctionsGenerated.h"
|
|
context_functions_template = (
|
|
template_preamble
|
|
+ """// This file should be included in the private section of the
|
|
// RemoteGraphicsContextGL implementations.
|
|
#pragma once
|
|
{}
|
|
|
|
"""
|
|
)
|
|
context_messages_fn = root_dir / "Source" / "WebKit" / "GPUProcess" / "graphics" / "RemoteGraphicsContextGL.messages.in"
|
|
context_messages_template = (
|
|
template_preamble
|
|
+ """#if ENABLE(GPU_PROCESS) && ENABLE(WEBGL)
|
|
|
|
messages -> RemoteGraphicsContextGL NotRefCounted Stream {{
|
|
void Reshape(int32_t width, int32_t height)
|
|
#if PLATFORM(COCOA)
|
|
void PrepareForDisplay() -> (MachSendRight displayBuffer) Synchronous NotStreamEncodableReply
|
|
#endif
|
|
#if !PLATFORM(COCOA)
|
|
void PrepareForDisplay() -> () Synchronous
|
|
#endif
|
|
void EnsureExtensionEnabled(String extension)
|
|
void NotifyMarkContextChanged()
|
|
void SynthesizeGLError(uint32_t error)
|
|
void GetError() -> (uint32_t returnValue) Synchronous
|
|
void PaintRenderingResultsToCanvas(WebCore::RenderingResourceIdentifier imageBuffer) -> () Synchronous
|
|
void PaintCompositedResultsToCanvas(WebCore::RenderingResourceIdentifier imageBuffer) -> () Synchronous
|
|
void CopyTextureFromMedia(WebCore::MediaPlayerIdentifier identifier, uint32_t texture, uint32_t target, int32_t level, uint32_t internalFormat, uint32_t format, uint32_t type, bool premultiplyAlpha, bool flipY) -> (bool success) Synchronous
|
|
void SimulateEventForTesting(WebCore::GraphicsContextGL::SimulatedEventForTesting event)
|
|
{}
|
|
}}
|
|
|
|
#endif
|
|
"""
|
|
)
|
|
|
|
context_proxy_functions_fn = root_dir / "Source" / "WebKit" / "WebProcess" / "GPU" / "graphics" / "RemoteGraphicsContextGLProxyFunctionsGenerated.cpp"
|
|
context_proxy_functions_template = (
|
|
template_preamble
|
|
+ """
|
|
#include "config.h"
|
|
#include "RemoteGraphicsContextGLProxy.h"
|
|
|
|
#if ENABLE(GPU_PROCESS) && ENABLE(WEBGL)
|
|
|
|
namespace WebKit {{
|
|
{}
|
|
|
|
}}
|
|
|
|
#endif
|
|
|
|
"""
|
|
)
|
|
|
|
|
|
def write_file(fn, new_contents):
|
|
try:
|
|
with open(fn) as f:
|
|
if f.read() == new_contents:
|
|
return
|
|
except:
|
|
pass
|
|
with open(fn, "w") as f:
|
|
f.write(new_contents)
|
|
|
|
class cpp_type(object):
|
|
type_name: str
|
|
|
|
def __init__(self, type_name : str):
|
|
self.type_name = type_name
|
|
|
|
def __str__(self):
|
|
return self.type_name
|
|
|
|
def __hash__(self):
|
|
return hash(self.type_name)
|
|
|
|
def __repr__(self):
|
|
return self.type_name
|
|
|
|
def __eq__(self, other):
|
|
return self.type_name == other.type_name
|
|
|
|
def is_void(self) -> bool:
|
|
return self.type_name in ["void", "GCGLvoid", "const void", "const GCGLvoid"]
|
|
|
|
def is_const(self) -> bool:
|
|
return self.type_name.startswith("const ")
|
|
|
|
def is_container(self) -> bool:
|
|
return False
|
|
|
|
def is_output_buffer_type(self) -> bool:
|
|
return False
|
|
|
|
def is_span(self) -> bool:
|
|
return False
|
|
|
|
def is_dynamic_span(self) -> bool:
|
|
return False
|
|
|
|
def is_pointer(self) -> bool:
|
|
return False
|
|
|
|
def is_const_pointer(self) -> bool:
|
|
return False
|
|
|
|
def is_reference(self) -> bool:
|
|
return False
|
|
|
|
def is_const_reference(self) -> bool:
|
|
return False
|
|
|
|
def get_value_type(self) -> 'cpp_type':
|
|
return self
|
|
|
|
def get_decay_type(self) -> 'cpp_type':
|
|
if self.is_const():
|
|
return get_cpp_type(self.type_name[6:])
|
|
return self
|
|
|
|
def get_rvalue_type(self) -> 'cpp_type':
|
|
return get_cpp_type(self.type_name + "&&")
|
|
|
|
def get_pointer_type(self) -> 'cpp_type':
|
|
return get_cpp_type(self.type_name + "*")
|
|
|
|
class cpp_type_container(cpp_type):
|
|
def __init__(self, type_name : str, container_name : str, contained_type : cpp_type, arity : Optional[int] = None):
|
|
cpp_type.__init__(self, type_name)
|
|
self.container_name = container_name
|
|
self.contained_type = contained_type
|
|
self.arity = arity
|
|
def is_container(self) -> bool:
|
|
return True
|
|
def is_span(self) -> bool:
|
|
return self.container_name == "GCGLSpan"
|
|
def is_dynamic_span(self) -> bool:
|
|
return self.container_name == "GCGLSpan" and self.arity is None
|
|
def get_container_name(self):
|
|
return self.container_name
|
|
def get_arity(self) -> Optional[int]:
|
|
return self.arity
|
|
def get_contained_type(self) -> cpp_type:
|
|
return self.contained_type
|
|
def is_output_buffer_type(self) -> bool:
|
|
return self.contained_type.is_const()
|
|
|
|
def create_cpp_type_container(type_name : str) -> Optional[cpp_type_container]:
|
|
# The logic to determine container is to just assume all templates are containers.
|
|
m = re.match(r"([\w:]+)<(.+)>$", type_name)
|
|
if not m:
|
|
return None
|
|
container_name = m[1]
|
|
# All templates are containers except these below.
|
|
if container_name in ['RefPtr', 'Ref']:
|
|
return None
|
|
templates = m[2]
|
|
arity = None
|
|
m = re.match(r"([^,]+),\s*(\d+)", templates)
|
|
if m:
|
|
templates = m[1]
|
|
arity = int(m[2])
|
|
return cpp_type_container(type_name, container_name, get_cpp_type(templates), arity)
|
|
|
|
class cpp_type_function(cpp_type):
|
|
def __init__(self, type_name : str, return_value_type : cpp_type, argument_types : List[cpp_type]):
|
|
cpp_type.__init__(self, type_name)
|
|
self.return_value_type = return_value_type
|
|
self.argument_types = argument_types
|
|
|
|
def cpp_split_args_specs(args_spec : str) -> Iterator[str]:
|
|
# https://stackoverflow.com/questions/33527245/python-split-by-comma-skipping-the-content-inside-parentheses
|
|
comma = r",(?!(?:[^<]*\<[^>]*\>)*[^<>]*\>)"
|
|
return filter(None, [a.strip() for a in re.split(comma, args_spec.strip())])
|
|
|
|
def create_cpp_type_function(type_name : str) -> Optional[cpp_type_function]:
|
|
m = re.match(r'(.*)\((.*)\)', type_name)
|
|
if not m:
|
|
return None
|
|
return_value_type = get_cpp_type(m[1])
|
|
args_types = [get_cpp_type(a) for a in cpp_split_args_specs(m[2])]
|
|
return cpp_type_function(type_name, return_value_type, args_types)
|
|
|
|
# Pointer or refererence
|
|
class cpp_type_indirect(cpp_type):
|
|
category : str
|
|
value_type : cpp_type
|
|
|
|
def __init__(self, type_name : str, category : str, value_type : cpp_type):
|
|
cpp_type.__init__(self, type_name)
|
|
self.category = category
|
|
self.value_type = value_type
|
|
|
|
def is_const_pointer(self):
|
|
return self.category == '*' and self.is_const()
|
|
def is_pointer(self):
|
|
return self.category == '*' and not self.is_const()
|
|
def is_const_reference(self):
|
|
return self.category == '&' and self.is_const()
|
|
def is_reference(self):
|
|
return self.category == '&' and not self.is_const()
|
|
def is_rvalue_reference(self):
|
|
return self.category == '&&'
|
|
def get_value_type(self):
|
|
return self.value_type
|
|
|
|
def create_cpp_type_indirect(type_name : str) -> Optional[cpp_type_indirect]:
|
|
m = re.match(r"const (.+)&&$", type_name)
|
|
if not m:
|
|
m = re.match(r"(.+)&&$", type_name)
|
|
if m:
|
|
return cpp_type_indirect(type_name, '&&', get_cpp_type(m[1]))
|
|
m = re.match(r"const (.+)&$", type_name)
|
|
if not m:
|
|
m = re.match(r"(.+)&$", type_name)
|
|
if m:
|
|
return cpp_type_indirect(type_name, '&', get_cpp_type(m[1]))
|
|
m = re.match(r"const (.+)\*$", type_name)
|
|
if not m:
|
|
m = re.match(r"(.+)\*$", type_name)
|
|
if m:
|
|
return cpp_type_indirect(type_name, '*', get_cpp_type(m[1]))
|
|
return None
|
|
|
|
|
|
class cpp_expr(object):
|
|
type: cpp_type
|
|
expr: str
|
|
|
|
def __init__(self, type: cpp_type, expr: str):
|
|
self.type = type
|
|
self.expr = expr
|
|
|
|
def __str__(self):
|
|
return self.expr
|
|
|
|
|
|
CppExprConverter = Callable[[cpp_expr, cpp_type], cpp_expr]
|
|
|
|
|
|
def cpp_reinterpret_cast_from_pointer_through(cast_through_type : cpp_type) -> Callable[[cpp_expr, cpp_type], cpp_expr]:
|
|
def cpp_reinterpret_cast_from_pointer(expr: cpp_expr, type: cpp_type) -> cpp_expr:
|
|
return cpp_expr(type, f"static_cast<{type.type_name}>(reinterpret_cast<{str(cast_through_type)}>({str(expr)}))")
|
|
return cpp_reinterpret_cast_from_pointer
|
|
|
|
def cpp_reinterpret_cast_to_pointer_through(cast_through_type : cpp_type) -> Callable[[cpp_expr, cpp_type], cpp_expr]:
|
|
def cpp_reinterpret_cast_to_pointer(expr: cpp_expr, type: cpp_type) -> cpp_expr:
|
|
return cpp_expr(type, f"reinterpret_cast<{type.type_name}>(static_cast<{str(cast_through_type)}>({str(expr)}))")
|
|
return cpp_reinterpret_cast_to_pointer
|
|
|
|
def cpp_static_cast(expr: cpp_expr, type: cpp_type) -> cpp_expr:
|
|
return cpp_expr(type, f"static_cast<{type.type_name}>({str(expr)})")
|
|
|
|
|
|
def cpp_implicit_cast(expr: cpp_expr, type: cpp_type) -> cpp_expr:
|
|
return cpp_expr(type, str(expr))
|
|
|
|
|
|
def cpp_array_reinterpret_cast_conversion(expr: cpp_expr, type: cpp_type_container) -> cpp_expr:
|
|
element_pointer_type = type.get_contained_type().get_pointer_type()
|
|
return cpp_expr(type, f"{str(type)}(reinterpret_cast<{element_pointer_type}>({str(expr)}.data()), {str(expr)}.size())")
|
|
|
|
def webkit_ipc_span_transfer_type_reinterpret_cast_conversion(expr: cpp_expr, type: cpp_type_container) -> cpp_expr:
|
|
element_pointer_type = type.get_contained_type().get_pointer_type()
|
|
return cpp_expr(type, f"{str(type)}(reinterpret_cast<const {element_pointer_type}>({str(expr)}.data), {str(expr)}.bufSize)")
|
|
|
|
def cpp_move_expr(expr: cpp_expr) -> cpp_expr:
|
|
return cpp_expr(expr.type.get_rvalue_type(), f"WTFMove({str(expr)})")
|
|
|
|
|
|
cpp_types: Dict[str, cpp_type] = {}
|
|
|
|
cpp_type_constructors : List[Callable[[str], Optional[cpp_type]]] = [
|
|
create_cpp_type_function,
|
|
create_cpp_type_container,
|
|
create_cpp_type_indirect
|
|
]
|
|
|
|
def get_cpp_type(type_name: str):
|
|
r = cpp_types.get(type_name, None)
|
|
if r:
|
|
return r
|
|
for type_constr in cpp_type_constructors:
|
|
r = type_constr(type_name)
|
|
if r:
|
|
break
|
|
if not r:
|
|
r = cpp_type(type_name)
|
|
cpp_types[type_name] = r
|
|
return r
|
|
|
|
|
|
class cpp_arg(object):
|
|
name: str
|
|
type: cpp_type
|
|
|
|
def __init__(self, type: cpp_type, name: str):
|
|
self.name = name
|
|
self.type = type
|
|
|
|
def __str__(self):
|
|
return "{} {}".format(self.type, self.name)
|
|
|
|
|
|
class cpp_decl(object):
|
|
type: cpp_type
|
|
name: str
|
|
|
|
def __init__(self, type: cpp_type, name: str):
|
|
self.type = type
|
|
self.name = name
|
|
|
|
def __str__(self):
|
|
return f"{str(self.type)} {self.name}"
|
|
|
|
|
|
class cpp_arg_list(object):
|
|
args: List[cpp_arg]
|
|
|
|
def __init__(self, args: List[cpp_arg]):
|
|
self.args = args
|
|
|
|
def names(self):
|
|
return ", ".join(a.name for a in self.args)
|
|
|
|
def exprs(self):
|
|
return [cpp_expr(a.type, a.name) for a in self.args]
|
|
|
|
def decls(self):
|
|
return [cpp_decl(a.type, a.name) for a in self.args]
|
|
|
|
def types(self):
|
|
return [a.type for a in self.args]
|
|
|
|
def __str__(self):
|
|
return ", ".join(str(a) for a in self.args)
|
|
|
|
|
|
class cpp_func(object):
|
|
name: str
|
|
args: cpp_arg_list
|
|
return_type: cpp_type
|
|
is_extension: bool
|
|
overload_suffix: str
|
|
|
|
def __init__(self, name: str, return_type: cpp_type, args: cpp_arg_list, is_extension: bool):
|
|
self.name = name
|
|
self.return_type = return_type
|
|
self.args = args
|
|
self.is_extension = is_extension
|
|
self.overload_suffix = ""
|
|
|
|
def __str__(self):
|
|
return f"{self.return_type} {self.name}({str(self.args)})"
|
|
|
|
def get_args_categories(self) -> Tuple[List[cpp_arg], List[cpp_arg]]:
|
|
in_args = []
|
|
out_args = []
|
|
for a in self.args.args:
|
|
#fmt: off
|
|
if a.type.is_pointer() or \
|
|
a.type.is_reference():
|
|
out_args += [a]
|
|
elif isinstance(a.type, cpp_type_container) and (((a.type.is_span() or a.type.is_dynamic_span()) and not a.type.get_contained_type().is_const())):
|
|
out_args += [a]
|
|
else:
|
|
in_args += [a]
|
|
#fmt: on
|
|
return in_args, out_args
|
|
|
|
def is_implemented_type(self, type: cpp_type):
|
|
if type.is_const_pointer():
|
|
return False
|
|
return True
|
|
|
|
def is_implemented(self):
|
|
#" in a.type.type_name for a in self.args.args):
|
|
# return False
|
|
#if "GCGLsync" in self.return_type.type_name:
|
|
# return False
|
|
if any(a.name == "bufSize" for a in self.args.args):
|
|
return False
|
|
if any(a.type.is_pointer() and a.type.get_value_type().is_void() for a in self.args.args):
|
|
return False
|
|
if any(not self.is_implemented_type(a.type) for a in self.args.args):
|
|
return False
|
|
if self.return_type.is_pointer():
|
|
return False
|
|
if not self.is_implemented_type(self.return_type):
|
|
return False
|
|
return True
|
|
|
|
|
|
webkit_ipc_types: Dict[cpp_type, cpp_type] = {}
|
|
|
|
webkit_ipc_types_converters: Dict[Tuple[cpp_type, cpp_type], CppExprConverter] = {}
|
|
|
|
|
|
def webkit_ipc_convert_expr(expr: cpp_expr, type: cpp_type) -> cpp_expr:
|
|
""" Converts `expr` of type of `self` to `type` """
|
|
convert = webkit_ipc_types_converters.get((expr.type, type), None)
|
|
if not convert:
|
|
if expr.type == type:
|
|
return expr
|
|
convert = cpp_implicit_cast
|
|
return convert(expr, type)
|
|
|
|
|
|
def webkit_ipc_get_span_transfer_type(type : cpp_type_container) -> cpp_type:
|
|
element_type = type.get_contained_type().get_decay_type()
|
|
arity = type.get_arity()
|
|
webkit_ipc_element_type = webkit_ipc_types[element_type] if not element_type.is_void() else get_cpp_type('uint8_t')
|
|
if arity is not None:
|
|
return get_cpp_type(f"IPC::ArrayReference<{str(webkit_ipc_element_type)}, {arity}>")
|
|
return get_cpp_type(f"IPC::ArrayReference<{str(webkit_ipc_element_type)}>")
|
|
|
|
|
|
|
|
def webkit_ipc_get_span_store_type(type: cpp_type_container) -> cpp_type:
|
|
element_type = type.get_contained_type().get_decay_type()
|
|
if element_type.is_void():
|
|
element_type = get_cpp_type('GCGLchar')
|
|
if type.is_dynamic_span():
|
|
inline_capacity = 16 if "float" in element_type.type_name else 4
|
|
return get_cpp_type(f"Vector<{str(element_type)}, {str(inline_capacity)}>")
|
|
return get_cpp_type(f"std::array<{str(element_type)}, {str(type.get_arity())}>")
|
|
|
|
def webkit_ipc_make_gcglspan_conversion(expr : cpp_expr, type : cpp_type_container) -> cpp_expr:
|
|
pointer_cast_type = type.get_contained_type().get_pointer_type()
|
|
if type.is_dynamic_span():
|
|
return cpp_expr(type, f"makeGCGLSpan(reinterpret_cast<{str(pointer_cast_type)}>({str(expr)}.data()), {str(expr)}.size())")
|
|
|
|
assert(type.is_span())
|
|
return cpp_expr(type, f"makeGCGLSpan<{str(type.get_arity())}>(reinterpret_cast<{str(pointer_cast_type)}>({str(expr)}.data()))")
|
|
|
|
# See messages.py function_parameter_type
|
|
webkit_ipc_builtin_types = set(
|
|
["uint8_t", "uint16_t", "uint32_t", "uint64_t", "int8_t", "int16_t", "int32_t", "int64_t", "bool", "float", "double" "bool"]
|
|
)
|
|
|
|
|
|
def webkit_ipc_get_message_forwarder_type(type: cpp_type) -> cpp_type:
|
|
if type.type_name in webkit_ipc_builtin_types:
|
|
return type
|
|
return type.get_rvalue_type()
|
|
|
|
|
|
def webkit_ipc_move_expr(expr: cpp_expr) -> cpp_expr:
|
|
if expr.type.type_name in webkit_ipc_builtin_types:
|
|
return expr
|
|
return cpp_move_expr(expr)
|
|
|
|
|
|
def webkit_ipc_msg_name(func: cpp_func):
|
|
return func.name[0].capitalize() + func.name[1:] + func.overload_suffix
|
|
|
|
|
|
class webkit_ipc_msg(object):
|
|
name: str
|
|
in_args: cpp_arg_list
|
|
out_args: cpp_arg_list
|
|
|
|
def __init__(self, func: cpp_func):
|
|
self.name = webkit_ipc_msg_name(func)
|
|
in_args, out_args = func.get_args_categories()
|
|
ipc_in_args = [cpp_arg(webkit_ipc_types[a.type], a.name) for a in in_args]
|
|
ipc_out_args = []
|
|
if not func.return_type.is_void():
|
|
ipc_out_args += [cpp_arg(webkit_ipc_types[func.return_type], "returnValue")]
|
|
for a in out_args:
|
|
ipc_out_args += [cpp_arg(webkit_ipc_types[a.type], a.name)]
|
|
if a.type.is_dynamic_span():
|
|
ipc_in_args += [cpp_arg(get_cpp_type("uint64_t"), f"{a.name}Size")]
|
|
self.in_args = cpp_arg_list(ipc_in_args)
|
|
self.out_args = cpp_arg_list(ipc_out_args)
|
|
|
|
def __str__(self):
|
|
if len(self.out_args.args):
|
|
return f"\n void {self.name}({str(self.in_args)}) -> ({str(self.out_args)}) Synchronous"
|
|
return f"\n void {self.name}({str(self.in_args)})"
|
|
|
|
|
|
class webkit_ipc_cpp_proxy_impl(object):
|
|
name: str
|
|
msg_name: str
|
|
return_type: cpp_type
|
|
args: cpp_arg_list
|
|
|
|
pre_call_stmts: List[str]
|
|
call_stmts: List[str]
|
|
post_call_stmts: List[str]
|
|
return_stmts: List[str]
|
|
in_exprs: List[cpp_expr]
|
|
out_exprs: List[cpp_expr]
|
|
|
|
def __init__(self, cpp_func: cpp_func):
|
|
self.name = cpp_func.name
|
|
self.msg_name = webkit_ipc_msg_name(cpp_func)
|
|
self.return_type = cpp_func.return_type
|
|
self.args = cpp_func.args
|
|
self.pre_call_stmts = []
|
|
self.call_stmts = []
|
|
self.post_call_stmts = []
|
|
self.return_stmts = []
|
|
self.in_exprs = []
|
|
self.out_exprs = []
|
|
in_args, out_args = cpp_func.get_args_categories()
|
|
self.process_return_value(cpp_func.return_type)
|
|
self.process_in_args(in_args)
|
|
self.process_out_args(out_args)
|
|
self.process_call()
|
|
|
|
def process_call(self):
|
|
in_exprs = ", ".join([str(i) for i in self.in_exprs])
|
|
out_exprs = ", ".join(str(o) for o in self.out_exprs)
|
|
is_async = self.return_type.is_void() and len(out_exprs) == 0
|
|
self.call_stmts += [ "if (!isContextLost()) {" ]
|
|
if is_async:
|
|
self.call_stmts += [
|
|
f" auto sendResult = send(Messages::RemoteGraphicsContextGL::{self.msg_name}({in_exprs}));",
|
|
]
|
|
else:
|
|
self.call_stmts += [
|
|
f" auto sendResult = sendSync(Messages::RemoteGraphicsContextGL::{self.msg_name}({in_exprs}), Messages::RemoteGraphicsContextGL::{self.msg_name}::Reply({out_exprs}));"
|
|
]
|
|
self.call_stmts += [
|
|
" if (!sendResult)",
|
|
" markContextLost();",
|
|
]
|
|
if self.post_call_stmts:
|
|
self.call_stmts += [" else {"] if len(self.post_call_stmts) > 1 else [ " else"]
|
|
self.post_call_stmts = [ " " + l for l in self.post_call_stmts ]
|
|
self.post_call_stmts += [ " }" ] if len(self.post_call_stmts) > 1 else []
|
|
self.post_call_stmts += [ "}" ]
|
|
|
|
|
|
def process_in_args(self, in_args: List[cpp_arg]):
|
|
for i in in_args:
|
|
if i.type.is_const_pointer():
|
|
assert False
|
|
else:
|
|
self.in_exprs += [webkit_ipc_convert_expr(cpp_expr(i.type, i.name), webkit_ipc_types[i.type])]
|
|
|
|
def process_out_args(self, out_args: List[cpp_arg]):
|
|
for o in out_args:
|
|
if o.type.is_pointer():
|
|
value_type = o.type.get_value_type()
|
|
webkit_ipc_value_type = webkit_ipc_types[value_type]
|
|
v = cpp_arg(webkit_ipc_value_type, o.name + "Reply")
|
|
self.pre_call_stmts += [f"{str(v.type)} {str(v.name)} = {{ }};"]
|
|
e = cpp_expr(v.type, v.name)
|
|
self.out_exprs += [e]
|
|
self.post_call_stmts += [
|
|
#fmt: off
|
|
f" if ({o.name})",
|
|
f" *{o.name} = {webkit_ipc_convert_expr(e, value_type)};"
|
|
#fmt: on
|
|
]
|
|
elif o.type.is_span():
|
|
webkit_ipc_type = webkit_ipc_types[o.type]
|
|
assert(isinstance(webkit_ipc_type, cpp_type_container))
|
|
v = cpp_arg(webkit_ipc_type, o.name + "Reply")
|
|
self.pre_call_stmts += [f"{str(v.type)} {str(v.name)};"]
|
|
self.out_exprs += [cpp_expr(v.type, v.name)]
|
|
if o.type.is_dynamic_span():
|
|
self.in_exprs += [cpp_expr(get_cpp_type("size_t"), f"{o.name}.bufSize")]
|
|
self.post_call_stmts += [
|
|
f" memcpy({o.name}.data, {v.name}.data(), {o.name}.bufSize * sizeof({str(webkit_ipc_type.get_contained_type())}));"
|
|
]
|
|
else:
|
|
self.out_exprs += [cpp_expr(o.type, o.name)]
|
|
|
|
def process_return_value(self, return_type: cpp_type):
|
|
if return_type.is_void():
|
|
return
|
|
self.return_type = return_type
|
|
ipc_return_type = webkit_ipc_types[return_type]
|
|
return_value_expr = cpp_expr(ipc_return_type, "returnValue")
|
|
self.pre_call_stmts += [f"{return_value_expr.type} {return_value_expr.expr} = {{ }};"]
|
|
self.out_exprs = [return_value_expr] + self.out_exprs
|
|
self.return_stmts = [f"return {str(webkit_ipc_convert_expr(return_value_expr, return_type))};"]
|
|
|
|
def __str__(self):
|
|
nolint = " // NOLINT" if "_" in self.name else ""
|
|
body = "".join(f"\n {b}" for b in self.pre_call_stmts + self.call_stmts + self.post_call_stmts + self.return_stmts)
|
|
return f"""\n{str(self.return_type)} RemoteGraphicsContextGLProxy::{self.name}({str(self.args)}){nolint}
|
|
{{{body}
|
|
}}"""
|
|
|
|
|
|
class webkit_ipc_cpp_proxy_placeholder(object):
|
|
name: str
|
|
return_type: cpp_type
|
|
args: cpp_arg_list
|
|
body: List[str]
|
|
|
|
def __init__(self, cpp_func: cpp_func):
|
|
self.name = cpp_func.name
|
|
|
|
self.return_type = cpp_func.return_type
|
|
self.args = cpp_func.args
|
|
self.body = ["notImplemented();"]
|
|
if cpp_func.return_type.type_name != "void":
|
|
self.body += ["return { };"]
|
|
|
|
def __str__(self):
|
|
nolint = " // NOLINT" if "_" in self.name else ""
|
|
body = "\n{\n " + "\n ".join(self.body) + "\n}"
|
|
return f"\n{str(self.return_type)} RemoteGraphicsContextGLProxy::{self.name}({str(self.args)}){nolint}{body}"
|
|
|
|
|
|
class context_proxy_cpp_webkit_ipc_generator(object):
|
|
"RemoteGraphicsContextGLProxy C++ implementation generator."
|
|
impls: List[webkit_ipc_cpp_proxy_impl]
|
|
unimpls: List[webkit_ipc_cpp_proxy_placeholder]
|
|
|
|
def __init__(self, funcs: Iterable[cpp_func], unimplemented: Iterable[cpp_func]):
|
|
self.impls = [webkit_ipc_cpp_proxy_impl(f) for f in funcs]
|
|
self.unimpls = [webkit_ipc_cpp_proxy_placeholder(f) for f in unimplemented]
|
|
|
|
def get_functions(self):
|
|
return "\n".join(str(i) for i in self.impls + self.unimpls)
|
|
|
|
def generate(self):
|
|
write_file(
|
|
context_proxy_functions_fn,
|
|
context_proxy_functions_template.format(self.get_functions()),
|
|
)
|
|
|
|
|
|
class webkit_ipc_cpp_impl(object):
|
|
name: str
|
|
args: cpp_arg_list
|
|
is_extension: bool
|
|
pre_call_stmts: List[str]
|
|
call_stmts: List[str]
|
|
post_call_stmts: List[str]
|
|
in_exprs: List[cpp_expr]
|
|
out_exprs: List[cpp_expr]
|
|
return_value_expr: Optional[cpp_expr]
|
|
|
|
def __init__(self, cpp_func: cpp_func):
|
|
self.name = cpp_func.name
|
|
self.overload_suffix = cpp_func.overload_suffix
|
|
self.args = cpp_arg_list([])
|
|
self.is_extension = cpp_func.is_extension
|
|
self.pre_call_stmts = []
|
|
self.call_stmts = []
|
|
self.post_call_stmts = []
|
|
self.in_exprs = []
|
|
self.out_exprs = []
|
|
self.return_value_expr = None
|
|
|
|
self.process_return_value(cpp_func.return_type)
|
|
in_args, out_args = cpp_func.get_args_categories()
|
|
self.process_args(cpp_func.args.args, set(in_args), set(out_args))
|
|
self.process_call()
|
|
|
|
def process_call(self):
|
|
self.call_stmts += [ "assertIsCurrent(m_streamThread);" ]
|
|
ext = "getExtensions()." if self.is_extension else ""
|
|
|
|
in_exprs = ", ".join(str(e) for e in self.in_exprs)
|
|
is_async = len(self.out_exprs) == 0
|
|
|
|
call_expr = f"m_context->{ext}{self.name}({in_exprs})"
|
|
if not self.return_value_expr:
|
|
self.call_stmts += [f"{call_expr};"]
|
|
else:
|
|
self.call_stmts += [f"{str(self.return_value_expr)} = {call_expr};"]
|
|
if not is_async:
|
|
out_exprs = ", ".join(str(e) for e in self.out_exprs)
|
|
self.post_call_stmts += [f"completionHandler({out_exprs});"]
|
|
|
|
def process_args(self, args: List[cpp_arg], in_args: Set[cpp_arg], out_args: Set[cpp_arg]):
|
|
for a in args:
|
|
if a.type.is_const_pointer():
|
|
assert False
|
|
if a in in_args:
|
|
self.process_in_arg(a)
|
|
else:
|
|
self.process_out_arg(a)
|
|
if self.out_exprs:
|
|
out_arg_decls = ", ".join(f"{str(e.type)}" for e in self.out_exprs)
|
|
self.args.args += [cpp_arg(get_cpp_type(f"CompletionHandler<void({out_arg_decls})>&&"), "completionHandler")]
|
|
|
|
def process_in_arg(self, a: cpp_arg):
|
|
self.args.args += [cpp_arg(webkit_ipc_get_message_forwarder_type(webkit_ipc_types[a.type]), a.name)]
|
|
self.in_exprs += [webkit_ipc_convert_expr(cpp_expr(webkit_ipc_types[a.type], a.name), a.type)]
|
|
|
|
def process_out_arg(self, a: cpp_arg):
|
|
if a.type.is_pointer():
|
|
value_arg = cpp_arg(a.type.get_value_type(), a.name)
|
|
self.pre_call_stmts += [f"{str(value_arg.type)} {str(value_arg.name)} = {{ }};"]
|
|
self.in_exprs += [cpp_expr(a.type, f"&{value_arg.name}")]
|
|
e = cpp_expr(value_arg.type, value_arg.name)
|
|
webkit_ipc_value_type = webkit_ipc_types[e.type]
|
|
self.out_exprs += [webkit_ipc_convert_expr(e, webkit_ipc_value_type)]
|
|
elif a.type.is_dynamic_span():
|
|
assert(isinstance(a.type, cpp_type_container))
|
|
size_arg = cpp_arg(get_cpp_type("uint64_t"), f"{a.name}Size")
|
|
self.args.args += [size_arg]
|
|
store_arg = cpp_arg(webkit_ipc_get_span_store_type(a.type), a.name)
|
|
self.pre_call_stmts += [f"{str(store_arg.type)} {str(store_arg.name)}(static_cast<size_t>({a.name}Size), 0);"]
|
|
self.in_exprs += [cpp_expr(store_arg.type, f"{store_arg.name}")]
|
|
webkit_ipc_type = webkit_ipc_types[a.type]
|
|
self.out_exprs += [webkit_ipc_convert_expr(cpp_expr(store_arg.type, store_arg.name), webkit_ipc_type)]
|
|
elif a.type.is_span():
|
|
assert(isinstance(a.type, cpp_type_container))
|
|
store_arg = cpp_arg(webkit_ipc_get_span_store_type(a.type), a.name)
|
|
self.pre_call_stmts += [f"{str(store_arg.type)} {str(store_arg.name)} {{ }};"]
|
|
self.in_exprs += [cpp_expr(store_arg.type, store_arg.name)]
|
|
webkit_ipc_type = webkit_ipc_types[a.type]
|
|
self.out_exprs += [webkit_ipc_convert_expr(cpp_expr(store_arg.type, store_arg.name), webkit_ipc_type)]
|
|
else:
|
|
assert a.type.is_reference()
|
|
webkit_ipc_type = webkit_ipc_types[a.type]
|
|
value_arg = cpp_arg(a.type.get_value_type(), a.name)
|
|
self.pre_call_stmts += [f"{self.ns(value_arg.type)} {str(value_arg.name)} {{ }};"]
|
|
e = cpp_expr(value_arg.type, value_arg.name)
|
|
self.in_exprs += [e]
|
|
self.out_exprs += [webkit_ipc_move_expr(webkit_ipc_convert_expr(e, webkit_ipc_type))]
|
|
|
|
def process_return_value(self, return_type: cpp_type):
|
|
if return_type.is_void():
|
|
return
|
|
ipc_return_type = webkit_ipc_types[return_type]
|
|
return_value_expr = cpp_expr(return_type, "returnValue")
|
|
self.pre_call_stmts += [f"{return_value_expr.type} {return_value_expr.expr} = {{ }};"]
|
|
self.out_exprs += [webkit_ipc_move_expr(webkit_ipc_convert_expr(return_value_expr, ipc_return_type))]
|
|
self.return_value_expr = return_value_expr
|
|
|
|
def __str__(self):
|
|
body = "".join(f"\n {b}" for b in self.pre_call_stmts + self.call_stmts + self.post_call_stmts)
|
|
return f""" void {self.name}{self.overload_suffix}({str(self.args)})
|
|
{{{body}
|
|
}}"""
|
|
|
|
def ns(self, type: cpp_type):
|
|
# TODO: namespace info is not stored in names.
|
|
if type.type_name == "ActiveInfo":
|
|
return "WebCore::GraphicsContextGL::" + str(type)
|
|
return str(type)
|
|
|
|
def webkit_ipc_resolve_overload_suffix(funcs : Iterable[cpp_func]):
|
|
counts = collections.Counter(f.name for f in funcs)
|
|
suffixes : Counter[str] = collections.Counter()
|
|
for f in funcs:
|
|
if counts[f.name] > 1:
|
|
f.overload_suffix = str(suffixes[f.name])
|
|
suffixes.update([f.name])
|
|
|
|
|
|
class context_cpp_webkit_ipc_generator(object):
|
|
"RemoteGraphicsContextGL C++ implementation generator."
|
|
impls: List[webkit_ipc_cpp_impl]
|
|
|
|
def __init__(self, funcs: Iterable[cpp_func]):
|
|
self.impls = [webkit_ipc_cpp_impl(f) for f in funcs]
|
|
|
|
def get_functions(self):
|
|
return "\n".join(str(i) for i in self.impls)
|
|
|
|
def generate(self):
|
|
write_file(
|
|
context_functions_fn,
|
|
context_functions_template.format(self.get_functions()),
|
|
)
|
|
|
|
|
|
class context_msg_webkit_ipc_generator(object):
|
|
"RemoteGraphicsContextGL WebKit IPC message definition generator."
|
|
msgs: List[webkit_ipc_msg]
|
|
|
|
def __init__(self, funcs: Iterable[cpp_func]):
|
|
self.msgs = [webkit_ipc_msg(f) for f in funcs]
|
|
|
|
def get_messages(self):
|
|
return "".join(str(m) for m in self.msgs)
|
|
|
|
def generate(self):
|
|
write_file(context_messages_fn, context_messages_template.format(self.get_messages()))
|
|
|
|
|
|
def create_cpp_arg(arg_spec: str, arg_index: int):
|
|
r = arg_spec.rsplit(" ", 1)
|
|
name = ""
|
|
type = None
|
|
if len(r) > 1 and r[0] != "const":
|
|
name = r[1].strip()
|
|
type = get_cpp_type(r[0])
|
|
else:
|
|
name = "arg{}".format(arg_index)
|
|
type = get_cpp_type(arg_spec)
|
|
return cpp_arg(type, name)
|
|
|
|
|
|
def create_cpp_arg_list(args_specs: Iterable[str]):
|
|
return cpp_arg_list([create_cpp_arg(arg_spec=e, arg_index=i) for i, e in enumerate(args_specs)])
|
|
|
|
|
|
def create_cpp_func(name: str, return_spec: str, args_specs: List[str], is_extension: bool):
|
|
return cpp_func(name=name, return_type=get_cpp_type(return_spec), args=create_cpp_arg_list(args_specs), is_extension=is_extension)
|
|
|
|
|
|
def read_lines_until(lines : Iterable[str], match : str) -> Generator[str, None, None]:
|
|
for line in lines:
|
|
if re.match(match, line.strip()):
|
|
break
|
|
yield line
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser("usage: %prog [options]")
|
|
parser.add_argument("--verbose", action="store_true", help="Print some debug info from the generator script")
|
|
options = parser.parse_args()
|
|
|
|
# Construct the list of functions to remote from web process to GPU process.
|
|
|
|
# FIXME: Until extensions header is removed, we need to complicate the implementation
|
|
# with the distinction of whether a function is or is not an extension function.
|
|
extension_signatures : Set[str] = set()
|
|
with open(extensions_input_fn) as f:
|
|
for line in f.readlines():
|
|
m = re.match(r".*virtual (\S+)\s+(\w+)\((.*)\) = 0;", line)
|
|
if m:
|
|
func = create_cpp_func(
|
|
name=m[2],
|
|
return_spec=m[1],
|
|
args_specs=cpp_split_args_specs(m[3]),
|
|
is_extension=True,
|
|
)
|
|
extension_signatures.update([str(func)])
|
|
funcs = []
|
|
unimplemented = []
|
|
for fn in functions_input_fns:
|
|
with open(fn) as f:
|
|
lines = iter(f.readlines())
|
|
for _ in read_lines_until(lines, "// Functions with a generated implementation. This list is used by generate-gpup-webgl script."):
|
|
pass
|
|
|
|
for line in read_lines_until(lines, "// End of list used by generate-gpup-webgl script."):
|
|
m = re.match(r"\s*(\S+)\s+(\w+)\((.*)\) final;", line)
|
|
if m:
|
|
func_name = m[2]
|
|
func = create_cpp_func(
|
|
name=func_name,
|
|
return_spec=m[1],
|
|
args_specs=cpp_split_args_specs(m[3]),
|
|
is_extension=False,
|
|
)
|
|
func.is_extension = str(func) in extension_signatures
|
|
if func.is_implemented():
|
|
funcs.append(func)
|
|
else:
|
|
unimplemented.append(func)
|
|
|
|
|
|
webkit_ipc_resolve_overload_suffix(funcs)
|
|
# Initialize WebKit IPC generation. Construct type mappings for the used C++ types -> IPC types.
|
|
# TODO: namespacing issues.
|
|
ai_type = get_cpp_type("ActiveInfo&")
|
|
ai_transfer_type = get_cpp_type("WebCore::GraphicsContextGL::ActiveInfo")
|
|
webkit_ipc_types[ai_type] = ai_transfer_type
|
|
|
|
with open(types_input_fn) as f:
|
|
lines = iter(f.readlines())
|
|
for _ in read_lines_until(lines, "// The GCGL types map to following WebKit IPC types. The list is used by generate-gpup-webgl script."):
|
|
pass
|
|
for line in read_lines_until(lines, "// End of list used by generate-gpup-webgl script."):
|
|
m = re.match(r".*static_assert\(std::is_same_v<(\w+), (\w+)>\);", line)
|
|
if m:
|
|
webkit_ipc_types[get_cpp_type(m[1])] = get_cpp_type(m[2])
|
|
continue
|
|
m = re.match(r".*static_assert\(sizeof\((\w+)\) == sizeof\((\w+)\)\);", line)
|
|
if m:
|
|
cpp_type = get_cpp_type(m[1])
|
|
ipc_type = get_cpp_type(m[2])
|
|
webkit_ipc_types[cpp_type] = ipc_type
|
|
webkit_ipc_types_converters[(cpp_type, ipc_type)] = cpp_static_cast
|
|
webkit_ipc_types_converters[(ipc_type, cpp_type)] = cpp_static_cast
|
|
continue
|
|
# FIXME: Here we use <= instead of == due to pointers, such as GCGLsync, GCGLintptr, ....
|
|
# This ends up failing if there ever is arrays of these types, since arrays are currently
|
|
# reinterpret-casted.
|
|
# WebKit IPC requires one sized type, but the size of these pointer-based values will change
|
|
# based on the platform.
|
|
m = re.match(r".*static_assert\(sizeof\((\w+)\) <= sizeof\((\w+)\)\);", line)
|
|
if m:
|
|
cpp_type = get_cpp_type(m[1])
|
|
ipc_type = get_cpp_type(m[2])
|
|
webkit_ipc_types[cpp_type] = ipc_type
|
|
webkit_ipc_types_converters[(cpp_type, ipc_type)] = cpp_static_cast
|
|
webkit_ipc_types_converters[(ipc_type, cpp_type)] = cpp_static_cast
|
|
continue
|
|
m = re.match(r".*static_assert\(sizeof\((\w+)\) <= sizeof\((\w+)\) && sizeof\((\w+)\) == sizeof\((\w+)\)\);", line)
|
|
if m:
|
|
cpp_type = get_cpp_type(m[1])
|
|
ipc_type = get_cpp_type(m[2])
|
|
cpp_cast_through_type = get_cpp_type(m[4])
|
|
webkit_ipc_types[cpp_type] = ipc_type
|
|
webkit_ipc_types_converters[(cpp_type, ipc_type)] = cpp_reinterpret_cast_from_pointer_through(cpp_cast_through_type)
|
|
webkit_ipc_types_converters[(ipc_type, cpp_type)] = cpp_reinterpret_cast_to_pointer_through(cpp_cast_through_type)
|
|
continue
|
|
|
|
# For all types in the input API, form corresponding IPC types and conversions.
|
|
# TODO: this is not driven by the typing.
|
|
all_types = set()
|
|
for func in funcs:
|
|
all_types.update(func.args.types() + [func.return_type])
|
|
# Sort by len so that template args come before templates.
|
|
for cpp_type in sorted(all_types, key=lambda x: len(x.type_name)):
|
|
if cpp_type in webkit_ipc_types:
|
|
continue
|
|
|
|
if cpp_type.is_dynamic_span() or cpp_type.is_span():
|
|
transfer_type = webkit_ipc_get_span_transfer_type(cpp_type)
|
|
webkit_ipc_types[cpp_type] = transfer_type.get_value_type()
|
|
if cpp_type.get_contained_type().is_const():
|
|
webkit_ipc_types_converters[(cpp_type, transfer_type)] = webkit_ipc_span_transfer_type_reinterpret_cast_conversion
|
|
webkit_ipc_types_converters[(transfer_type, cpp_type)] = webkit_ipc_make_gcglspan_conversion
|
|
else:
|
|
store_type = webkit_ipc_get_span_store_type(cpp_type)
|
|
webkit_ipc_types_converters[(store_type, transfer_type)] = cpp_array_reinterpret_cast_conversion
|
|
elif cpp_type.is_reference() or cpp_type.is_const_reference() or cpp_type.is_container():
|
|
value_type = cpp_type.get_value_type() if not cpp_type.is_container() else cpp_type
|
|
if value_type.is_container():
|
|
contained_type = value_type.get_contained_type()
|
|
webkit_ipc_contained_type = webkit_ipc_types[contained_type]
|
|
if webkit_ipc_contained_type == contained_type:
|
|
webkit_ipc_types[cpp_type] = value_type
|
|
else:
|
|
transfer_type = get_cpp_type(f"{value_type.get_container_name()}<{str(webkit_ipc_contained_type)}>")
|
|
webkit_ipc_types[cpp_type] = transfer_type
|
|
# TODO: Here might be case where Vector<GCGLint> was used in the interface and Vector<int32_t> is used
|
|
# in the IPC definition. There is no sensible way to do this at the moment. We do not convert, rather
|
|
# expect that all the invocations are taken care of the fact that GCGLint is the same type as int32_t.
|
|
# This will not hold for all types such as GCGLboolean.
|
|
#webkit_ipc_types_converters[(cpp_type, transfer_type)] = cpp_array_reinterpret_cast_conversion
|
|
else:
|
|
webkit_ipc_types[cpp_type] = value_type
|
|
else:
|
|
webkit_ipc_types[cpp_type] = cpp_type.get_value_type()
|
|
|
|
# The input to the generators is list of functions to remote.
|
|
# Run the various generators.
|
|
generators = [
|
|
context_proxy_cpp_webkit_ipc_generator(funcs, unimplemented),
|
|
context_msg_webkit_ipc_generator(funcs),
|
|
context_cpp_webkit_ipc_generator(funcs),
|
|
]
|
|
for g in generators:
|
|
g.generate()
|
|
|
|
if options.verbose:
|
|
print("Implemented:")
|
|
print("".join(f" {str(i)} final\n" for i in funcs))
|
|
print("Unimplemented:")
|
|
print("".join(f" {str(u)} final\n" for u in unimplemented))
|
|
print(f"Implemented: {len(funcs)}, unimplemented: {len(unimplemented)}, total: {len(funcs)+len(unimplemented)}")
|
|
print("C++ type map to WebKit IPC type map:")
|
|
for _, t in cpp_types.items():
|
|
if t in webkit_ipc_types:
|
|
print(f" {str(t)} -> {str(webkit_ipc_types[t])}")
|
|
print("C++ types without WebKit IPC type:")
|
|
for _, t in cpp_types.items():
|
|
if t not in webkit_ipc_types:
|
|
print(f" {str(t)}")
|
|
print("WebKit IPC type conversions")
|
|
for (a, b), converter in webkit_ipc_types_converters.items():
|
|
print(f" {str(a)} -> {str(b)} : {converter.__name__}")
|
|
print("Done.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|