新增模块覆盖: 系统层 (14): system, security, print, opengl, renderscript, transition, test, service_notification, service_controls, service_quicksettings, service_wallpaper, service_autofill, service_dreams, service_vr 应用层 (13): app_admin, app_backup, app_job, app_usage, app_role, app_people, appwidget, companion, credentials, mtp, sip, telecom, speech 硬件媒体层 (15): hardware_display, hardware_fingerprint, hardware_usb, hardware_input, media_audiofx, media_browse, media_session, media_tv, media_midi, media_projection, uwb, se, view_autofill, view_textclassifier, view_translation 总计 94 个模块,75,342 行代码
903 lines
32 KiB
Python
903 lines
32 KiB
Python
from __future__ import annotations
|
|
|
|
"""
|
|
Android RenderScript 组件 — RenderScript, Allocation, Element, Type, Script 等
|
|
方法签名完全对齐 Android SDK (android.renderscript 包)
|
|
"""
|
|
|
|
import math
|
|
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RenderScript
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RenderScript(Stub):
|
|
"""RenderScript — RenderScript 运行时上下文 (桌面仅存根)"""
|
|
|
|
# 优先级
|
|
Priority_LOW = 0
|
|
Priority_NORMAL = 1
|
|
Priority_HIGH = 2
|
|
|
|
# 上下文类型
|
|
ContextType_NORMAL = 0
|
|
ContextType_DEBUG = 1
|
|
ContextType_PROFILE = 2
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._context_type = RenderScript.ContextType_NORMAL
|
|
self._error_handler: Optional[Callable] = None
|
|
self._message_handler: Optional[Callable] = None
|
|
self._priority = RenderScript.Priority_NORMAL
|
|
self._initialized = False
|
|
|
|
@staticmethod
|
|
def create(context: Any = None) -> "RenderScript":
|
|
"""创建 RenderScript 上下文"""
|
|
rs = RenderScript()
|
|
rs._initialized = True
|
|
return rs
|
|
|
|
@staticmethod
|
|
def createMultiContext(context: Any = None,
|
|
context_type: int = ContextType_NORMAL,
|
|
flags: int = 0,
|
|
api_version: int = 0) -> "RenderScript":
|
|
"""创建多上下文 RenderScript"""
|
|
rs = RenderScript()
|
|
rs._context_type = context_type
|
|
rs._initialized = True
|
|
return rs
|
|
|
|
def setPriority(self, priority: int):
|
|
"""设置优先级"""
|
|
self._priority = priority
|
|
|
|
def getPriority(self) -> int:
|
|
return self._priority
|
|
|
|
def setErrorHandler(self, handler: Callable):
|
|
"""设置错误处理器"""
|
|
self._error_handler = handler
|
|
|
|
def setMessageHandler(self, handler: Callable):
|
|
"""设置消息处理器"""
|
|
self._message_handler = handler
|
|
|
|
def finish(self):
|
|
"""等待所有挂起渲染完成"""
|
|
pass
|
|
|
|
def destroy(self):
|
|
"""销毁 RenderScript 上下文"""
|
|
self._initialized = False
|
|
|
|
def getApplicationContext(self) -> Any:
|
|
return None
|
|
|
|
def getErrorHandler(self) -> Optional[Callable]:
|
|
return self._error_handler
|
|
|
|
def getMessageHandler(self) -> Optional[Callable]:
|
|
return self._message_handler
|
|
|
|
def isDestroyed(self) -> bool:
|
|
return not self._initialized
|
|
|
|
def nvLoadAll(self):
|
|
pass
|
|
|
|
def nvLoadFont(self, name: str) -> int:
|
|
return 0
|
|
|
|
def nvLoadProp(self, name: str) -> int:
|
|
return 0
|
|
|
|
def toString(self) -> str:
|
|
return f"RenderScript(priority={self._priority}, initialized={self._initialized})"
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# Element
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class Element(Stub):
|
|
"""Element — RenderScript 数据类型元素"""
|
|
|
|
# 预定义数据类型
|
|
F32: "Element" = None
|
|
F64: "Element" = None
|
|
I8: "Element" = None
|
|
I16: "Element" = None
|
|
I32: "Element" = None
|
|
I64: "Element" = None
|
|
U8: "Element" = None
|
|
U16: "Element" = None
|
|
U32: "Element" = None
|
|
U64: "Element" = None
|
|
BOOLEAN: "Element" = None
|
|
ALLOCATION: "Element" = None
|
|
A_8: "Element" = None
|
|
RGB_565: "Element" = None
|
|
RGBA_4444: "Element" = None
|
|
RGBA_8888: "Element" = None
|
|
F32_2: "Element" = None
|
|
F32_3: "Element" = None
|
|
F32_4: "Element" = None
|
|
F64_2: "Element" = None
|
|
F64_3: "Element" = None
|
|
F64_4: "Element" = None
|
|
I8_2: "Element" = None
|
|
I8_3: "Element" = None
|
|
I8_4: "Element" = None
|
|
I16_2: "Element" = None
|
|
I16_3: "Element" = None
|
|
I16_4: "Element" = None
|
|
I32_2: "Element" = None
|
|
I32_3: "Element" = None
|
|
I32_4: "Element" = None
|
|
I64_2: "Element" = None
|
|
I64_3: "Element" = None
|
|
I64_4: "Element" = None
|
|
U8_2: "Element" = None
|
|
U8_3: "Element" = None
|
|
U8_4: "Element" = None
|
|
U16_2: "Element" = None
|
|
U16_3: "Element" = None
|
|
U16_4: "Element" = None
|
|
U32_2: "Element" = None
|
|
U32_3: "Element" = None
|
|
U32_4: "Element" = None
|
|
U64_2: "Element" = None
|
|
U64_3: "Element" = None
|
|
U64_4: "Element" = None
|
|
|
|
# 数据类型
|
|
DataType = type("DataType", (), {
|
|
"NONE": 0, "FLOAT_32": 1, "FLOAT_64": 2,
|
|
"SIGNED_8": 3, "SIGNED_16": 4, "SIGNED_32": 5, "SIGNED_64": 6,
|
|
"UNSIGNED_8": 7, "UNSIGNED_16": 8, "UNSIGNED_32": 9, "UNSIGNED_64": 10,
|
|
"BOOLEAN": 11, "UNSIGNED_5_6_5": 12, "UNSIGNED_5_5_5_1": 13,
|
|
"UNSIGNED_4_4_4_4": 14, "MATRIX_4X4": 15, "MATRIX_3X3": 16,
|
|
"UNSIGNED_2_10_10_10": 17, "RS_ELEMENT": 18,
|
|
})
|
|
|
|
# 数据类型大小
|
|
DataType = DataType()
|
|
|
|
def __init__(self, rs: Optional[RenderScript] = None, data_type: int = 0,
|
|
vector_size: int = 1):
|
|
super().__init__()
|
|
self._rs = rs
|
|
self._data_type = data_type
|
|
self._vector_size = vector_size
|
|
self._element_size = self._compute_size()
|
|
|
|
def _compute_size(self) -> int:
|
|
base_sizes = {
|
|
Element.DataType.FLOAT_32: 4, Element.DataType.FLOAT_64: 8,
|
|
Element.DataType.SIGNED_8: 1, Element.DataType.SIGNED_16: 2,
|
|
Element.DataType.SIGNED_32: 4, Element.DataType.SIGNED_64: 8,
|
|
Element.DataType.UNSIGNED_8: 1, Element.DataType.UNSIGNED_16: 2,
|
|
Element.DataType.UNSIGNED_32: 4, Element.DataType.UNSIGNED_64: 8,
|
|
Element.DataType.BOOLEAN: 1,
|
|
Element.DataType.UNSIGNED_5_6_5: 2,
|
|
Element.DataType.UNSIGNED_5_5_5_1: 2,
|
|
Element.DataType.UNSIGNED_4_4_4_4: 2,
|
|
Element.DataType.MATRIX_4X4: 64,
|
|
Element.DataType.MATRIX_3X3: 36,
|
|
Element.DataType.RS_ELEMENT: 4,
|
|
}
|
|
return base_sizes.get(self._data_type, 4) * self._vector_size
|
|
|
|
def getBytesSize(self) -> int:
|
|
return self._element_size
|
|
|
|
def getVectorSize(self) -> int:
|
|
return self._vector_size
|
|
|
|
def getDataType(self) -> int:
|
|
return self._data_type
|
|
|
|
def isCompatible(self, e: "Element") -> bool:
|
|
return self._data_type == e._data_type and self._vector_size == e._vector_size
|
|
|
|
def getSubElement(self, index: int) -> Optional["Element"]:
|
|
return None
|
|
|
|
def getSubElementCount(self) -> int:
|
|
return 0
|
|
|
|
def getSubElementArraySize(self, index: int) -> int:
|
|
return 0
|
|
|
|
def getSubElementOffsetBytes(self, index: int) -> int:
|
|
return 0
|
|
|
|
def toString(self) -> str:
|
|
return f"Element(dataType={self._data_type}, vectorSize={self._vector_size})"
|
|
|
|
def hashCode(self) -> int:
|
|
return hash((self._data_type, self._vector_size)) & 0x7FFFFFFF
|
|
|
|
def equals(self, other) -> bool:
|
|
if not isinstance(other, Element):
|
|
return False
|
|
return self._data_type == other._data_type and self._vector_size == other._vector_size
|
|
|
|
@staticmethod
|
|
def BOOL(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.BOOLEAN, 1)
|
|
|
|
@staticmethod
|
|
def U8(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.UNSIGNED_8, 1)
|
|
|
|
@staticmethod
|
|
def I8(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.SIGNED_8, 1)
|
|
|
|
@staticmethod
|
|
def U16(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.UNSIGNED_16, 1)
|
|
|
|
@staticmethod
|
|
def I16(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.SIGNED_16, 1)
|
|
|
|
@staticmethod
|
|
def U32(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.UNSIGNED_32, 1)
|
|
|
|
@staticmethod
|
|
def I32(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.SIGNED_32, 1)
|
|
|
|
@staticmethod
|
|
def U64(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.UNSIGNED_64, 1)
|
|
|
|
@staticmethod
|
|
def I64(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.SIGNED_64, 1)
|
|
|
|
@staticmethod
|
|
def F32(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.FLOAT_32, 1)
|
|
|
|
@staticmethod
|
|
def F64(rs: RenderScript) -> "Element":
|
|
return Element(rs, Element.DataType.FLOAT_64, 1)
|
|
|
|
@staticmethod
|
|
def createVector(rs: RenderScript, data_type: int, size: int) -> "Element":
|
|
return Element(rs, data_type, size)
|
|
|
|
@staticmethod
|
|
def createPixel(rs: RenderScript, data_type: int, pixel_type: int) -> "Element":
|
|
return Element(rs, data_type, 4)
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# Type
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class Type(Stub):
|
|
"""Type — RenderScript 内存分配类型"""
|
|
|
|
CubemapFace = type("CubemapFace", (), {
|
|
"POSITIVE_X": 0, "NEGATIVE_X": 1,
|
|
"POSITIVE_Y": 2, "NEGATIVE_Y": 3,
|
|
"POSITIVE_Z": 4, "NEGATIVE_Z": 5,
|
|
})
|
|
|
|
def __init__(self, rs: Optional[RenderScript] = None,
|
|
element: Optional[Element] = None,
|
|
dim_x: int = 0, dim_y: int = 0, dim_z: int = 0,
|
|
mipmaps: bool = False, faces: bool = False):
|
|
super().__init__()
|
|
self._rs = rs
|
|
self._element = element
|
|
self._dim_x = dim_x
|
|
self._dim_y = dim_y
|
|
self._dim_z = dim_z
|
|
self._mipmaps = mipmaps
|
|
self._faces = faces
|
|
self._yuv_format = 0
|
|
|
|
def getElement(self) -> Optional[Element]:
|
|
return self._element
|
|
|
|
def getX(self) -> int:
|
|
return self._dim_x
|
|
|
|
def getY(self) -> int:
|
|
return self._dim_y
|
|
|
|
def getZ(self) -> int:
|
|
return self._dim_z
|
|
|
|
def getCount(self) -> int:
|
|
return self._dim_x * max(self._dim_y, 1) * max(self._dim_z, 1)
|
|
|
|
def hasMipmaps(self) -> bool:
|
|
return self._mipmaps
|
|
|
|
def hasFaces(self) -> bool:
|
|
return self._faces
|
|
|
|
def getYuvFormat(self) -> int:
|
|
return self._yuv_format
|
|
|
|
def setYuvFormat(self, yuv_format: int):
|
|
self._yuv_format = yuv_format
|
|
|
|
def toString(self) -> str:
|
|
return (f"Type(element={self._element}, dims={self._dim_x}x{self._dim_y}"
|
|
f"x{self._dim_z}, mipmaps={self._mipmaps})")
|
|
|
|
def hashCode(self) -> int:
|
|
return hash((self._dim_x, self._dim_y, self._dim_z)) & 0x7FFFFFFF
|
|
|
|
def equals(self, other) -> bool:
|
|
if not isinstance(other, Type):
|
|
return False
|
|
return (self._dim_x == other._dim_x and self._dim_y == other._dim_y
|
|
and self._dim_z == other._dim_z)
|
|
|
|
# ── Builder ──
|
|
|
|
class Builder(Stub):
|
|
"""Builder — Type 构建器"""
|
|
|
|
def __init__(self, rs: RenderScript, element: Element):
|
|
super().__init__()
|
|
self._rs = rs
|
|
self._element = element
|
|
self._dim_x = 0
|
|
self._dim_y = 0
|
|
self._dim_z = 0
|
|
self._mipmaps = False
|
|
self._faces = False
|
|
self._yuv_format = 0
|
|
|
|
def setX(self, value: int) -> "Type.Builder":
|
|
self._dim_x = value
|
|
return self
|
|
|
|
def setY(self, value: int) -> "Type.Builder":
|
|
self._dim_y = value
|
|
return self
|
|
|
|
def setZ(self, value: int) -> "Type.Builder":
|
|
self._dim_z = value
|
|
return self
|
|
|
|
def setMipmaps(self, enable: bool) -> "Type.Builder":
|
|
self._mipmaps = enable
|
|
return self
|
|
|
|
def setFaces(self, enable: bool) -> "Type.Builder":
|
|
self._faces = enable
|
|
return self
|
|
|
|
def setYuvFormat(self, yuv_format: int) -> "Type.Builder":
|
|
self._yuv_format = yuv_format
|
|
return self
|
|
|
|
def create(self) -> Type:
|
|
t = Type(self._rs, self._element, self._dim_x, self._dim_y,
|
|
self._dim_z, self._mipmaps, self._faces)
|
|
t._yuv_format = self._yuv_format
|
|
return t
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# Allocation
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class Allocation(Stub):
|
|
"""Allocation — RenderScript 内存分配"""
|
|
|
|
# 使用类型
|
|
USAGE_SCRIPT = 0x0001
|
|
USAGE_GRAPHICS_TEXTURE = 0x0002
|
|
USAGE_GRAPHICS_VERTEX = 0x0004
|
|
USAGE_GRAPHICS_CONSTANTS = 0x0008
|
|
USAGE_GRAPHICS_RENDER_TARGET = 0x0010
|
|
USAGE_IO_INPUT = 0x0020
|
|
USAGE_IO_OUTPUT = 0x0040
|
|
USAGE_SHARED = 0x0080
|
|
|
|
# Mipmap 控制
|
|
MIPMAP_FULL = 0
|
|
MIPMAP_ON_SYNC_TO_TEXTURE = 1
|
|
|
|
def __init__(self, rs: Optional[RenderScript] = None,
|
|
type_: Optional[Type] = None,
|
|
usage: int = USAGE_SCRIPT):
|
|
super().__init__()
|
|
self._rs = rs
|
|
self._type = type_
|
|
self._usage = usage
|
|
self._data: Any = None
|
|
self._element_size = type_.getElement().getBytesSize() if type_ and type_.getElement() else 0
|
|
|
|
@staticmethod
|
|
def createTyped(rs: RenderScript, type_: Type,
|
|
usage: int = USAGE_SCRIPT) -> "Allocation":
|
|
"""创建分配"""
|
|
alloc = Allocation(rs, type_, usage)
|
|
total_size = type_.getCount() * type_.getElement().getBytesSize() if type_.getElement() else 0
|
|
alloc._data = bytearray(total_size)
|
|
return alloc
|
|
|
|
@staticmethod
|
|
def createFromBitmap(rs: RenderScript, bitmap: Any,
|
|
usage: int = USAGE_SCRIPT) -> "Allocation":
|
|
"""从位图创建分配"""
|
|
# 尝试获取位图尺寸
|
|
width, height = 0, 0
|
|
try:
|
|
width = bitmap.getWidth() if hasattr(bitmap, 'getWidth') else 0
|
|
height = bitmap.getHeight() if hasattr(bitmap, 'getHeight') else 0
|
|
except Exception:
|
|
pass
|
|
element = Element(rs, Element.DataType.UNSIGNED_8, 4)
|
|
type_ = Type(rs, element, width, height)
|
|
alloc = Allocation(rs, type_, usage)
|
|
alloc._data = bytearray(width * height * 4)
|
|
return alloc
|
|
|
|
@staticmethod
|
|
def createFromBitmapBoxed(rs: RenderScript, bitmap: Any,
|
|
usage: int = USAGE_SCRIPT) -> "Allocation":
|
|
return Allocation.createFromBitmap(rs, bitmap, usage)
|
|
|
|
def copyFrom(self, data: Any):
|
|
"""从数组或位图复制数据"""
|
|
if isinstance(data, (bytes, bytearray)):
|
|
self._data = bytearray(data)
|
|
elif hasattr(data, '__iter__'):
|
|
import struct
|
|
try:
|
|
self._data = bytearray(struct.pack(f'<{len(list(data))}f',
|
|
*[float(v) for v in data]))
|
|
except Exception:
|
|
self._data = bytearray(len(list(data)) * 4)
|
|
else:
|
|
self._data = bytearray(1024)
|
|
|
|
def copyTo(self, data: Any):
|
|
"""将数据复制到目标"""
|
|
if isinstance(data, bytearray) and self._data:
|
|
data[:] = self._data
|
|
elif isinstance(data, list):
|
|
data.clear()
|
|
if self._data:
|
|
for i in range(0, len(self._data), 4):
|
|
data.append(int.from_bytes(self._data[i:i+4], 'little'))
|
|
|
|
def resize(self, dim_x: int):
|
|
"""重新调整分配大小"""
|
|
if self._type:
|
|
self._type._dim_x = dim_x
|
|
self._data = bytearray(self._type.getCount() * self._element_size)
|
|
|
|
def getType(self) -> Optional[Type]:
|
|
return self._type
|
|
|
|
def getUsage(self) -> int:
|
|
return self._usage
|
|
|
|
def getElement(self) -> Optional[Element]:
|
|
return self._type.getElement() if self._type else None
|
|
|
|
def syncAll(self, src_location: int):
|
|
pass
|
|
|
|
def destroy(self):
|
|
self._data = None
|
|
|
|
def toString(self) -> str:
|
|
return (f"Allocation(type={self._type}, usage={self._usage}, "
|
|
f"data_size={len(self._data) if self._data else 0})")
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# Matrix4f
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class Matrix4f(Stub):
|
|
"""Matrix4f — 4x4 浮点矩阵"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._matrix = [0.0] * 16
|
|
self._matrix[0] = 1.0 # 单位矩阵
|
|
self._matrix[5] = 1.0
|
|
self._matrix[10] = 1.0
|
|
self._matrix[15] = 1.0
|
|
|
|
def getArray(self) -> List[float]:
|
|
return list(self._matrix)
|
|
|
|
def setArray(self, array: List[float]):
|
|
if len(array) >= 16:
|
|
self._matrix = list(array[:16])
|
|
|
|
def loadIdentity(self):
|
|
self._matrix = [0.0] * 16
|
|
self._matrix[0] = 1.0
|
|
self._matrix[5] = 1.0
|
|
self._matrix[10] = 1.0
|
|
self._matrix[15] = 1.0
|
|
|
|
def load(self, src: "Matrix4f"):
|
|
self._matrix = list(src._matrix)
|
|
|
|
def loadRotate(self, rot: float, x: float, y: float, z: float):
|
|
angle_rad = math.radians(rot)
|
|
c = math.cos(angle_rad)
|
|
s = math.sin(angle_rad)
|
|
self.loadIdentity()
|
|
if x == 1 and y == 0 and z == 0:
|
|
self._matrix[5] = c
|
|
self._matrix[6] = -s
|
|
self._matrix[9] = s
|
|
self._matrix[10] = c
|
|
elif x == 0 and y == 1 and z == 0:
|
|
self._matrix[0] = c
|
|
self._matrix[2] = s
|
|
self._matrix[8] = -s
|
|
self._matrix[10] = c
|
|
elif x == 0 and y == 0 and z == 1:
|
|
self._matrix[0] = c
|
|
self._matrix[1] = -s
|
|
self._matrix[4] = s
|
|
self._matrix[5] = c
|
|
|
|
def loadScale(self, x: float, y: float, z: float):
|
|
self.loadIdentity()
|
|
self._matrix[0] = x
|
|
self._matrix[5] = y
|
|
self._matrix[10] = z
|
|
|
|
def loadTranslate(self, x: float, y: float, z: float):
|
|
self.loadIdentity()
|
|
self._matrix[12] = x
|
|
self._matrix[13] = y
|
|
self._matrix[14] = z
|
|
|
|
def loadMultiply(self, lhs: "Matrix4f", rhs: "Matrix4f"):
|
|
for i in range(4):
|
|
for j in range(4):
|
|
self._matrix[i * 4 + j] = sum(
|
|
lhs._matrix[i * 4 + k] * rhs._matrix[k * 4 + j]
|
|
for k in range(4)
|
|
)
|
|
|
|
def multiply(self, rhs: "Matrix4f"):
|
|
result = [0.0] * 16
|
|
for i in range(4):
|
|
for j in range(4):
|
|
result[i * 4 + j] = sum(
|
|
self._matrix[i * 4 + k] * rhs._matrix[k * 4 + j]
|
|
for k in range(4)
|
|
)
|
|
self._matrix = result
|
|
|
|
def transpose(self):
|
|
for i in range(4):
|
|
for j in range(i + 1, 4):
|
|
self._matrix[i * 4 + j], self._matrix[j * 4 + i] = \
|
|
self._matrix[j * 4 + i], self._matrix[i * 4 + j]
|
|
|
|
def toString(self) -> str:
|
|
rows = []
|
|
for i in range(4):
|
|
row = self._matrix[i*4:(i+1)*4]
|
|
rows.append(f"[{', '.join(f'{v:.4f}' for v in row)}]")
|
|
return f"Matrix4f({', '.join(rows)})"
|
|
|
|
def hashCode(self) -> int:
|
|
return hash(tuple(self._matrix)) & 0x7FFFFFFF
|
|
|
|
def equals(self, other) -> bool:
|
|
if not isinstance(other, Matrix4f):
|
|
return False
|
|
return self._matrix == other._matrix
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# Matrix3f
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class Matrix3f(Stub):
|
|
"""Matrix3f — 3x3 浮点矩阵"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._matrix = [0.0] * 9
|
|
self._matrix[0] = 1.0
|
|
self._matrix[4] = 1.0
|
|
self._matrix[8] = 1.0
|
|
|
|
def getArray(self) -> List[float]:
|
|
return list(self._matrix)
|
|
|
|
def setArray(self, array: List[float]):
|
|
if len(array) >= 9:
|
|
self._matrix = list(array[:9])
|
|
|
|
def loadIdentity(self):
|
|
self._matrix = [0.0] * 9
|
|
self._matrix[0] = 1.0
|
|
self._matrix[4] = 1.0
|
|
self._matrix[8] = 1.0
|
|
|
|
def load(self, src: "Matrix3f"):
|
|
self._matrix = list(src._matrix)
|
|
|
|
def loadMultiply(self, lhs: "Matrix3f", rhs: "Matrix3f"):
|
|
for i in range(3):
|
|
for j in range(3):
|
|
self._matrix[i * 3 + j] = sum(
|
|
lhs._matrix[i * 3 + k] * rhs._matrix[k * 3 + j]
|
|
for k in range(3)
|
|
)
|
|
|
|
def multiply(self, rhs: "Matrix3f"):
|
|
result = [0.0] * 9
|
|
for i in range(3):
|
|
for j in range(3):
|
|
result[i * 3 + j] = sum(
|
|
self._matrix[i * 3 + k] * rhs._matrix[k * 3 + j]
|
|
for k in range(3)
|
|
)
|
|
self._matrix = result
|
|
|
|
def transpose(self):
|
|
for i in range(3):
|
|
for j in range(i + 1, 3):
|
|
self._matrix[i * 3 + j], self._matrix[j * 3 + i] = \
|
|
self._matrix[j * 3 + i], self._matrix[i * 3 + j]
|
|
|
|
def toString(self) -> str:
|
|
rows = []
|
|
for i in range(3):
|
|
row = self._matrix[i*3:(i+1)*3]
|
|
rows.append(f"[{', '.join(f'{v:.4f}' for v in row)}]")
|
|
return f"Matrix3f({', '.join(rows)})"
|
|
|
|
def hashCode(self) -> int:
|
|
return hash(tuple(self._matrix)) & 0x7FFFFFFF
|
|
|
|
def equals(self, other) -> bool:
|
|
if not isinstance(other, Matrix3f):
|
|
return False
|
|
return self._matrix == other._matrix
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# Script (base)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class Script(Stub):
|
|
"""Script — RenderScript 脚本基类"""
|
|
|
|
def __init__(self, rs: Optional[RenderScript] = None):
|
|
super().__init__()
|
|
self._rs = rs
|
|
self._kernel_groups: List[Any] = []
|
|
|
|
def setVar(self, index: int, value: Any):
|
|
"""设置脚本变量"""
|
|
pass
|
|
|
|
def getVar(self, index: int) -> Any:
|
|
return None
|
|
|
|
def setTimeZone(self, timezone: str):
|
|
pass
|
|
|
|
def forEach(self, slot: int, ains: List[Allocation],
|
|
aout: Allocation, vdata: Any = None):
|
|
"""执行 forEach 内核"""
|
|
raise AndroidOnlyError("Script.forEach() 仅在 Android (RenderScript) 设备上可用")
|
|
|
|
def invoke(self, slot: int):
|
|
"""调用可调用函数"""
|
|
pass
|
|
|
|
def bindAllocation(self, va: Allocation, slot: int):
|
|
"""绑定分配"""
|
|
pass
|
|
|
|
def destroy(self):
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"Script@{hex(id(self))}"
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# ScriptC
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class ScriptC(Script):
|
|
"""ScriptC — 编译的 RenderScript 内核脚本"""
|
|
|
|
def __init__(self, rs: RenderScript, resource_id: int = 0):
|
|
super().__init__(rs)
|
|
self._resource_id = resource_id
|
|
|
|
def toString(self) -> str:
|
|
return f"ScriptC(resourceId={self._resource_id})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# ScriptIntrinsicBlur
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class ScriptIntrinsicBlur(Script):
|
|
"""ScriptIntrinsicBlur — 高斯模糊内在函数"""
|
|
|
|
def __init__(self, rs: RenderScript):
|
|
super().__init__(rs)
|
|
self._radius: float = 5.0
|
|
self._input: Optional[Allocation] = None
|
|
|
|
@staticmethod
|
|
def create(rs: RenderScript, e: Element) -> "ScriptIntrinsicBlur":
|
|
"""创建模糊内在函数"""
|
|
return ScriptIntrinsicBlur(rs)
|
|
|
|
def setRadius(self, radius: float):
|
|
"""设置模糊半径"""
|
|
self._radius = max(0.0, min(radius, 25.0))
|
|
|
|
def setInput(self, alloc: Allocation):
|
|
"""设置输入分配"""
|
|
self._input = alloc
|
|
|
|
def forEach(self, aout: Allocation):
|
|
"""执行模糊"""
|
|
if self._input and aout:
|
|
pass # 在桌面环境不执行实际模糊
|
|
|
|
def toString(self) -> str:
|
|
return f"ScriptIntrinsicBlur(radius={self._radius})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# ScriptIntrinsicConvolve3x3
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class ScriptIntrinsicConvolve3x3(Script):
|
|
"""ScriptIntrinsicConvolve3x3 — 3x3 卷积内在函数"""
|
|
|
|
def __init__(self, rs: RenderScript):
|
|
super().__init__(rs)
|
|
self._coefficients: List[float] = [0.0] * 9
|
|
self._input: Optional[Allocation] = None
|
|
|
|
@staticmethod
|
|
def create(rs: RenderScript, e: Element) -> "ScriptIntrinsicConvolve3x3":
|
|
"""创建卷积内在函数"""
|
|
return ScriptIntrinsicConvolve3x3(rs)
|
|
|
|
def setCoefficients(self, coeffs: List[float]):
|
|
"""设置卷积系数"""
|
|
for i in range(min(len(coeffs), 9)):
|
|
self._coefficients[i] = coeffs[i]
|
|
|
|
def setInput(self, alloc: Allocation):
|
|
"""设置输入分配"""
|
|
self._input = alloc
|
|
|
|
def forEach(self, aout: Allocation):
|
|
"""执行卷积"""
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"ScriptIntrinsicConvolve3x3(coefficients={self._coefficients})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# 初始化 Element 静态实例
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
def _init_elements():
|
|
"""初始化 Element 预定义实例(在模块导入时调用)"""
|
|
rs = RenderScript.create()
|
|
Element.F32 = Element.F32(rs)
|
|
Element.F64 = Element.F64(rs)
|
|
Element.I8 = Element.I8(rs)
|
|
Element.I16 = Element.I16(rs)
|
|
Element.I32 = Element.I32(rs)
|
|
Element.I64 = Element.I64(rs)
|
|
Element.U8 = Element.U8(rs)
|
|
Element.U16 = Element.U16(rs)
|
|
Element.U32 = Element.U32(rs)
|
|
Element.U64 = Element.U64(rs)
|
|
Element.BOOLEAN = Element.BOOL(rs)
|
|
Element.ALLOCATION = Element(rs, Element.DataType.RS_ELEMENT, 1)
|
|
Element.A_8 = Element.createPixel(rs, Element.DataType.UNSIGNED_8, 1)
|
|
Element.RGB_565 = Element.createPixel(rs, Element.DataType.UNSIGNED_5_6_5, 3)
|
|
Element.RGBA_4444 = Element.createPixel(rs, Element.DataType.UNSIGNED_4_4_4_4, 4)
|
|
Element.RGBA_8888 = Element.createPixel(rs, Element.DataType.UNSIGNED_8, 4)
|
|
Element.F32_2 = Element.createVector(rs, Element.DataType.FLOAT_32, 2)
|
|
Element.F32_3 = Element.createVector(rs, Element.DataType.FLOAT_32, 3)
|
|
Element.F32_4 = Element.createVector(rs, Element.DataType.FLOAT_32, 4)
|
|
Element.F64_2 = Element.createVector(rs, Element.DataType.FLOAT_64, 2)
|
|
Element.F64_3 = Element.createVector(rs, Element.DataType.FLOAT_64, 3)
|
|
Element.F64_4 = Element.createVector(rs, Element.DataType.FLOAT_64, 4)
|
|
Element.I8_2 = Element.createVector(rs, Element.DataType.SIGNED_8, 2)
|
|
Element.I8_3 = Element.createVector(rs, Element.DataType.SIGNED_8, 3)
|
|
Element.I8_4 = Element.createVector(rs, Element.DataType.SIGNED_8, 4)
|
|
Element.I16_2 = Element.createVector(rs, Element.DataType.SIGNED_16, 2)
|
|
Element.I16_3 = Element.createVector(rs, Element.DataType.SIGNED_16, 3)
|
|
Element.I16_4 = Element.createVector(rs, Element.DataType.SIGNED_16, 4)
|
|
Element.I32_2 = Element.createVector(rs, Element.DataType.SIGNED_32, 2)
|
|
Element.I32_3 = Element.createVector(rs, Element.DataType.SIGNED_32, 3)
|
|
Element.I32_4 = Element.createVector(rs, Element.DataType.SIGNED_32, 4)
|
|
Element.I64_2 = Element.createVector(rs, Element.DataType.SIGNED_64, 2)
|
|
Element.I64_3 = Element.createVector(rs, Element.DataType.SIGNED_64, 3)
|
|
Element.I64_4 = Element.createVector(rs, Element.DataType.SIGNED_64, 4)
|
|
Element.U8_2 = Element.createVector(rs, Element.DataType.UNSIGNED_8, 2)
|
|
Element.U8_3 = Element.createVector(rs, Element.DataType.UNSIGNED_8, 3)
|
|
Element.U8_4 = Element.createVector(rs, Element.DataType.UNSIGNED_8, 4)
|
|
Element.U16_2 = Element.createVector(rs, Element.DataType.UNSIGNED_16, 2)
|
|
Element.U16_3 = Element.createVector(rs, Element.DataType.UNSIGNED_16, 3)
|
|
Element.U16_4 = Element.createVector(rs, Element.DataType.UNSIGNED_16, 4)
|
|
Element.U32_2 = Element.createVector(rs, Element.DataType.UNSIGNED_32, 2)
|
|
Element.U32_3 = Element.createVector(rs, Element.DataType.UNSIGNED_32, 3)
|
|
Element.U32_4 = Element.createVector(rs, Element.DataType.UNSIGNED_32, 4)
|
|
Element.U64_2 = Element.createVector(rs, Element.DataType.UNSIGNED_64, 2)
|
|
Element.U64_3 = Element.createVector(rs, Element.DataType.UNSIGNED_64, 3)
|
|
Element.U64_4 = Element.createVector(rs, Element.DataType.UNSIGNED_64, 4)
|
|
|
|
|
|
_init_elements()
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# __all__
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
__all__ = [
|
|
"RenderScript",
|
|
"Allocation",
|
|
"Element",
|
|
"Type",
|
|
"Script",
|
|
"ScriptIntrinsicBlur",
|
|
"ScriptIntrinsicConvolve3x3",
|
|
"ScriptC",
|
|
"Matrix4f",
|
|
"Matrix3f",
|
|
] |