""" Android Graphics Surface 组件 — SurfaceTexture, SurfaceHolder, SurfaceView, GLSurfaceView 方法签名完全对齐 Android SDK (android.graphics.surface 包 和 android.view.Surface) """ from __future__ import annotations import time from typing import Any, Callable, Dict, List, Optional, Set, Tuple from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException # ═══════════════════════════════════════════════════════════════ # SurfaceTexture # ═══════════════════════════════════════════════════════════════ class SurfaceTexture(Stub): """SurfaceTexture — 表面纹理""" # 纹理目标常量 TEXTURE_TARGET_2D = 3553 TEXTURE_TARGET_EXTERNAL = 36197 # Transform 矩阵常量 TRANSFORM_MATRIX_SIZE = 16 def __init__(self, tex_name: int = 0, allow_high_performance: bool = True): super().__init__() self._tex_name = tex_name self._tex_target: int = SurfaceTexture.TEXTURE_TARGET_EXTERNAL self._timestamp: int = 0 self._frame_available_listener: Optional[Callable] = None self._frame_available_listener_handler: Any = None self._default_buffer_size: Tuple[int, int] = (0, 0) self._is_abandoned: bool = False self._is_released: bool = False self._transform_matrix: List[float] = [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, ] self._buffer_count: int = 0 self._frame_count: int = 0 self._width: int = 0 self._height: int = 0 def getTexName(self) -> int: return self._tex_name def getTimestamp(self) -> int: """获取时间戳 (纳秒)""" return self._timestamp def updateTexImage(self): """更新纹理图像""" self._timestamp = int(time.time() * 1000000000) self._frame_count += 1 def getTransformMatrix(self, matrix: Optional[List[float]] = None) -> List[float]: """获取变换矩阵""" if matrix is not None and len(matrix) >= 16: for i in range(16): matrix[i] = self._transform_matrix[i] return list(self._transform_matrix) def setDefaultBufferSize(self, width: int, height: int): """设置默认缓冲区大小""" self._default_buffer_size = (width, height) self._width = width self._height = height def getDefaultBufferSize(self) -> Tuple[int, int]: return self._default_buffer_size def setOnFrameAvailableListener(self, listener: Optional[Callable], handler: Any = None): """设置帧可用监听器""" self._frame_available_listener = listener self._frame_available_listener_handler = handler if listener: listener(self) def getOnFrameAvailableListener(self) -> Optional[Callable]: return self._frame_available_listener def detachFromGLContext(self): """从 GL 上下文分离""" pass def attachToGLContext(self, tex_name: int): """附加到 GL 上下文""" self._tex_name = tex_name def release(self): """释放表面纹理""" self._is_released = True self._frame_available_listener = None def releaseTexImage(self): """释放纹理图像""" pass def abandon(self): """废弃表面纹理""" self._is_abandoned = True self._frame_available_listener = None def isReleased(self) -> bool: return self._is_released def isAbandoned(self) -> bool: return self._is_abandoned def getWidth(self) -> int: return self._width def getHeight(self) -> int: return self._height def getFrameCount(self) -> int: return self._frame_count def getBufferCount(self) -> int: return self._buffer_count def toString(self) -> str: return f"SurfaceTexture(tex={self._tex_name}, {self._width}x{self._height})" # ═══════════════════════════════════════════════════════════════ # SurfaceHolder # ═══════════════════════════════════════════════════════════════ class SurfaceHolder(Stub): """SurfaceHolder — 表面持有者""" SURFACE_TYPE_NORMAL = 0 SURFACE_TYPE_HARDWARE = 1 SURFACE_TYPE_GPU = 2 SURFACE_TYPE_PUSH_BUFFERS = 3 # 表面变更类型 CHANGE_TYPE_NONE = 0 CHANGE_TYPE_SIZE_CHANGED = 1 CHANGE_TYPE_FORMAT_CHANGED = 2 CHANGE_TYPE_SURFACE_CREATED = 3 CHANGE_TYPE_SURFACE_DESTROYED = 4 CHANGE_TYPE_SURFACE_REDRAW = 5 class Callback(Stub): """SurfaceHolder.Callback — 表面回调""" def surfaceCreated(self, holder: SurfaceHolder): pass def surfaceChanged(self, holder: SurfaceHolder, format: int, width: int, height: int): pass def surfaceDestroyed(self, holder: SurfaceHolder): pass def surfaceRedrawNeeded(self, holder: SurfaceHolder): pass class Callback2(Callback): """SurfaceHolder.Callback2 — 表面回调 (扩展)""" def surfaceRedrawNeeded(self, holder: SurfaceHolder): pass def __init__(self, surface: Any = None): super().__init__() self._surface = surface self._is_creating: bool = False self._type: int = SurfaceHolder.SURFACE_TYPE_NORMAL self._width: int = 0 self._height: int = 0 self._format: int = 0 self._callbacks: List[SurfaceHolder.Callback] = [] self._callback2: Optional[SurfaceHolder.Callback2] = None self._fixed_size: Tuple[int, int] = (-1, -1) self._keep_screen_on: bool = False def getSurface(self) -> Any: return self._surface def setSurface(self, surface: Any): self._surface = surface def addCallback(self, callback: Callback): if callback not in self._callbacks: self._callbacks.append(callback) def removeCallback(self, callback: Callback): self._callbacks = [c for c in self._callbacks if c is not callback] def getCallbacks(self) -> List[Callback]: return list(self._callbacks) def setType(self, type_: int): self._type = type_ def getType(self) -> int: return self._type def setFixedSize(self, width: int, height: int): self._fixed_size = (width, height) self._width = width self._height = height def getFixedSize(self) -> Tuple[int, int]: return self._fixed_size def setSizeFromLayout(self): """从布局获取大小""" pass def isCreating(self) -> bool: return self._is_creating def setCreating(self, creating: bool): self._is_creating = creating if creating: for cb in self._callbacks: cb.surfaceCreated(self) def setFormat(self, format: int): self._format = format def getFormat(self) -> int: return self._format def getWidth(self) -> int: return self._width def getHeight(self) -> int: return self._height def setKeepScreenOn(self, keep_on: bool): self._keep_screen_on = keep_on def isKeepScreenOn(self) -> bool: return self._keep_screen_on def lockCanvas(self) -> Any: """锁定画布""" return None def lockCanvas(Rect: Any) -> Any: """锁定画布指定区域""" return None def unlockCanvasAndPost(self, canvas: Any): """解锁画布并提交""" pass def notifySurfaceCreated(self): for cb in self._callbacks: cb.surfaceCreated(self) def notifySurfaceChanged(self, format: int, width: int, height: int): for cb in self._callbacks: cb.surfaceChanged(self, format, width, height) def notifySurfaceDestroyed(self): for cb in self._callbacks: cb.surfaceDestroyed(self) def toString(self) -> str: return f"SurfaceHolder({self._width}x{self._height}, type={self._type})" # ═══════════════════════════════════════════════════════════════ # SurfaceView # ═══════════════════════════════════════════════════════════════ class SurfaceView(Stub): """SurfaceView — 表面视图""" def __init__(self, context: Any = None): super().__init__() self._context = context self._holder: Optional[SurfaceHolder] = SurfaceHolder() self._is_visible: bool = False self._is_created: bool = False self._width: int = 0 self._height: int = 0 self._format: int = 0 self._z_order: int = 0 self._is_securable: bool = False self._transparent_region: Optional[Any] = None self._surface_frame: Optional[Any] = None self._window_token: Any = None def getHolder(self) -> SurfaceHolder: return self._holder def setZOrderOnTop(self, on_top: bool): """设置 Z 轴顺序在顶层""" self._z_order = 1 if on_top else 0 def setZOrderMediaOverlay(self, is_media_overlay: bool): """设置媒体覆盖 Z 轴顺序""" self._z_order = 2 if is_media_overlay else 0 def setVisibility(self, visible: bool): self._is_visible = visible def isVisible(self) -> bool: return self._is_visible def getWidth(self) -> int: return self._width def getHeight(self) -> int: return self._height def setSecure(self, secure: bool): self._is_securable = secure def isSecure(self) -> bool: return self._is_securable def getContext(self) -> Any: return self._context def getWindowToken(self) -> Any: return self._window_token def setWindowToken(self, token: Any): self._window_token = token def onWindowVisibilityChanged(self, visibility: int): """窗口可见性变化回调""" pass def onMeasure(self, width_measure_spec: int, height_measure_spec: int): """测量回调""" pass def onLayout(self, changed: bool, left: int, top: int, right: int, bottom: int): """布局回调""" self._width = right - left self._height = bottom - top if self._holder: self._holder.notifySurfaceChanged(self._format, self._width, self._height) def draw(self, canvas: Any): """绘制""" pass def toString(self) -> str: return f"SurfaceView({self._width}x{self._height}, visible={self._is_visible})" # ═══════════════════════════════════════════════════════════════ # GLSurfaceView # ═══════════════════════════════════════════════════════════════ class GLSurfaceView(SurfaceView): """GLSurfaceView — OpenGL ES 表面视图""" RENDERMODE_CONTINUOUSLY = 1 RENDERMODE_WHEN_DIRTY = 0 DEBUG_CHECK_GL_ERROR = 1 DEBUG_LOG_GL_CALLS = 2 class Renderer(Stub): """GLSurfaceView.Renderer — OpenGL 渲染器""" def onSurfaceCreated(self, gl: Any, config: Any): pass def onSurfaceChanged(self, gl: Any, width: int, height: int): pass def onDrawFrame(self, gl: Any): pass def __init__(self, context: Any = None): super().__init__(context) self._renderer: Optional[GLSurfaceView.Renderer] = None self._render_mode: int = GLSurfaceView.RENDERMODE_CONTINUOUSLY self._egl_context_client_version: int = 2 self._preserve_egl_context_on_pause: bool = False self._debug_flags: int = 0 self._is_running: bool = False self._is_paused: bool = False self._frame_count: int = 0 self._request_render: bool = False def setRenderer(self, renderer: Renderer): """设置渲染器""" self._renderer = renderer def getRenderer(self) -> Optional[Renderer]: return self._renderer def setRenderMode(self, mode: int): """设置渲染模式""" self._render_mode = mode def getRenderMode(self) -> int: return self._render_mode def requestRender(self): """请求渲染""" self._request_render = True if self._render_mode == GLSurfaceView.RENDERMODE_WHEN_DIRTY: self._frame_count += 1 def queueEvent(self, r: Callable): """队列事件""" r() def onPause(self): """暂停""" self._is_paused = True self._is_running = False def onResume(self): """恢复""" self._is_paused = False self._is_running = True def setPreserveEGLContextOnPause(self, preserve: bool): self._preserve_egl_context_on_pause = preserve def getPreserveEGLContextOnPause(self) -> bool: return self._preserve_egl_context_on_pause def setEGLContextClientVersion(self, version: int): self._egl_context_client_version = version def getEGLContextClientVersion(self) -> int: return self._egl_context_client_version def setDebugFlags(self, flags: int): self._debug_flags = flags def getDebugFlags(self) -> int: return self._debug_flags def isRunning(self) -> bool: return self._is_running def isPaused(self) -> bool: return self._is_paused def getFrameCount(self) -> int: return self._frame_count def onSurfaceCreated(self, gl: Any, config: Any): if self._renderer: self._renderer.onSurfaceCreated(gl, config) def onSurfaceChanged(self, gl: Any, width: int, height: int): if self._renderer: self._renderer.onSurfaceChanged(gl, width, height) def onDrawFrame(self, gl: Any): if self._renderer: self._renderer.onDrawFrame(gl) def destroyDrawingCache(self): pass def toString(self) -> str: return f"GLSurfaceView(renderMode={self._render_mode}, running={self._is_running})" # ═══════════════════════════════════════════════════════════════ # Surface (helper) # ═══════════════════════════════════════════════════════════════ class Surface(Stub): """Surface — 表面 (android.view.Surface)""" ROTATION_0 = 0 ROTATION_90 = 1 ROTATION_180 = 2 ROTATION_270 = 3 SCALING_MODE_FREEZE = 0 SCALING_MODE_SCALE_TO_WINDOW = 1 SCALING_MODE_SCALE_CROP = 2 SCALING_MODE_NO_SCALE_CROP = 3 def __init__(self, surface_texture: Optional[SurfaceTexture] = None): super().__init__() self._surface_texture = surface_texture self._is_valid: bool = True self._is_released: bool = False self._width: int = 0 self._height: int = 0 self._format: int = 0 self._name: str = "" def isValid(self) -> bool: return self._is_valid and not self._is_released def isReleased(self) -> bool: return self._is_released def release(self): self._is_released = True def getSurfaceTexture(self) -> Optional[SurfaceTexture]: return self._surface_texture def setSurfaceTexture(self, st: SurfaceTexture): self._surface_texture = st def getWidth(self) -> int: return self._width def getHeight(self) -> int: return self._height def setWidth(self, width: int): self._width = width def setHeight(self, height: int): self._height = height def getFormat(self) -> int: return self._format def setName(self, name: str): self._name = name def getName(self) -> str: return self._name def lockCanvas(self, in_out_dirty_rect: Any = None) -> Any: """锁定画布""" if self._is_released: return None return None def unlockCanvasAndPost(self, canvas: Any): """解锁画布并提交""" pass def toString(self) -> str: return f"Surface(name={self._name}, valid={self._is_valid}, released={self._is_released})" # ═══════════════════════════════════════════════════════════════ # SurfaceControl (helper) # ═══════════════════════════════════════════════════════════════ class SurfaceControl(Stub): """SurfaceControl — 表面控制""" BUFFER_TRANSFORM_IDENTITY = 0 BUFFER_TRANSFORM_MIRROR_HORIZONTAL = 1 BUFFER_TRANSFORM_MIRROR_VERTICAL = 2 BUFFER_TRANSFORM_ROTATE_90 = 4 BUFFER_TRANSFORM_ROTATE_180 = 3 BUFFER_TRANSFORM_ROTATE_270 = 7 def __init__(self, surface: Optional[Surface] = None): super().__init__() self._surface = surface self._alpha: float = 1.0 self._layer: int = 0 self._z_order: int = 0 self._is_visible: bool = True self._transform: int = SurfaceControl.BUFFER_TRANSFORM_IDENTITY self._crop: Tuple[int, int, int, int] = (0, 0, 0, 0) def getSurface(self) -> Optional[Surface]: return self._surface def setSurface(self, surface: Surface): self._surface = surface def setAlpha(self, alpha: float): self._alpha = max(0.0, min(1.0, alpha)) def getAlpha(self) -> float: return self._alpha def setLayer(self, layer: int): self._layer = layer def getLayer(self) -> int: return self._layer def setVisibility(self, visible: bool): self._is_visible = visible def isVisible(self) -> bool: return self._is_visible def setTransform(self, transform: int): self._transform = transform def getTransform(self) -> int: return self._transform def setCrop(self, left: int, top: int, right: int, bottom: int): self._crop = (left, top, right, bottom) def getCrop(self) -> Tuple[int, int, int, int]: return self._crop def release(self): if self._surface: self._surface.release() def toString(self) -> str: return f"SurfaceControl(layer={self._layer}, alpha={self._alpha})" # ═══════════════════════════════════════════════════════════════ # SurfaceUtils # ═══════════════════════════════════════════════════════════════ class SurfaceUtils(Stub): """SurfaceUtils — 表面工具类""" @staticmethod def createSurfaceFromTexture(texture: SurfaceTexture) -> Surface: return Surface(texture) @staticmethod def createSurfaceTexture(tex_name: int = 0) -> SurfaceTexture: return SurfaceTexture(tex_name) @staticmethod def createGLSurfaceView(context: Any) -> GLSurfaceView: return GLSurfaceView(context) @staticmethod def createSurfaceView(context: Any) -> SurfaceView: return SurfaceView(context) @staticmethod def createSurfaceHolder(surface: Any) -> SurfaceHolder: return SurfaceHolder(surface) @staticmethod def isSurfaceValid(surface: Surface) -> bool: return surface is not None and surface.isValid() @staticmethod def releaseSurface(surface: Surface): if surface: surface.release() @staticmethod def releaseSurfaceTexture(texture: SurfaceTexture): if texture: texture.release() @staticmethod def getDefaultRenderer(context: Any) -> GLSurfaceView.Renderer: class DefaultRenderer(GLSurfaceView.Renderer): def onSurfaceCreated(self, gl, config): pass def onSurfaceChanged(self, gl, width, height): pass def onDrawFrame(self, gl): pass return DefaultRenderer() @staticmethod def createSimpleRenderer() -> GLSurfaceView.Renderer: class SimpleRenderer(GLSurfaceView.Renderer): def __init__(self): super().__init__() self._background_color: Tuple[float, float, float, float] = (0.0, 0.0, 0.0, 1.0) def onSurfaceCreated(self, gl, config): pass def onSurfaceChanged(self, gl, width, height): pass def onDrawFrame(self, gl): pass def setBackgroundColor(self, r: float, g: float, b: float, a: float): self._background_color = (r, g, b, a) return SimpleRenderer() @staticmethod def getSurfaceRotationDegrees(rotation: int) -> int: return rotation * 90