""" Android OpenGL 组件 — GLSurfaceView, GLU, GLUtils, EGL14 等 方法签名完全对齐 Android SDK (android.opengl 包) """ import math from typing import Any, Callable, List, Optional, Tuple from .._core import Stub, AndroidOnlyError # ═══════════════════════════════════════════════════════════════ # EGL 常量 # ═══════════════════════════════════════════════════════════════ class EGL14(Stub): """EGL14 — EGL 1.4 API 常量 (桌面仅提供常量)""" # EGL 布尔值 EGL_TRUE = 1 EGL_FALSE = 0 # EGL 错误码 EGL_SUCCESS = 0x3000 EGL_NOT_INITIALIZED = 0x3001 EGL_BAD_ACCESS = 0x3002 EGL_BAD_ALLOC = 0x3003 EGL_BAD_ATTRIBUTE = 0x3004 EGL_BAD_CONFIG = 0x3005 EGL_BAD_CONTEXT = 0x3006 EGL_BAD_CURRENT_SURFACE = 0x3007 EGL_BAD_DISPLAY = 0x3008 EGL_BAD_MATCH = 0x3009 EGL_BAD_NATIVE_PIXMAP = 0x300A EGL_BAD_NATIVE_WINDOW = 0x300B EGL_BAD_PARAMETER = 0x300C EGL_BAD_SURFACE = 0x300D EGL_CONTEXT_LOST = 0x300E # EGL 配置属性 EGL_BUFFER_SIZE = 0x3020 EGL_ALPHA_SIZE = 0x3021 EGL_BLUE_SIZE = 0x3022 EGL_GREEN_SIZE = 0x3023 EGL_RED_SIZE = 0x3024 EGL_DEPTH_SIZE = 0x3025 EGL_STENCIL_SIZE = 0x3026 EGL_CONFIG_CAVEAT = 0x3027 EGL_CONFIG_ID = 0x3028 EGL_LEVEL = 0x3029 EGL_MAX_PBUFFER_HEIGHT = 0x302A EGL_MAX_PBUFFER_PIXELS = 0x302B EGL_MAX_PBUFFER_WIDTH = 0x302C EGL_NATIVE_RENDERABLE = 0x302D EGL_NATIVE_VISUAL_ID = 0x302E EGL_NATIVE_VISUAL_TYPE = 0x302F EGL_PRESERVED_RESOURCES = 0x3030 EGL_SAMPLES = 0x3031 EGL_SAMPLE_BUFFERS = 0x3032 EGL_SURFACE_TYPE = 0x3033 EGL_TRANSPARENT_TYPE = 0x3034 EGL_TRANSPARENT_BLUE_VALUE = 0x3035 EGL_TRANSPARENT_GREEN_VALUE = 0x3036 EGL_TRANSPARENT_RED_VALUE = 0x3037 EGL_NONE = 0x3038 EGL_BIND_TO_TEXTURE_RGB = 0x3039 EGL_BIND_TO_TEXTURE_RGBA = 0x303A EGL_MIN_SWAP_INTERVAL = 0x303B EGL_MAX_SWAP_INTERVAL = 0x303C # EGL 表面属性 EGL_WIDTH = 0x3057 EGL_HEIGHT = 0x3056 EGL_LARGEST_PBUFFER = 0x3058 EGL_TEXTURE_FORMAT = 0x3080 EGL_TEXTURE_TARGET = 0x3081 EGL_MIPMAP_TEXTURE = 0x3082 EGL_MIPMAP_LEVEL = 0x3083 # EGL 渲染上下文属性 EGL_CONTEXT_CLIENT_TYPE = 0x3097 EGL_CONTEXT_CLIENT_VERSION = 0x3098 # EGL 显示 EGL_DEFAULT_DISPLAY = 0 # EGL 版本 EGL_VERSION_1_4 = 1 # OpenGL ES 位标记 EGL_OPENGL_ES_BIT = 0x0001 EGL_OPENGL_ES2_BIT = 0x0004 EGL_OPENGL_ES3_BIT = 0x0040 def __init__(self): super().__init__() @staticmethod def eglGetDisplay(display_id: Any) -> "EGLDisplay": """获取 EGL 显示 (桌面仅返回存根)""" raise AndroidOnlyError("EGL14.eglGetDisplay() 仅在 Android 设备上可用") @staticmethod def eglInitialize(display: "EGLDisplay", major_minor: Optional[List[int]] = None) -> bool: """初始化 EGL (桌面仅返回存根)""" raise AndroidOnlyError("EGL14.eglInitialize() 仅在 Android 设备上可用") @staticmethod def eglChooseConfig(display: "EGLDisplay", attrib_list: List[int], configs: List[Any], config_size: int, num_config: List[int]) -> bool: """选择 EGL 配置 (桌面仅返回存根)""" raise AndroidOnlyError("EGL14.eglChooseConfig() 仅在 Android 设备上可用") @staticmethod def eglCreateContext(display: "EGLDisplay", config: "EGLConfig", share_context: "EGLContext", attrib_list: List[int]) -> "EGLContext": """创建 EGL 上下文 (桌面仅返回存根)""" raise AndroidOnlyError("EGL14.eglCreateContext() 仅在 Android 设备上可用") @staticmethod def eglCreateWindowSurface(display: "EGLDisplay", config: "EGLConfig", win: Any, attrib_list: List[int]) -> "EGLSurface": """创建窗口表面 (桌面仅返回存根)""" raise AndroidOnlyError("EGL14.eglCreateWindowSurface() 仅在 Android 设备上可用") @staticmethod def eglMakeCurrent(display: "EGLDisplay", draw: "EGLSurface", read: "EGLSurface", context: "EGLContext") -> bool: """绑定 EGL 上下文 (桌面仅返回存根)""" raise AndroidOnlyError("EGL14.eglMakeCurrent() 仅在 Android 设备上可用") @staticmethod def eglSwapBuffers(display: "EGLDisplay", surface: "EGLSurface") -> bool: """交换缓冲区 (桌面仅返回存根)""" raise AndroidOnlyError("EGL14.eglSwapBuffers() 仅在 Android 设备上可用") @staticmethod def eglDestroyContext(display: "EGLDisplay", context: "EGLContext") -> bool: """销毁 EGL 上下文 (桌面仅返回存根)""" raise AndroidOnlyError("EGL14.eglDestroyContext() 仅在 Android 设备上可用") @staticmethod def eglDestroySurface(display: "EGLDisplay", surface: "EGLSurface") -> bool: """销毁表面 (桌面仅返回存根)""" raise AndroidOnlyError("EGL14.eglDestroySurface() 仅在 Android 设备上可用") @staticmethod def eglTerminate(display: "EGLDisplay") -> bool: """终止 EGL (桌面仅返回存根)""" raise AndroidOnlyError("EGL14.eglTerminate() 仅在 Android 设备上可用") @staticmethod def eglGetError() -> int: """获取 EGL 错误码""" return EGL14.EGL_SUCCESS @staticmethod def eglQueryString(display: "EGLDisplay", name: int) -> str: """查询 EGL 字符串""" if name == 0x3029: # EGL_VERSION return "1.4 (desktop stub)" return "" def toString(self) -> str: return "EGL14(desktop-stub)" class EGLDisplay(Stub): """EGLDisplay — EGL 显示连接""" def __init__(self): super().__init__() def toString(self) -> str: return f"EGLDisplay@{hex(id(self))}" def hashCode(self) -> int: return hash(id(self)) & 0x7FFFFFFF def equals(self, other) -> bool: return self is other class EGLConfig(Stub): """EGLConfig — EGL 帧缓冲配置""" def __init__(self): super().__init__() def toString(self) -> str: return f"EGLConfig@{hex(id(self))}" def hashCode(self) -> int: return hash(id(self)) & 0x7FFFFFFF def equals(self, other) -> bool: return self is other class EGLContext(Stub): """EGLContext — EGL 渲染上下文""" def __init__(self): super().__init__() def toString(self) -> str: return f"EGLContext@{hex(id(self))}" def hashCode(self) -> int: return hash(id(self)) & 0x7FFFFFFF def equals(self, other) -> bool: return self is other class EGLSurface(Stub): """EGLSurface — EGL 渲染表面""" def __init__(self): super().__init__() def toString(self) -> str: return f"EGLSurface@{hex(id(self))}" def hashCode(self) -> int: return hash(id(self)) & 0x7FFFFFFF def equals(self, other) -> bool: return self is other # ═══════════════════════════════════════════════════════════════ # GLSurfaceView # ═══════════════════════════════════════════════════════════════ class GLSurfaceView(Stub): """GLSurfaceView — OpenGL 渲染视图 (桌面存根)""" # 渲染模式 RENDERMODE_CONTINUOUSLY = 1 RENDERMODE_WHEN_DIRTY = 0 # 调试标志 DEBUG_CHECK_GL_ERROR = 1 DEBUG_LOG_GL_CALLS = 2 def __init__(self, context: Any = None): super().__init__() self._context = context self._renderer: Optional[Any] = 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._paused: bool = False self._queue: List[Callable] = [] def setRenderer(self, renderer: Any): """设置渲染器""" self._renderer = renderer if renderer: renderer.onSurfaceCreated(None, None) renderer.onSurfaceChanged(None, 0, 0) def setRenderMode(self, render_mode: int): """设置渲染模式""" self._render_mode = render_mode def getRenderMode(self) -> int: """获取渲染模式""" return self._render_mode def onPause(self): """暂停渲染""" self._paused = True def onResume(self): """恢复渲染""" self._paused = False def queueEvent(self, r: Callable): """将事件排入 GL 线程队列""" self._queue.append(r) # 立即执行 (桌面模拟) try: r() except Exception: pass def requestRender(self): """请求渲染""" if self._renderer and not self._paused: self._renderer.onDrawFrame(None) def setEGLContextClientVersion(self, version: int): """设置 EGL 客户端版本""" self._egl_context_client_version = version def setPreserveEGLContextOnPause(self, preserve: bool): """设置暂停时是否保留 EGL 上下文""" self._preserve_egl_context_on_pause = preserve def setDebugFlags(self, debug_flags: int): """设置调试标志""" self._debug_flags = debug_flags def getPreserveEGLContextOnPause(self) -> bool: return self._preserve_egl_context_on_pause def surfaceCreated(self, holder: Any): """表面创建回调""" pass def surfaceDestroyed(self, holder: Any): """表面销毁回调""" pass def surfaceChanged(self, holder: Any, format: int, w: int, h: int): """表面变化回调""" pass def toString(self) -> str: return f"GLSurfaceView(renderMode={self._render_mode}, paused={self._paused})" def hashCode(self) -> int: return id(self) & 0x7FFFFFFF def equals(self, other) -> bool: return self is other # ═══════════════════════════════════════════════════════════════ # GLU # ═══════════════════════════════════════════════════════════════ class GLU(Stub): """GLU — OpenGL 实用工具函数""" def __init__(self): super().__init__() @staticmethod def gluLookAt(eye_x: float, eye_y: float, eye_z: float, center_x: float, center_y: float, center_z: float, up_x: float, up_y: float, up_z: float): """定义视图变换 (桌面仅抛异常)""" raise AndroidOnlyError("GLU.gluLookAt() 仅在 Android (OpenGL) 设备上可用") @staticmethod def gluPerspective(fov_y: float, aspect: float, z_near: float, z_far: float): """设置透视投影 (桌面仅抛异常)""" raise AndroidOnlyError("GLU.gluPerspective() 仅在 Android (OpenGL) 设备上可用") @staticmethod def gluOrtho2D(left: float, right: float, bottom: float, top: float): """设置正交投影 (桌面仅抛异常)""" raise AndroidOnlyError("GLU.gluOrtho2D() 仅在 Android (OpenGL) 设备上可用") @staticmethod def gluProject(obj_x: float, obj_y: float, obj_z: float, model: List[float], proj: List[float], viewport: List[int]) -> Tuple[bool, float, float, float]: """将对象坐标映射到窗口坐标""" win_x = (obj_x * proj[0] + 1.0) * viewport[2] / 2.0 + viewport[0] win_y = (obj_y * proj[5] + 1.0) * viewport[3] / 2.0 + viewport[1] win_z = obj_z * proj[10] + proj[11] return True, win_x, win_y, win_z @staticmethod def gluUnProject(win_x: float, win_y: float, win_z: float, model: List[float], proj: List[float], viewport: List[int]) -> Tuple[bool, float, float, float]: """将窗口坐标映射到对象坐标""" obj_x = 2.0 * (win_x - viewport[0]) / viewport[2] - 1.0 obj_y = 2.0 * (win_y - viewport[1]) / viewport[3] - 1.0 obj_z = win_z * 2.0 - 1.0 return True, obj_x, obj_y, obj_z @staticmethod def gluErrorString(error: int) -> str: """返回 OpenGL 错误描述字符串""" errors = { 0x0500: "GL_INVALID_ENUM", 0x0501: "GL_INVALID_VALUE", 0x0502: "GL_INVALID_OPERATION", 0x0503: "GL_STACK_OVERFLOW", 0x0504: "GL_STACK_UNDERFLOW", 0x0505: "GL_OUT_OF_MEMORY", 0x0506: "GL_INVALID_FRAMEBUFFER_OPERATION", } return errors.get(error, f"Unknown error 0x{error:04X}") def toString(self) -> str: return "GLU(desktop-stub)" def hashCode(self) -> int: return hash("android.opengl.GLU") & 0x7FFFFFFF def equals(self, other) -> bool: return isinstance(other, GLU) # ═══════════════════════════════════════════════════════════════ # GLUtils # ═══════════════════════════════════════════════════════════════ class GLUtils(Stub): """GLUtils — OpenGL 工具函数""" def __init__(self): super().__init__() @staticmethod def getInternalFormat(bitmap: Any) -> int: """获取位图的内部格式""" return 0x1908 # GL_RGBA @staticmethod def getType(bitmap: Any) -> int: """获取位图数据类型""" return 0x1401 # GL_UNSIGNED_BYTE @staticmethod def texImage2D(target: int, level: int, internal_format: int, bitmap: Any, border: int = 0): """上传 2D 纹理图像""" raise AndroidOnlyError("GLUtils.texImage2D() 仅在 Android (OpenGL) 设备上可用") @staticmethod def texSubImage2D(target: int, level: int, xoffset: int, yoffset: int, bitmap: Any, format: int = -1, type_: int = -1): """更新 2D 纹理子图像""" raise AndroidOnlyError("GLUtils.texSubImage2D() 仅在 Android (OpenGL) 设备上可用") @staticmethod def toString(bitmap_or_buffer: Any) -> str: return str(bitmap_or_buffer) def toString(self) -> str: return "GLUtils(desktop-stub)" def hashCode(self) -> int: return hash("android.opengl.GLUtils") & 0x7FFFFFFF def equals(self, other) -> bool: return isinstance(other, GLUtils) # ═══════════════════════════════════════════════════════════════ # __all__ # ═══════════════════════════════════════════════════════════════ __all__ = [ "GLSurfaceView", "GLU", "GLUtils", "EGL14", "EGLConfig", "EGLContext", "EGLDisplay", "EGLSurface", ]