From aeff232c91c73d1466cc63d2fa43bd2c109b042a Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Mon, 9 Mar 2026 09:24:54 +0000 Subject: [PATCH 1/5] [WIP] Commit of opengl widget. --- cocoa/src/toga_cocoa/libs/appkit.py | 6 + cocoa/src/toga_cocoa/widgets/openglview.py | 99 ++ core/src/toga/__init__.pyi | 1 + core/src/toga/widgets/gl/__init__.py | 0 core/src/toga/widgets/gl/openglcontext.py | 1507 ++++++++++++++++++++ core/src/toga/widgets/gl/openglview.py | 55 + examples/opengl/CHANGELOG | 1 + examples/opengl/LICENSE | 1 + examples/opengl/README.md | 19 + examples/opengl/opengl/__init__.py | 9 + examples/opengl/opengl/__main__.py | 4 + examples/opengl/opengl/app.py | 31 + examples/opengl/opengl/resources/star.png | Bin 0 -> 4654 bytes examples/opengl/pyproject.toml | 70 + qt/src/toga_qt/widgets/openglview.py | 120 ++ 15 files changed, 1923 insertions(+) create mode 100644 cocoa/src/toga_cocoa/widgets/openglview.py create mode 100644 core/src/toga/widgets/gl/__init__.py create mode 100644 core/src/toga/widgets/gl/openglcontext.py create mode 100644 core/src/toga/widgets/gl/openglview.py create mode 100644 examples/opengl/CHANGELOG create mode 100644 examples/opengl/LICENSE create mode 100644 examples/opengl/README.md create mode 100644 examples/opengl/opengl/__init__.py create mode 100644 examples/opengl/opengl/__main__.py create mode 100644 examples/opengl/opengl/app.py create mode 100644 examples/opengl/opengl/resources/star.png create mode 100644 examples/opengl/pyproject.toml create mode 100644 qt/src/toga_qt/widgets/openglview.py diff --git a/cocoa/src/toga_cocoa/libs/appkit.py b/cocoa/src/toga_cocoa/libs/appkit.py index b2fff69ebc..3faab77c8c 100644 --- a/cocoa/src/toga_cocoa/libs/appkit.py +++ b/cocoa/src/toga_cocoa/libs/appkit.py @@ -522,6 +522,12 @@ class NSLayoutPriority(Enum): NSOpenGLCPSwapInterval = 222 +###################################################################### +# NSOpenGLView.h +NSOpenGLView = ObjCClass("NSOpenGLView") +NSOpenGLContext = ObjCClass("NSOpenGLContext") +NSOpenGLPixelFormat = ObjCClass("NSOpenGLPixelFormat") + ###################################################################### # NSOpenPanel.h NSOpenPanel = ObjCClass("NSOpenPanel") diff --git a/cocoa/src/toga_cocoa/widgets/openglview.py b/cocoa/src/toga_cocoa/widgets/openglview.py new file mode 100644 index 0000000000..2258d3640e --- /dev/null +++ b/cocoa/src/toga_cocoa/widgets/openglview.py @@ -0,0 +1,99 @@ +import ctypes + +import moderngl +from OpenGL import GL +from rubicon.objc import objc_method, objc_property +from travertino.size import at_least + +from toga.widgets.gl.openglcontext import OpenGLContext +from toga_cocoa.libs import ( + NSOpenGLPFAAccelerated, + NSOpenGLPFAAccumSize, + NSOpenGLPFAAlphaSize, + NSOpenGLPFAColorSize, + NSOpenGLPFADepthSize, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFANoRecovery, + NSOpenGLPFAStencilSize, + NSOpenGLPFAWindow, + NSOpenGLPixelFormat, + NSOpenGLView, + NSRect, +) + +from .base import Widget + + +class CocoaOpenGLContext(OpenGLContext): + def __init__(self, impl): + self.impl = impl + self.native = impl.native.openGLContext + print(self.native) + + def clear_color(self, r: float, g: float, b: float, a: float): + GL.glClearColor(r, g, b, a) + print("here") + + def clear(self, mask: int): + GL.glClear(mask) + print("and here") + + +class TogaOpenGLView(NSOpenGLView): + interface = objc_property(object, weak=True) + impl = objc_property(object, weak=True) + + @objc_method + def drawRect_(self, rect: NSRect) -> None: + self.openGLContext.makeCurrentContext() + context = moderngl.create_context() + context.clear(1.0, 0.0, 0.0, 1.0) + # context = CocoaOpenGLContext(self.impl) + # context.native.makeCurrentContext() + # GL.glViewport(0, 0, int(rect.size.width), int(rect.size.height)) + # GL.glClearColor(1.0, 0.0, 0.0, 1.0) + # GL.glClear(GL.GL_COLOR_BUFFER_BIT) + # print('here') + # # self.interface.on_render(context) + self.openGLContext.flushBuffer() + + @objc_method + def initWithFrame(self, frame: NSRect): + a = ( + NSOpenGLPFANoRecovery, + NSOpenGLPFAWindow, + NSOpenGLPFAAccelerated, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAColorSize, + 24, + NSOpenGLPFAAlphaSize, + 8, + NSOpenGLPFADepthSize, + 24, + NSOpenGLPFAStencilSize, + 8, + NSOpenGLPFAAccumSize, + 0, + ) + attributes = (ctypes.c_uint32 * len(a))(*a) + pixel_format = NSOpenGLPixelFormat.alloc().initWithAttributes(attributes) + self.initWithFrame_pixelFormat(frame, pixel_format) + + +class OpenGLView(Widget): + def create(self): + self.native = TogaOpenGLView.alloc().init() + self.native.interface = self.interface + self.native.impl = self + + # Add the layout constraints + self.add_constraints() + + def redraw(self): + self.native.needsDisplay = True + + # Rehint + def rehint(self): + fitting_size = self.native.fittingSize() + self.interface.intrinsic.height = at_least(fitting_size.height) + self.interface.intrinsic.width = at_least(fitting_size.width) diff --git a/core/src/toga/__init__.pyi b/core/src/toga/__init__.pyi index da118ad4fa..49606a6553 100644 --- a/core/src/toga/__init__.pyi +++ b/core/src/toga/__init__.pyi @@ -47,6 +47,7 @@ from toga.widgets.multilinetextinput import MultilineTextInput as MultilineTextI from toga.widgets.numberinput import NumberInput as NumberInput from toga.widgets.optioncontainer import OptionContainer as OptionContainer from toga.widgets.optioncontainer import OptionItem as OptionItem +from toga.widgets.gl.openglview import OpenGLView as OpenGLView from toga.widgets.passwordinput import PasswordInput as PasswordInput from toga.widgets.progressbar import ProgressBar as ProgressBar from toga.widgets.box import Row as Row diff --git a/core/src/toga/widgets/gl/__init__.py b/core/src/toga/widgets/gl/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/src/toga/widgets/gl/openglcontext.py b/core/src/toga/widgets/gl/openglcontext.py new file mode 100644 index 0000000000..47e6b4d0a4 --- /dev/null +++ b/core/src/toga/widgets/gl/openglcontext.py @@ -0,0 +1,1507 @@ +from typing import Protocol + + +class OpenGLContext(Protocol): + FALSE = 0 + POINTS = 0 + ZERO = 0 + NONE = 0 + NO_ERROR = 0 + TRUE = 1 + LINES = 1 + ONE = 1 + CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT = 1 + MAP_READ_BIT = 1 + CONTEXT_CORE_PROFILE_BIT = 1 + SYNC_FLUSH_COMMANDS_BIT = 1 + VERTEX_SHADER_BIT = 1 + VERTEX_ATTRIB_ARRAY_BARRIER_BIT = 1 + LINE_LOOP = 2 + MAP_WRITE_BIT = 2 + CONTEXT_COMPATIBILITY_PROFILE_BIT = 2 + FRAGMENT_SHADER_BIT = 2 + ELEMENT_ARRAY_BARRIER_BIT = 2 + CONTEXT_FLAG_DEBUG_BIT = 2 + LINE_STRIP = 3 + TRIANGLES = 4 + MAP_INVALIDATE_RANGE_BIT = 4 + GEOMETRY_SHADER_BIT = 4 + UNIFORM_BARRIER_BIT = 4 + CONTEXT_FLAG_ROBUST_ACCESS_BIT = 4 + TRIANGLE_STRIP = 5 + TRIANGLE_FAN = 6 + QUADS = 7 + MAP_INVALIDATE_BUFFER_BIT = 8 + TESS_CONTROL_SHADER_BIT = 8 + TEXTURE_FETCH_BARRIER_BIT = 8 + CONTEXT_FLAG_NO_ERROR_BIT = 8 + LINES_ADJACENCY = 10 + LINE_STRIP_ADJACENCY = 11 + TRIANGLES_ADJACENCY = 12 + TRIANGLE_STRIP_ADJACENCY = 13 + PATCHES = 14 + MAP_FLUSH_EXPLICIT_BIT = 16 + TESS_EVALUATION_SHADER_BIT = 16 + MAP_UNSYNCHRONIZED_BIT = 32 + SHADER_IMAGE_ACCESS_BARRIER_BIT = 32 + COMPUTE_SHADER_BIT = 32 + COMMAND_BARRIER_BIT = 64 + MAP_PERSISTENT_BIT = 64 + MESH_SHADER_BIT_NV = 64 + PIXEL_BUFFER_BARRIER_BIT = 128 + MAP_COHERENT_BIT = 128 + TASK_SHADER_BIT_NV = 128 + DEPTH_BUFFER_BIT = 256 + TEXTURE_UPDATE_BARRIER_BIT = 256 + DYNAMIC_STORAGE_BIT = 256 + NEVER = 512 + BUFFER_UPDATE_BARRIER_BIT = 512 + CLIENT_STORAGE_BIT = 512 + LESS = 513 + EQUAL = 514 + LEQUAL = 515 + GREATER = 516 + NOTEQUAL = 517 + GEQUAL = 518 + ALWAYS = 519 + SRC_COLOR = 768 + ONE_MINUS_SRC_COLOR = 769 + SRC_ALPHA = 770 + ONE_MINUS_SRC_ALPHA = 771 + DST_ALPHA = 772 + ONE_MINUS_DST_ALPHA = 773 + DST_COLOR = 774 + ONE_MINUS_DST_COLOR = 775 + SRC_ALPHA_SATURATE = 776 + STENCIL_BUFFER_BIT = 1024 + FRONT_LEFT = 1024 + FRAMEBUFFER_BARRIER_BIT = 1024 + FRONT_RIGHT = 1025 + BACK_LEFT = 1026 + BACK_RIGHT = 1027 + FRONT = 1028 + BACK = 1029 + LEFT = 1030 + RIGHT = 1031 + FRONT_AND_BACK = 1032 + INVALID_ENUM = 1280 + INVALID_VALUE = 1281 + INVALID_OPERATION = 1282 + STACK_OVERFLOW = 1283 + STACK_UNDERFLOW = 1284 + OUT_OF_MEMORY = 1285 + INVALID_FRAMEBUFFER_OPERATION = 1286 + INVALID_FRAMEBUFFER_OPERATION_EXT = 1286 + CONTEXT_LOST = 1287 + TRANSFORM_FEEDBACK_BARRIER_BIT = 2048 + CW = 2304 + CCW = 2305 + POINT_SIZE = 2833 + POINT_SIZE_RANGE = 2834 + SMOOTH_POINT_SIZE_RANGE = 2834 + POINT_SIZE_GRANULARITY = 2835 + SMOOTH_POINT_SIZE_GRANULARITY = 2835 + LINE_SMOOTH = 2848 + LINE_WIDTH = 2849 + LINE_WIDTH_RANGE = 2850 + SMOOTH_LINE_WIDTH_RANGE = 2850 + LINE_WIDTH_GRANULARITY = 2851 + SMOOTH_LINE_WIDTH_GRANULARITY = 2851 + POLYGON_MODE = 2880 + POLYGON_SMOOTH = 2881 + CULL_FACE = 2884 + CULL_FACE_MODE = 2885 + FRONT_FACE = 2886 + DEPTH_RANGE = 2928 + DEPTH_TEST = 2929 + DEPTH_WRITEMASK = 2930 + DEPTH_CLEAR_VALUE = 2931 + DEPTH_FUNC = 2932 + STENCIL_TEST = 2960 + STENCIL_CLEAR_VALUE = 2961 + STENCIL_FUNC = 2962 + STENCIL_VALUE_MASK = 2963 + STENCIL_FAIL = 2964 + STENCIL_PASS_DEPTH_FAIL = 2965 + STENCIL_PASS_DEPTH_PASS = 2966 + STENCIL_REF = 2967 + STENCIL_WRITEMASK = 2968 + VIEWPORT = 2978 + DITHER = 3024 + BLEND_DST = 3040 + BLEND_SRC = 3041 + BLEND = 3042 + LOGIC_OP_MODE = 3056 + COLOR_LOGIC_OP = 3058 + DRAW_BUFFER = 3073 + READ_BUFFER = 3074 + SCISSOR_BOX = 3088 + SCISSOR_TEST = 3089 + COLOR_CLEAR_VALUE = 3106 + COLOR_WRITEMASK = 3107 + DOUBLEBUFFER = 3122 + STEREO = 3123 + LINE_SMOOTH_HINT = 3154 + POLYGON_SMOOTH_HINT = 3155 + UNPACK_SWAP_BYTES = 3312 + UNPACK_LSB_FIRST = 3313 + UNPACK_ROW_LENGTH = 3314 + UNPACK_SKIP_ROWS = 3315 + UNPACK_SKIP_PIXELS = 3316 + UNPACK_ALIGNMENT = 3317 + PACK_SWAP_BYTES = 3328 + PACK_LSB_FIRST = 3329 + PACK_ROW_LENGTH = 3330 + PACK_SKIP_ROWS = 3331 + PACK_SKIP_PIXELS = 3332 + PACK_ALIGNMENT = 3333 + MAX_CLIP_DISTANCES = 3378 + MAX_TEXTURE_SIZE = 3379 + MAX_VIEWPORT_DIMS = 3386 + SUBPIXEL_BITS = 3408 + TEXTURE_1D = 3552 + TEXTURE_2D = 3553 + TEXTURE_WIDTH = 4096 + ATOMIC_COUNTER_BARRIER_BIT = 4096 + TEXTURE_HEIGHT = 4097 + TEXTURE_INTERNAL_FORMAT = 4099 + TEXTURE_BORDER_COLOR = 4100 + TEXTURE_TARGET = 4102 + DONT_CARE = 4352 + FASTEST = 4353 + NICEST = 4354 + BYTE = 5120 + UNSIGNED_BYTE = 5121 + SHORT = 5122 + UNSIGNED_SHORT = 5123 + INT = 5124 + UNSIGNED_INT = 5125 + FLOAT = 5126 + DOUBLE = 5130 + HALF_FLOAT = 5131 + FIXED = 5132 + INT64_ARB = 5134 + UNSIGNED_INT64_ARB = 5135 + CLEAR = 5376 + AND = 5377 + AND_REVERSE = 5378 + COPY = 5379 + AND_INVERTED = 5380 + NOOP = 5381 + XOR = 5382 + OR = 5383 + NOR = 5384 + EQUIV = 5385 + INVERT = 5386 + OR_REVERSE = 5387 + COPY_INVERTED = 5388 + OR_INVERTED = 5389 + NAND = 5390 + SET = 5391 + TEXTURE = 5890 + COLOR = 6144 + DEPTH = 6145 + STENCIL = 6146 + STENCIL_INDEX = 6401 + DEPTH_COMPONENT = 6402 + RED = 6403 + GREEN = 6404 + BLUE = 6405 + ALPHA = 6406 + RGB = 6407 + RGBA = 6408 + POINT = 6912 + LINE = 6913 + FILL = 6914 + KEEP = 7680 + REPLACE = 7681 + INCR = 7682 + DECR = 7683 + VENDOR = 7936 + RENDERER = 7937 + VERSION = 7938 + EXTENSIONS = 7939 + SHADER_STORAGE_BARRIER_BIT = 8192 + NEAREST = 9728 + LINEAR = 9729 + NEAREST_MIPMAP_NEAREST = 9984 + LINEAR_MIPMAP_NEAREST = 9985 + NEAREST_MIPMAP_LINEAR = 9986 + LINEAR_MIPMAP_LINEAR = 9987 + TEXTURE_MAG_FILTER = 10240 + TEXTURE_MIN_FILTER = 10241 + TEXTURE_WRAP_S = 10242 + TEXTURE_WRAP_T = 10243 + REPEAT = 10497 + POLYGON_OFFSET_UNITS = 10752 + POLYGON_OFFSET_POINT = 10753 + POLYGON_OFFSET_LINE = 10754 + R3_G3_B2 = 10768 + CLIP_DISTANCE0 = 12288 + CLIP_DISTANCE1 = 12289 + CLIP_DISTANCE2 = 12290 + CLIP_DISTANCE3 = 12291 + CLIP_DISTANCE4 = 12292 + CLIP_DISTANCE5 = 12293 + CLIP_DISTANCE6 = 12294 + CLIP_DISTANCE7 = 12295 + COLOR_BUFFER_BIT = 16384 + CLIENT_MAPPED_BUFFER_BARRIER_BIT = 16384 + QUERY_BUFFER_BARRIER_BIT = 32768 + CONSTANT_COLOR = 32769 + ONE_MINUS_CONSTANT_COLOR = 32770 + CONSTANT_ALPHA = 32771 + ONE_MINUS_CONSTANT_ALPHA = 32772 + BLEND_COLOR = 32773 + FUNC_ADD = 32774 + MIN = 32775 + MAX = 32776 + BLEND_EQUATION = 32777 + BLEND_EQUATION_RGB = 32777 + FUNC_SUBTRACT = 32778 + FUNC_REVERSE_SUBTRACT = 32779 + CONVOLUTION_1D = 32784 + CONVOLUTION_2D = 32785 + SEPARABLE_2D = 32786 + HISTOGRAM = 32804 + PROXY_HISTOGRAM = 32805 + MINMAX = 32814 + UNSIGNED_BYTE_3_3_2 = 32818 + UNSIGNED_SHORT_4_4_4_4 = 32819 + UNSIGNED_SHORT_5_5_5_1 = 32820 + UNSIGNED_INT_8_8_8_8 = 32821 + UNSIGNED_INT_10_10_10_2 = 32822 + POLYGON_OFFSET_FILL = 32823 + POLYGON_OFFSET_FACTOR = 32824 + RGB4 = 32847 + RGB5 = 32848 + RGB8 = 32849 + RGB10 = 32850 + RGB12 = 32851 + RGB16 = 32852 + RGBA2 = 32853 + RGBA4 = 32854 + RGB5_A1 = 32855 + RGBA8 = 32856 + RGB10_A2 = 32857 + RGBA12 = 32858 + RGBA16 = 32859 + TEXTURE_RED_SIZE = 32860 + TEXTURE_GREEN_SIZE = 32861 + TEXTURE_BLUE_SIZE = 32862 + TEXTURE_ALPHA_SIZE = 32863 + PROXY_TEXTURE_1D = 32867 + PROXY_TEXTURE_2D = 32868 + TEXTURE_BINDING_1D = 32872 + TEXTURE_BINDING_2D = 32873 + TEXTURE_BINDING_3D = 32874 + PACK_SKIP_IMAGES = 32875 + PACK_IMAGE_HEIGHT = 32876 + UNPACK_SKIP_IMAGES = 32877 + UNPACK_IMAGE_HEIGHT = 32878 + TEXTURE_3D = 32879 + PROXY_TEXTURE_3D = 32880 + TEXTURE_DEPTH = 32881 + TEXTURE_WRAP_R = 32882 + MAX_3D_TEXTURE_SIZE = 32883 + VERTEX_ARRAY = 32884 + MULTISAMPLE = 32925 + MULTISAMPLE_ARB = 32925 + SAMPLE_ALPHA_TO_COVERAGE = 32926 + SAMPLE_ALPHA_TO_COVERAGE_ARB = 32926 + SAMPLE_ALPHA_TO_ONE = 32927 + SAMPLE_ALPHA_TO_ONE_ARB = 32927 + SAMPLE_COVERAGE = 32928 + SAMPLE_COVERAGE_ARB = 32928 + SAMPLE_BUFFERS = 32936 + SAMPLE_BUFFERS_ARB = 32936 + SAMPLES = 32937 + SAMPLES_ARB = 32937 + SAMPLE_COVERAGE_VALUE = 32938 + SAMPLE_COVERAGE_VALUE_ARB = 32938 + SAMPLE_COVERAGE_INVERT = 32939 + SAMPLE_COVERAGE_INVERT_ARB = 32939 + BLEND_DST_RGB = 32968 + BLEND_SRC_RGB = 32969 + BLEND_DST_ALPHA = 32970 + BLEND_SRC_ALPHA = 32971 + COLOR_TABLE = 32976 + POST_CONVOLUTION_COLOR_TABLE = 32977 + POST_COLOR_MATRIX_COLOR_TABLE = 32978 + PROXY_COLOR_TABLE = 32979 + PROXY_POST_CONVOLUTION_COLOR_TABLE = 32980 + PROXY_POST_COLOR_MATRIX_COLOR_TABLE = 32981 + BGR = 32992 + BGRA = 32993 + MAX_ELEMENTS_VERTICES = 33000 + MAX_ELEMENTS_INDICES = 33001 + PARAMETER_BUFFER = 33006 + PARAMETER_BUFFER_BINDING = 33007 + POINT_FADE_THRESHOLD_SIZE = 33064 + CLAMP_TO_BORDER = 33069 + CLAMP_TO_EDGE = 33071 + TEXTURE_MIN_LOD = 33082 + TEXTURE_MAX_LOD = 33083 + TEXTURE_BASE_LEVEL = 33084 + TEXTURE_MAX_LEVEL = 33085 + DEPTH_COMPONENT16 = 33189 + DEPTH_COMPONENT24 = 33190 + DEPTH_COMPONENT32 = 33191 + FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = 33296 + FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE = 33297 + FRAMEBUFFER_ATTACHMENT_RED_SIZE = 33298 + FRAMEBUFFER_ATTACHMENT_GREEN_SIZE = 33299 + FRAMEBUFFER_ATTACHMENT_BLUE_SIZE = 33300 + FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE = 33301 + FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE = 33302 + FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE = 33303 + FRAMEBUFFER_DEFAULT = 33304 + FRAMEBUFFER_UNDEFINED = 33305 + DEPTH_STENCIL_ATTACHMENT = 33306 + MAJOR_VERSION = 33307 + MINOR_VERSION = 33308 + NUM_EXTENSIONS = 33309 + CONTEXT_FLAGS = 33310 + BUFFER_IMMUTABLE_STORAGE = 33311 + BUFFER_STORAGE_FLAGS = 33312 + PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED = 33313 + COMPRESSED_RED = 33317 + COMPRESSED_RG = 33318 + RG = 33319 + RG_INTEGER = 33320 + R8 = 33321 + R16 = 33322 + RG8 = 33323 + RG16 = 33324 + R16F = 33325 + R32F = 33326 + RG16F = 33327 + RG32F = 33328 + R8I = 33329 + R8UI = 33330 + R16I = 33331 + R16UI = 33332 + R32I = 33333 + R32UI = 33334 + RG8I = 33335 + RG8UI = 33336 + RG16I = 33337 + RG16UI = 33338 + RG32I = 33339 + RG32UI = 33340 + DEBUG_OUTPUT_SYNCHRONOUS = 33346 + DEBUG_NEXT_LOGGED_MESSAGE_LENGTH = 33347 + DEBUG_CALLBACK_FUNCTION = 33348 + DEBUG_CALLBACK_USER_PARAM = 33349 + DEBUG_SOURCE_API = 33350 + DEBUG_SOURCE_WINDOW_SYSTEM = 33351 + DEBUG_SOURCE_SHADER_COMPILER = 33352 + DEBUG_SOURCE_THIRD_PARTY = 33353 + DEBUG_SOURCE_APPLICATION = 33354 + DEBUG_SOURCE_OTHER = 33355 + DEBUG_TYPE_ERROR = 33356 + DEBUG_TYPE_DEPRECATED_BEHAVIOR = 33357 + DEBUG_TYPE_UNDEFINED_BEHAVIOR = 33358 + DEBUG_TYPE_PORTABILITY = 33359 + DEBUG_TYPE_PERFORMANCE = 33360 + DEBUG_TYPE_OTHER = 33361 + LOSE_CONTEXT_ON_RESET = 33362 + GUILTY_CONTEXT_RESET = 33363 + INNOCENT_CONTEXT_RESET = 33364 + UNKNOWN_CONTEXT_RESET = 33365 + RESET_NOTIFICATION_STRATEGY = 33366 + PROGRAM_BINARY_RETRIEVABLE_HINT = 33367 + PROGRAM_SEPARABLE = 33368 + ACTIVE_PROGRAM = 33369 + PROGRAM_PIPELINE_BINDING = 33370 + MAX_VIEWPORTS = 33371 + VIEWPORT_SUBPIXEL_BITS = 33372 + VIEWPORT_BOUNDS_RANGE = 33373 + LAYER_PROVOKING_VERTEX = 33374 + VIEWPORT_INDEX_PROVOKING_VERTEX = 33375 + UNDEFINED_VERTEX = 33376 + NO_RESET_NOTIFICATION = 33377 + MAX_COMPUTE_SHARED_MEMORY_SIZE = 33378 + MAX_COMPUTE_UNIFORM_COMPONENTS = 33379 + MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS = 33380 + MAX_COMPUTE_ATOMIC_COUNTERS = 33381 + MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS = 33382 + COMPUTE_WORK_GROUP_SIZE = 33383 + DEBUG_TYPE_MARKER = 33384 + DEBUG_TYPE_PUSH_GROUP = 33385 + DEBUG_TYPE_POP_GROUP = 33386 + DEBUG_SEVERITY_NOTIFICATION = 33387 + MAX_DEBUG_GROUP_STACK_DEPTH = 33388 + DEBUG_GROUP_STACK_DEPTH = 33389 + MAX_UNIFORM_LOCATIONS = 33390 + INTERNALFORMAT_SUPPORTED = 33391 + INTERNALFORMAT_PREFERRED = 33392 + INTERNALFORMAT_RED_SIZE = 33393 + INTERNALFORMAT_GREEN_SIZE = 33394 + INTERNALFORMAT_BLUE_SIZE = 33395 + INTERNALFORMAT_ALPHA_SIZE = 33396 + INTERNALFORMAT_DEPTH_SIZE = 33397 + INTERNALFORMAT_STENCIL_SIZE = 33398 + INTERNALFORMAT_SHARED_SIZE = 33399 + INTERNALFORMAT_RED_TYPE = 33400 + INTERNALFORMAT_GREEN_TYPE = 33401 + INTERNALFORMAT_BLUE_TYPE = 33402 + INTERNALFORMAT_ALPHA_TYPE = 33403 + INTERNALFORMAT_DEPTH_TYPE = 33404 + INTERNALFORMAT_STENCIL_TYPE = 33405 + MAX_WIDTH = 33406 + MAX_HEIGHT = 33407 + MAX_DEPTH = 33408 + MAX_LAYERS = 33409 + MAX_COMBINED_DIMENSIONS = 33410 + COLOR_COMPONENTS = 33411 + DEPTH_COMPONENTS = 33412 + STENCIL_COMPONENTS = 33413 + COLOR_RENDERABLE = 33414 + DEPTH_RENDERABLE = 33415 + STENCIL_RENDERABLE = 33416 + FRAMEBUFFER_RENDERABLE = 33417 + FRAMEBUFFER_RENDERABLE_LAYERED = 33418 + FRAMEBUFFER_BLEND = 33419 + READ_PIXELS = 33420 + READ_PIXELS_FORMAT = 33421 + READ_PIXELS_TYPE = 33422 + TEXTURE_IMAGE_FORMAT = 33423 + TEXTURE_IMAGE_TYPE = 33424 + GET_TEXTURE_IMAGE_FORMAT = 33425 + GET_TEXTURE_IMAGE_TYPE = 33426 + MIPMAP = 33427 + MANUAL_GENERATE_MIPMAP = 33428 + AUTO_GENERATE_MIPMAP = 33429 + COLOR_ENCODING = 33430 + SRGB_READ = 33431 + SRGB_WRITE = 33432 + FILTER = 33434 + VERTEX_TEXTURE = 33435 + TESS_CONTROL_TEXTURE = 33436 + TESS_EVALUATION_TEXTURE = 33437 + GEOMETRY_TEXTURE = 33438 + FRAGMENT_TEXTURE = 33439 + COMPUTE_TEXTURE = 33440 + TEXTURE_SHADOW = 33441 + TEXTURE_GATHER = 33442 + TEXTURE_GATHER_SHADOW = 33443 + SHADER_IMAGE_LOAD = 33444 + SHADER_IMAGE_STORE = 33445 + SHADER_IMAGE_ATOMIC = 33446 + IMAGE_TEXEL_SIZE = 33447 + IMAGE_COMPATIBILITY_CLASS = 33448 + IMAGE_PIXEL_FORMAT = 33449 + IMAGE_PIXEL_TYPE = 33450 + SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST = 33452 + SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST = 33453 + SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE = 33454 + SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE = 33455 + TEXTURE_COMPRESSED_BLOCK_WIDTH = 33457 + TEXTURE_COMPRESSED_BLOCK_HEIGHT = 33458 + TEXTURE_COMPRESSED_BLOCK_SIZE = 33459 + CLEAR_BUFFER = 33460 + TEXTURE_VIEW = 33461 + VIEW_COMPATIBILITY_CLASS = 33462 + FULL_SUPPORT = 33463 + CAVEAT_SUPPORT = 33464 + IMAGE_CLASS_4_X_32 = 33465 + IMAGE_CLASS_2_X_32 = 33466 + IMAGE_CLASS_1_X_32 = 33467 + IMAGE_CLASS_4_X_16 = 33468 + IMAGE_CLASS_2_X_16 = 33469 + IMAGE_CLASS_1_X_16 = 33470 + IMAGE_CLASS_4_X_8 = 33471 + IMAGE_CLASS_2_X_8 = 33472 + IMAGE_CLASS_1_X_8 = 33473 + IMAGE_CLASS_11_11_10 = 33474 + IMAGE_CLASS_10_10_10_2 = 33475 + VIEW_CLASS_128_BITS = 33476 + VIEW_CLASS_96_BITS = 33477 + VIEW_CLASS_64_BITS = 33478 + VIEW_CLASS_48_BITS = 33479 + VIEW_CLASS_32_BITS = 33480 + VIEW_CLASS_24_BITS = 33481 + VIEW_CLASS_16_BITS = 33482 + VIEW_CLASS_8_BITS = 33483 + VIEW_CLASS_S3TC_DXT1_RGB = 33484 + VIEW_CLASS_S3TC_DXT1_RGBA = 33485 + VIEW_CLASS_S3TC_DXT3_RGBA = 33486 + VIEW_CLASS_S3TC_DXT5_RGBA = 33487 + VIEW_CLASS_RGTC1_RED = 33488 + VIEW_CLASS_RGTC2_RG = 33489 + VIEW_CLASS_BPTC_UNORM = 33490 + VIEW_CLASS_BPTC_FLOAT = 33491 + VERTEX_ATTRIB_BINDING = 33492 + VERTEX_ATTRIB_RELATIVE_OFFSET = 33493 + VERTEX_BINDING_DIVISOR = 33494 + VERTEX_BINDING_OFFSET = 33495 + VERTEX_BINDING_STRIDE = 33496 + MAX_VERTEX_ATTRIB_RELATIVE_OFFSET = 33497 + MAX_VERTEX_ATTRIB_BINDINGS = 33498 + TEXTURE_VIEW_MIN_LEVEL = 33499 + TEXTURE_VIEW_NUM_LEVELS = 33500 + TEXTURE_VIEW_MIN_LAYER = 33501 + TEXTURE_VIEW_NUM_LAYERS = 33502 + TEXTURE_IMMUTABLE_LEVELS = 33503 + BUFFER = 33504 + SHADER = 33505 + PROGRAM = 33506 + QUERY = 33507 + PROGRAM_PIPELINE = 33508 + MAX_VERTEX_ATTRIB_STRIDE = 33509 + SAMPLER = 33510 + DISPLAY_LIST = 33511 + MAX_LABEL_LENGTH = 33512 + NUM_SHADING_LANGUAGE_VERSIONS = 33513 + QUERY_TARGET = 33514 + TRANSFORM_FEEDBACK_OVERFLOW = 33516 + TRANSFORM_FEEDBACK_STREAM_OVERFLOW = 33517 + VERTICES_SUBMITTED = 33518 + PRIMITIVES_SUBMITTED = 33519 + VERTEX_SHADER_INVOCATIONS = 33520 + TESS_CONTROL_SHADER_PATCHES = 33521 + TESS_EVALUATION_SHADER_INVOCATIONS = 33522 + GEOMETRY_SHADER_PRIMITIVES_EMITTED = 33523 + FRAGMENT_SHADER_INVOCATIONS = 33524 + COMPUTE_SHADER_INVOCATIONS = 33525 + CLIPPING_INPUT_PRIMITIVES = 33526 + CLIPPING_OUTPUT_PRIMITIVES = 33527 + MAX_CULL_DISTANCES = 33529 + MAX_COMBINED_CLIP_AND_CULL_DISTANCES = 33530 + CONTEXT_RELEASE_BEHAVIOR = 33531 + CONTEXT_RELEASE_BEHAVIOR_FLUSH = 33532 + UNSIGNED_BYTE_2_3_3_REV = 33634 + UNSIGNED_SHORT_5_6_5 = 33635 + UNSIGNED_SHORT_5_6_5_REV = 33636 + UNSIGNED_SHORT_4_4_4_4_REV = 33637 + UNSIGNED_SHORT_1_5_5_5_REV = 33638 + UNSIGNED_INT_8_8_8_8_REV = 33639 + UNSIGNED_INT_2_10_10_10_REV = 33640 + MIRRORED_REPEAT = 33648 + COMPRESSED_RGB_S3TC_DXT1_EXT = 33776 + COMPRESSED_RGBA_S3TC_DXT1_EXT = 33777 + COMPRESSED_RGBA_S3TC_DXT3_EXT = 33778 + COMPRESSED_RGBA_S3TC_DXT5_EXT = 33779 + ALIASED_LINE_WIDTH_RANGE = 33902 + TEXTURE0 = 33984 + TEXTURE1 = 33985 + TEXTURE2 = 33986 + TEXTURE3 = 33987 + TEXTURE4 = 33988 + TEXTURE5 = 33989 + TEXTURE6 = 33990 + TEXTURE7 = 33991 + TEXTURE8 = 33992 + TEXTURE9 = 33993 + TEXTURE10 = 33994 + TEXTURE11 = 33995 + TEXTURE12 = 33996 + TEXTURE13 = 33997 + TEXTURE14 = 33998 + TEXTURE15 = 33999 + TEXTURE16 = 34000 + TEXTURE17 = 34001 + TEXTURE18 = 34002 + TEXTURE19 = 34003 + TEXTURE20 = 34004 + TEXTURE21 = 34005 + TEXTURE22 = 34006 + TEXTURE23 = 34007 + TEXTURE24 = 34008 + TEXTURE25 = 34009 + TEXTURE26 = 34010 + TEXTURE27 = 34011 + TEXTURE28 = 34012 + TEXTURE29 = 34013 + TEXTURE30 = 34014 + TEXTURE31 = 34015 + ACTIVE_TEXTURE = 34016 + MAX_RENDERBUFFER_SIZE = 34024 + MAX_RENDERBUFFER_SIZE_EXT = 34024 + COMPRESSED_RGB = 34029 + COMPRESSED_RGBA = 34030 + TEXTURE_COMPRESSION_HINT = 34031 + UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER = 34032 + UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER = 34033 + TEXTURE_RECTANGLE = 34037 + TEXTURE_BINDING_RECTANGLE = 34038 + PROXY_TEXTURE_RECTANGLE = 34039 + MAX_RECTANGLE_TEXTURE_SIZE = 34040 + DEPTH_STENCIL = 34041 + UNSIGNED_INT_24_8 = 34042 + MAX_TEXTURE_LOD_BIAS = 34045 + TEXTURE_MAX_ANISOTROPY = 34046 + MAX_TEXTURE_MAX_ANISOTROPY = 34047 + TEXTURE_LOD_BIAS = 34049 + INCR_WRAP = 34055 + DECR_WRAP = 34056 + TEXTURE_CUBE_MAP = 34067 + TEXTURE_BINDING_CUBE_MAP = 34068 + TEXTURE_CUBE_MAP_POSITIVE_X = 34069 + TEXTURE_CUBE_MAP_NEGATIVE_X = 34070 + TEXTURE_CUBE_MAP_POSITIVE_Y = 34071 + TEXTURE_CUBE_MAP_NEGATIVE_Y = 34072 + TEXTURE_CUBE_MAP_POSITIVE_Z = 34073 + TEXTURE_CUBE_MAP_NEGATIVE_Z = 34074 + PROXY_TEXTURE_CUBE_MAP = 34075 + MAX_CUBE_MAP_TEXTURE_SIZE = 34076 + SRC1_ALPHA = 34185 + VERTEX_ARRAY_BINDING = 34229 + VERTEX_ATTRIB_ARRAY_ENABLED = 34338 + VERTEX_ATTRIB_ARRAY_SIZE = 34339 + VERTEX_ATTRIB_ARRAY_STRIDE = 34340 + VERTEX_ATTRIB_ARRAY_TYPE = 34341 + CURRENT_VERTEX_ATTRIB = 34342 + VERTEX_PROGRAM_POINT_SIZE = 34370 + PROGRAM_POINT_SIZE = 34370 + VERTEX_ATTRIB_ARRAY_POINTER = 34373 + DEPTH_CLAMP = 34383 + TEXTURE_COMPRESSED_IMAGE_SIZE = 34464 + TEXTURE_COMPRESSED = 34465 + NUM_COMPRESSED_TEXTURE_FORMATS = 34466 + COMPRESSED_TEXTURE_FORMATS = 34467 + PROGRAM_BINARY_LENGTH = 34625 + MIRROR_CLAMP_TO_EDGE = 34627 + VERTEX_ATTRIB_ARRAY_LONG = 34638 + BUFFER_SIZE = 34660 + BUFFER_USAGE = 34661 + NUM_PROGRAM_BINARY_FORMATS = 34814 + PROGRAM_BINARY_FORMATS = 34815 + STENCIL_BACK_FUNC = 34816 + STENCIL_BACK_FAIL = 34817 + STENCIL_BACK_PASS_DEPTH_FAIL = 34818 + STENCIL_BACK_PASS_DEPTH_PASS = 34819 + RGBA32F = 34836 + RGB32F = 34837 + RGBA16F = 34842 + RGB16F = 34843 + MAX_DRAW_BUFFERS = 34852 + DRAW_BUFFER0 = 34853 + DRAW_BUFFER1 = 34854 + DRAW_BUFFER2 = 34855 + DRAW_BUFFER3 = 34856 + DRAW_BUFFER4 = 34857 + DRAW_BUFFER5 = 34858 + DRAW_BUFFER6 = 34859 + DRAW_BUFFER7 = 34860 + DRAW_BUFFER8 = 34861 + DRAW_BUFFER9 = 34862 + DRAW_BUFFER10 = 34863 + DRAW_BUFFER11 = 34864 + DRAW_BUFFER12 = 34865 + DRAW_BUFFER13 = 34866 + DRAW_BUFFER14 = 34867 + DRAW_BUFFER15 = 34868 + BLEND_EQUATION_ALPHA = 34877 + TEXTURE_DEPTH_SIZE = 34890 + TEXTURE_COMPARE_MODE = 34892 + TEXTURE_COMPARE_FUNC = 34893 + COMPARE_REF_TO_TEXTURE = 34894 + TEXTURE_CUBE_MAP_SEAMLESS = 34895 + QUERY_COUNTER_BITS = 34916 + CURRENT_QUERY = 34917 + QUERY_RESULT = 34918 + QUERY_RESULT_AVAILABLE = 34919 + MAX_VERTEX_ATTRIBS = 34921 + VERTEX_ATTRIB_ARRAY_NORMALIZED = 34922 + MAX_TESS_CONTROL_INPUT_COMPONENTS = 34924 + MAX_TESS_EVALUATION_INPUT_COMPONENTS = 34925 + MAX_TEXTURE_IMAGE_UNITS = 34930 + GEOMETRY_SHADER_INVOCATIONS = 34943 + ARRAY_BUFFER = 34962 + ELEMENT_ARRAY_BUFFER = 34963 + ARRAY_BUFFER_BINDING = 34964 + ELEMENT_ARRAY_BUFFER_BINDING = 34965 + VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 34975 + READ_ONLY = 35000 + WRITE_ONLY = 35001 + READ_WRITE = 35002 + BUFFER_ACCESS = 35003 + BUFFER_MAPPED = 35004 + BUFFER_MAP_POINTER = 35005 + TIME_ELAPSED = 35007 + STREAM_DRAW = 35040 + STREAM_READ = 35041 + STREAM_COPY = 35042 + STATIC_DRAW = 35044 + STATIC_READ = 35045 + STATIC_COPY = 35046 + DYNAMIC_DRAW = 35048 + DYNAMIC_READ = 35049 + DYNAMIC_COPY = 35050 + PIXEL_PACK_BUFFER = 35051 + PIXEL_UNPACK_BUFFER = 35052 + PIXEL_PACK_BUFFER_BINDING = 35053 + PIXEL_UNPACK_BUFFER_BINDING = 35055 + DEPTH24_STENCIL8 = 35056 + TEXTURE_STENCIL_SIZE = 35057 + SRC1_COLOR = 35065 + ONE_MINUS_SRC1_COLOR = 35066 + ONE_MINUS_SRC1_ALPHA = 35067 + MAX_DUAL_SOURCE_DRAW_BUFFERS = 35068 + VERTEX_ATTRIB_ARRAY_INTEGER = 35069 + VERTEX_ATTRIB_ARRAY_DIVISOR = 35070 + MAX_ARRAY_TEXTURE_LAYERS = 35071 + MIN_PROGRAM_TEXEL_OFFSET = 35076 + MAX_PROGRAM_TEXEL_OFFSET = 35077 + SAMPLES_PASSED = 35092 + GEOMETRY_VERTICES_OUT = 35094 + GEOMETRY_INPUT_TYPE = 35095 + GEOMETRY_OUTPUT_TYPE = 35096 + SAMPLER_BINDING = 35097 + CLAMP_READ_COLOR = 35100 + FIXED_ONLY = 35101 + UNIFORM_BUFFER = 35345 + UNIFORM_BUFFER_BINDING = 35368 + UNIFORM_BUFFER_START = 35369 + UNIFORM_BUFFER_SIZE = 35370 + MAX_VERTEX_UNIFORM_BLOCKS = 35371 + MAX_GEOMETRY_UNIFORM_BLOCKS = 35372 + MAX_FRAGMENT_UNIFORM_BLOCKS = 35373 + MAX_COMBINED_UNIFORM_BLOCKS = 35374 + MAX_UNIFORM_BUFFER_BINDINGS = 35375 + MAX_UNIFORM_BLOCK_SIZE = 35376 + MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = 35377 + MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS = 35378 + MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = 35379 + UNIFORM_BUFFER_OFFSET_ALIGNMENT = 35380 + ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH = 35381 + ACTIVE_UNIFORM_BLOCKS = 35382 + UNIFORM_TYPE = 35383 + UNIFORM_SIZE = 35384 + UNIFORM_NAME_LENGTH = 35385 + UNIFORM_BLOCK_INDEX = 35386 + UNIFORM_OFFSET = 35387 + UNIFORM_ARRAY_STRIDE = 35388 + UNIFORM_MATRIX_STRIDE = 35389 + UNIFORM_IS_ROW_MAJOR = 35390 + UNIFORM_BLOCK_BINDING = 35391 + UNIFORM_BLOCK_DATA_SIZE = 35392 + UNIFORM_BLOCK_NAME_LENGTH = 35393 + UNIFORM_BLOCK_ACTIVE_UNIFORMS = 35394 + UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 35395 + UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 35396 + UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER = 35397 + UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 35398 + FRAGMENT_SHADER = 35632 + VERTEX_SHADER = 35633 + MAX_FRAGMENT_UNIFORM_COMPONENTS = 35657 + MAX_VERTEX_UNIFORM_COMPONENTS = 35658 + MAX_VARYING_FLOATS = 35659 + MAX_VARYING_COMPONENTS = 35659 + MAX_VERTEX_TEXTURE_IMAGE_UNITS = 35660 + MAX_COMBINED_TEXTURE_IMAGE_UNITS = 35661 + SHADER_TYPE = 35663 + FLOAT_VEC2 = 35664 + FLOAT_VEC3 = 35665 + FLOAT_VEC4 = 35666 + INT_VEC2 = 35667 + INT_VEC3 = 35668 + INT_VEC4 = 35669 + BOOL = 35670 + BOOL_VEC2 = 35671 + BOOL_VEC3 = 35672 + BOOL_VEC4 = 35673 + FLOAT_MAT2 = 35674 + FLOAT_MAT3 = 35675 + FLOAT_MAT4 = 35676 + SAMPLER_1D = 35677 + SAMPLER_2D = 35678 + SAMPLER_3D = 35679 + SAMPLER_CUBE = 35680 + SAMPLER_1D_SHADOW = 35681 + SAMPLER_2D_SHADOW = 35682 + SAMPLER_2D_RECT = 35683 + SAMPLER_2D_RECT_SHADOW = 35684 + FLOAT_MAT2x3 = 35685 + FLOAT_MAT2x4 = 35686 + FLOAT_MAT3x2 = 35687 + FLOAT_MAT3x4 = 35688 + FLOAT_MAT4x2 = 35689 + FLOAT_MAT4x3 = 35690 + DELETE_STATUS = 35712 + COMPILE_STATUS = 35713 + LINK_STATUS = 35714 + VALIDATE_STATUS = 35715 + INFO_LOG_LENGTH = 35716 + ATTACHED_SHADERS = 35717 + ACTIVE_UNIFORMS = 35718 + ACTIVE_UNIFORM_MAX_LENGTH = 35719 + SHADER_SOURCE_LENGTH = 35720 + ACTIVE_ATTRIBUTES = 35721 + ACTIVE_ATTRIBUTE_MAX_LENGTH = 35722 + FRAGMENT_SHADER_DERIVATIVE_HINT = 35723 + SHADING_LANGUAGE_VERSION = 35724 + CURRENT_PROGRAM = 35725 + IMPLEMENTATION_COLOR_READ_TYPE = 35738 + IMPLEMENTATION_COLOR_READ_FORMAT = 35739 + TEXTURE_RED_TYPE = 35856 + TEXTURE_GREEN_TYPE = 35857 + TEXTURE_BLUE_TYPE = 35858 + TEXTURE_ALPHA_TYPE = 35859 + TEXTURE_DEPTH_TYPE = 35862 + UNSIGNED_NORMALIZED = 35863 + TEXTURE_1D_ARRAY = 35864 + PROXY_TEXTURE_1D_ARRAY = 35865 + TEXTURE_2D_ARRAY = 35866 + PROXY_TEXTURE_2D_ARRAY = 35867 + TEXTURE_BINDING_1D_ARRAY = 35868 + TEXTURE_BINDING_2D_ARRAY = 35869 + MAX_GEOMETRY_TEXTURE_IMAGE_UNITS = 35881 + TEXTURE_BUFFER = 35882 + TEXTURE_BUFFER_BINDING = 35882 + MAX_TEXTURE_BUFFER_SIZE = 35883 + TEXTURE_BINDING_BUFFER = 35884 + TEXTURE_BUFFER_DATA_STORE_BINDING = 35885 + ANY_SAMPLES_PASSED = 35887 + SAMPLE_SHADING = 35894 + MIN_SAMPLE_SHADING_VALUE = 35895 + R11F_G11F_B10F = 35898 + UNSIGNED_INT_10F_11F_11F_REV = 35899 + RGB9_E5 = 35901 + UNSIGNED_INT_5_9_9_9_REV = 35902 + TEXTURE_SHARED_SIZE = 35903 + SRGB = 35904 + SRGB8 = 35905 + SRGB_ALPHA = 35906 + SRGB8_ALPHA8 = 35907 + COMPRESSED_SRGB = 35912 + COMPRESSED_SRGB_ALPHA = 35913 + TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH = 35958 + TRANSFORM_FEEDBACK_BUFFER_MODE = 35967 + MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS = 35968 + TRANSFORM_FEEDBACK_VARYINGS = 35971 + TRANSFORM_FEEDBACK_BUFFER_START = 35972 + TRANSFORM_FEEDBACK_BUFFER_SIZE = 35973 + PRIMITIVES_GENERATED = 35975 + TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = 35976 + RASTERIZER_DISCARD = 35977 + MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS = 35978 + MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 35979 + INTERLEAVED_ATTRIBS = 35980 + SEPARATE_ATTRIBS = 35981 + TRANSFORM_FEEDBACK_BUFFER = 35982 + TRANSFORM_FEEDBACK_BUFFER_BINDING = 35983 + POINT_SPRITE_COORD_ORIGIN = 36000 + LOWER_LEFT = 36001 + UPPER_LEFT = 36002 + STENCIL_BACK_REF = 36003 + STENCIL_BACK_VALUE_MASK = 36004 + STENCIL_BACK_WRITEMASK = 36005 + FRAMEBUFFER_BINDING = 36006 + DRAW_FRAMEBUFFER_BINDING = 36006 + FRAMEBUFFER_BINDING_EXT = 36006 + RENDERBUFFER_BINDING = 36007 + RENDERBUFFER_BINDING_EXT = 36007 + READ_FRAMEBUFFER = 36008 + DRAW_FRAMEBUFFER = 36009 + READ_FRAMEBUFFER_BINDING = 36010 + RENDERBUFFER_SAMPLES = 36011 + DEPTH_COMPONENT32F = 36012 + DEPTH32F_STENCIL8 = 36013 + FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 36048 + FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT = 36048 + FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 36049 + FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT = 36049 + FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 36050 + FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT = 36050 + FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 36051 + FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT = 36051 + FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER = 36052 + FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT = 36052 + FRAMEBUFFER_COMPLETE = 36053 + FRAMEBUFFER_COMPLETE_EXT = 36053 + FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 36054 + FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT = 36054 + FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 36055 + FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT = 36055 + FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT = 36057 + FRAMEBUFFER_INCOMPLETE_FORMATS_EXT = 36058 + FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER = 36059 + FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT = 36059 + FRAMEBUFFER_INCOMPLETE_READ_BUFFER = 36060 + FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT = 36060 + FRAMEBUFFER_UNSUPPORTED = 36061 + FRAMEBUFFER_UNSUPPORTED_EXT = 36061 + MAX_COLOR_ATTACHMENTS = 36063 + MAX_COLOR_ATTACHMENTS_EXT = 36063 + COLOR_ATTACHMENT0 = 36064 + COLOR_ATTACHMENT0_EXT = 36064 + COLOR_ATTACHMENT1 = 36065 + COLOR_ATTACHMENT1_EXT = 36065 + COLOR_ATTACHMENT2 = 36066 + COLOR_ATTACHMENT2_EXT = 36066 + COLOR_ATTACHMENT3 = 36067 + COLOR_ATTACHMENT3_EXT = 36067 + COLOR_ATTACHMENT4 = 36068 + COLOR_ATTACHMENT4_EXT = 36068 + COLOR_ATTACHMENT5 = 36069 + COLOR_ATTACHMENT5_EXT = 36069 + COLOR_ATTACHMENT6 = 36070 + COLOR_ATTACHMENT6_EXT = 36070 + COLOR_ATTACHMENT7 = 36071 + COLOR_ATTACHMENT7_EXT = 36071 + COLOR_ATTACHMENT8 = 36072 + COLOR_ATTACHMENT8_EXT = 36072 + COLOR_ATTACHMENT9 = 36073 + COLOR_ATTACHMENT9_EXT = 36073 + COLOR_ATTACHMENT10 = 36074 + COLOR_ATTACHMENT10_EXT = 36074 + COLOR_ATTACHMENT11 = 36075 + COLOR_ATTACHMENT11_EXT = 36075 + COLOR_ATTACHMENT12 = 36076 + COLOR_ATTACHMENT12_EXT = 36076 + COLOR_ATTACHMENT13 = 36077 + COLOR_ATTACHMENT13_EXT = 36077 + COLOR_ATTACHMENT14 = 36078 + COLOR_ATTACHMENT14_EXT = 36078 + COLOR_ATTACHMENT15 = 36079 + COLOR_ATTACHMENT15_EXT = 36079 + COLOR_ATTACHMENT16 = 36080 + COLOR_ATTACHMENT17 = 36081 + COLOR_ATTACHMENT18 = 36082 + COLOR_ATTACHMENT19 = 36083 + COLOR_ATTACHMENT20 = 36084 + COLOR_ATTACHMENT21 = 36085 + COLOR_ATTACHMENT22 = 36086 + COLOR_ATTACHMENT23 = 36087 + COLOR_ATTACHMENT24 = 36088 + COLOR_ATTACHMENT25 = 36089 + COLOR_ATTACHMENT26 = 36090 + COLOR_ATTACHMENT27 = 36091 + COLOR_ATTACHMENT28 = 36092 + COLOR_ATTACHMENT29 = 36093 + COLOR_ATTACHMENT30 = 36094 + COLOR_ATTACHMENT31 = 36095 + DEPTH_ATTACHMENT = 36096 + DEPTH_ATTACHMENT_EXT = 36096 + STENCIL_ATTACHMENT = 36128 + STENCIL_ATTACHMENT_EXT = 36128 + FRAMEBUFFER = 36160 + FRAMEBUFFER_EXT = 36160 + RENDERBUFFER = 36161 + RENDERBUFFER_EXT = 36161 + RENDERBUFFER_WIDTH = 36162 + RENDERBUFFER_WIDTH_EXT = 36162 + RENDERBUFFER_HEIGHT = 36163 + RENDERBUFFER_HEIGHT_EXT = 36163 + RENDERBUFFER_INTERNAL_FORMAT = 36164 + RENDERBUFFER_INTERNAL_FORMAT_EXT = 36164 + STENCIL_INDEX1 = 36166 + STENCIL_INDEX1_EXT = 36166 + STENCIL_INDEX4 = 36167 + STENCIL_INDEX4_EXT = 36167 + STENCIL_INDEX8 = 36168 + STENCIL_INDEX8_EXT = 36168 + STENCIL_INDEX16 = 36169 + STENCIL_INDEX16_EXT = 36169 + RENDERBUFFER_RED_SIZE = 36176 + RENDERBUFFER_RED_SIZE_EXT = 36176 + RENDERBUFFER_GREEN_SIZE = 36177 + RENDERBUFFER_GREEN_SIZE_EXT = 36177 + RENDERBUFFER_BLUE_SIZE = 36178 + RENDERBUFFER_BLUE_SIZE_EXT = 36178 + RENDERBUFFER_ALPHA_SIZE = 36179 + RENDERBUFFER_ALPHA_SIZE_EXT = 36179 + RENDERBUFFER_DEPTH_SIZE = 36180 + RENDERBUFFER_DEPTH_SIZE_EXT = 36180 + RENDERBUFFER_STENCIL_SIZE = 36181 + RENDERBUFFER_STENCIL_SIZE_EXT = 36181 + FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = 36182 + MAX_SAMPLES = 36183 + RGB565 = 36194 + PRIMITIVE_RESTART_FIXED_INDEX = 36201 + ANY_SAMPLES_PASSED_CONSERVATIVE = 36202 + MAX_ELEMENT_INDEX = 36203 + RGBA32UI = 36208 + RGB32UI = 36209 + RGBA16UI = 36214 + RGB16UI = 36215 + RGBA8UI = 36220 + RGB8UI = 36221 + RGBA32I = 36226 + RGB32I = 36227 + RGBA16I = 36232 + RGB16I = 36233 + RGBA8I = 36238 + RGB8I = 36239 + RED_INTEGER = 36244 + GREEN_INTEGER = 36245 + BLUE_INTEGER = 36246 + RGB_INTEGER = 36248 + RGBA_INTEGER = 36249 + BGR_INTEGER = 36250 + BGRA_INTEGER = 36251 + INT_2_10_10_10_REV = 36255 + FRAMEBUFFER_ATTACHMENT_LAYERED = 36263 + FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS = 36264 + FLOAT_32_UNSIGNED_INT_24_8_REV = 36269 + FRAMEBUFFER_SRGB = 36281 + COMPRESSED_RED_RGTC1 = 36283 + COMPRESSED_SIGNED_RED_RGTC1 = 36284 + COMPRESSED_RG_RGTC2 = 36285 + COMPRESSED_SIGNED_RG_RGTC2 = 36286 + SAMPLER_1D_ARRAY = 36288 + SAMPLER_2D_ARRAY = 36289 + SAMPLER_BUFFER = 36290 + SAMPLER_1D_ARRAY_SHADOW = 36291 + SAMPLER_2D_ARRAY_SHADOW = 36292 + SAMPLER_CUBE_SHADOW = 36293 + UNSIGNED_INT_VEC2 = 36294 + UNSIGNED_INT_VEC3 = 36295 + UNSIGNED_INT_VEC4 = 36296 + INT_SAMPLER_1D = 36297 + INT_SAMPLER_2D = 36298 + INT_SAMPLER_3D = 36299 + INT_SAMPLER_CUBE = 36300 + INT_SAMPLER_2D_RECT = 36301 + INT_SAMPLER_1D_ARRAY = 36302 + INT_SAMPLER_2D_ARRAY = 36303 + INT_SAMPLER_BUFFER = 36304 + UNSIGNED_INT_SAMPLER_1D = 36305 + UNSIGNED_INT_SAMPLER_2D = 36306 + UNSIGNED_INT_SAMPLER_3D = 36307 + UNSIGNED_INT_SAMPLER_CUBE = 36308 + UNSIGNED_INT_SAMPLER_2D_RECT = 36309 + UNSIGNED_INT_SAMPLER_1D_ARRAY = 36310 + UNSIGNED_INT_SAMPLER_2D_ARRAY = 36311 + UNSIGNED_INT_SAMPLER_BUFFER = 36312 + GEOMETRY_SHADER = 36313 + MAX_GEOMETRY_UNIFORM_COMPONENTS = 36319 + MAX_GEOMETRY_OUTPUT_VERTICES = 36320 + MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = 36321 + ACTIVE_SUBROUTINES = 36325 + ACTIVE_SUBROUTINE_UNIFORMS = 36326 + MAX_SUBROUTINES = 36327 + MAX_SUBROUTINE_UNIFORM_LOCATIONS = 36328 + LOW_FLOAT = 36336 + MEDIUM_FLOAT = 36337 + HIGH_FLOAT = 36338 + LOW_INT = 36339 + MEDIUM_INT = 36340 + HIGH_INT = 36341 + SHADER_BINARY_FORMATS = 36344 + NUM_SHADER_BINARY_FORMATS = 36345 + SHADER_COMPILER = 36346 + MAX_VERTEX_UNIFORM_VECTORS = 36347 + MAX_VARYING_VECTORS = 36348 + MAX_FRAGMENT_UNIFORM_VECTORS = 36349 + QUERY_WAIT = 36371 + QUERY_NO_WAIT = 36372 + QUERY_BY_REGION_WAIT = 36373 + QUERY_BY_REGION_NO_WAIT = 36374 + QUERY_WAIT_INVERTED = 36375 + QUERY_NO_WAIT_INVERTED = 36376 + QUERY_BY_REGION_WAIT_INVERTED = 36377 + QUERY_BY_REGION_NO_WAIT_INVERTED = 36378 + POLYGON_OFFSET_CLAMP = 36379 + MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS = 36382 + MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS = 36383 + TRANSFORM_FEEDBACK = 36386 + TRANSFORM_FEEDBACK_BUFFER_PAUSED = 36387 + TRANSFORM_FEEDBACK_PAUSED = 36387 + TRANSFORM_FEEDBACK_BUFFER_ACTIVE = 36388 + TRANSFORM_FEEDBACK_ACTIVE = 36388 + TRANSFORM_FEEDBACK_BINDING = 36389 + TIMESTAMP = 36392 + TEXTURE_SWIZZLE_R = 36418 + TEXTURE_SWIZZLE_G = 36419 + TEXTURE_SWIZZLE_B = 36420 + TEXTURE_SWIZZLE_A = 36421 + TEXTURE_SWIZZLE_RGBA = 36422 + ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS = 36423 + ACTIVE_SUBROUTINE_MAX_LENGTH = 36424 + ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH = 36425 + NUM_COMPATIBLE_SUBROUTINES = 36426 + COMPATIBLE_SUBROUTINES = 36427 + QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION = 36428 + FIRST_VERTEX_CONVENTION = 36429 + LAST_VERTEX_CONVENTION = 36430 + PROVOKING_VERTEX = 36431 + SAMPLE_POSITION = 36432 + SAMPLE_MASK = 36433 + SAMPLE_MASK_VALUE = 36434 + MAX_SAMPLE_MASK_WORDS = 36441 + MAX_GEOMETRY_SHADER_INVOCATIONS = 36442 + MIN_FRAGMENT_INTERPOLATION_OFFSET = 36443 + MAX_FRAGMENT_INTERPOLATION_OFFSET = 36444 + FRAGMENT_INTERPOLATION_OFFSET_BITS = 36445 + MIN_PROGRAM_TEXTURE_GATHER_OFFSET = 36446 + MAX_PROGRAM_TEXTURE_GATHER_OFFSET = 36447 + MAX_MESH_UNIFORM_BLOCKS_NV = 36448 + MAX_MESH_TEXTURE_IMAGE_UNITS_NV = 36449 + MAX_MESH_IMAGE_UNIFORMS_NV = 36450 + MAX_MESH_UNIFORM_COMPONENTS_NV = 36451 + MAX_MESH_ATOMIC_COUNTER_BUFFERS_NV = 36452 + MAX_MESH_ATOMIC_COUNTERS_NV = 36453 + MAX_MESH_SHADER_STORAGE_BLOCKS_NV = 36454 + MAX_COMBINED_MESH_UNIFORM_COMPONENTS_NV = 36455 + MAX_TASK_UNIFORM_BLOCKS_NV = 36456 + MAX_TASK_TEXTURE_IMAGE_UNITS_NV = 36457 + MAX_TASK_IMAGE_UNIFORMS_NV = 36458 + MAX_TASK_UNIFORM_COMPONENTS_NV = 36459 + MAX_TASK_ATOMIC_COUNTER_BUFFERS_NV = 36460 + MAX_TASK_ATOMIC_COUNTERS_NV = 36461 + MAX_TASK_SHADER_STORAGE_BLOCKS_NV = 36462 + MAX_COMBINED_TASK_UNIFORM_COMPONENTS_NV = 36463 + MAX_TRANSFORM_FEEDBACK_BUFFERS = 36464 + MAX_VERTEX_STREAMS = 36465 + PATCH_VERTICES = 36466 + PATCH_DEFAULT_INNER_LEVEL = 36467 + PATCH_DEFAULT_OUTER_LEVEL = 36468 + TESS_CONTROL_OUTPUT_VERTICES = 36469 + TESS_GEN_MODE = 36470 + TESS_GEN_SPACING = 36471 + TESS_GEN_VERTEX_ORDER = 36472 + TESS_GEN_POINT_MODE = 36473 + ISOLINES = 36474 + FRACTIONAL_ODD = 36475 + FRACTIONAL_EVEN = 36476 + MAX_PATCH_VERTICES = 36477 + MAX_TESS_GEN_LEVEL = 36478 + MAX_TESS_CONTROL_UNIFORM_COMPONENTS = 36479 + MAX_TESS_EVALUATION_UNIFORM_COMPONENTS = 36480 + MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS = 36481 + MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS = 36482 + MAX_TESS_CONTROL_OUTPUT_COMPONENTS = 36483 + MAX_TESS_PATCH_COMPONENTS = 36484 + MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS = 36485 + MAX_TESS_EVALUATION_OUTPUT_COMPONENTS = 36486 + TESS_EVALUATION_SHADER = 36487 + TESS_CONTROL_SHADER = 36488 + MAX_TESS_CONTROL_UNIFORM_BLOCKS = 36489 + MAX_TESS_EVALUATION_UNIFORM_BLOCKS = 36490 + COMPRESSED_RGBA_BPTC_UNORM = 36492 + COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 36493 + COMPRESSED_RGB_BPTC_SIGNED_FLOAT = 36494 + COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 36495 + COPY_READ_BUFFER = 36662 + COPY_READ_BUFFER_BINDING = 36662 + COPY_WRITE_BUFFER = 36663 + COPY_WRITE_BUFFER_BINDING = 36663 + MAX_IMAGE_UNITS = 36664 + MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS = 36665 + MAX_COMBINED_SHADER_OUTPUT_RESOURCES = 36665 + IMAGE_BINDING_NAME = 36666 + IMAGE_BINDING_LEVEL = 36667 + IMAGE_BINDING_LAYERED = 36668 + IMAGE_BINDING_LAYER = 36669 + IMAGE_BINDING_ACCESS = 36670 + DRAW_INDIRECT_BUFFER = 36671 + DRAW_INDIRECT_BUFFER_BINDING = 36675 + DOUBLE_MAT2 = 36678 + DOUBLE_MAT3 = 36679 + DOUBLE_MAT4 = 36680 + DOUBLE_MAT2x3 = 36681 + DOUBLE_MAT2x4 = 36682 + DOUBLE_MAT3x2 = 36683 + DOUBLE_MAT3x4 = 36684 + DOUBLE_MAT4x2 = 36685 + DOUBLE_MAT4x3 = 36686 + VERTEX_BINDING_BUFFER = 36687 + R8_SNORM = 36756 + RG8_SNORM = 36757 + RGB8_SNORM = 36758 + RGBA8_SNORM = 36759 + R16_SNORM = 36760 + RG16_SNORM = 36761 + RGB16_SNORM = 36762 + RGBA16_SNORM = 36763 + SIGNED_NORMALIZED = 36764 + PRIMITIVE_RESTART = 36765 + PRIMITIVE_RESTART_INDEX = 36766 + INT64_VEC2_ARB = 36841 + INT64_VEC3_ARB = 36842 + INT64_VEC4_ARB = 36843 + UNSIGNED_INT64_VEC2_ARB = 36853 + UNSIGNED_INT64_VEC3_ARB = 36854 + UNSIGNED_INT64_VEC4_ARB = 36855 + DOUBLE_VEC2 = 36860 + DOUBLE_VEC3 = 36861 + DOUBLE_VEC4 = 36862 + TEXTURE_CUBE_MAP_ARRAY = 36873 + TEXTURE_BINDING_CUBE_MAP_ARRAY = 36874 + PROXY_TEXTURE_CUBE_MAP_ARRAY = 36875 + SAMPLER_CUBE_MAP_ARRAY = 36876 + SAMPLER_CUBE_MAP_ARRAY_SHADOW = 36877 + INT_SAMPLER_CUBE_MAP_ARRAY = 36878 + UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY = 36879 + IMAGE_1D = 36940 + IMAGE_2D = 36941 + IMAGE_3D = 36942 + IMAGE_2D_RECT = 36943 + IMAGE_CUBE = 36944 + IMAGE_BUFFER = 36945 + IMAGE_1D_ARRAY = 36946 + IMAGE_2D_ARRAY = 36947 + IMAGE_CUBE_MAP_ARRAY = 36948 + IMAGE_2D_MULTISAMPLE = 36949 + IMAGE_2D_MULTISAMPLE_ARRAY = 36950 + INT_IMAGE_1D = 36951 + INT_IMAGE_2D = 36952 + INT_IMAGE_3D = 36953 + INT_IMAGE_2D_RECT = 36954 + INT_IMAGE_CUBE = 36955 + INT_IMAGE_BUFFER = 36956 + INT_IMAGE_1D_ARRAY = 36957 + INT_IMAGE_2D_ARRAY = 36958 + INT_IMAGE_CUBE_MAP_ARRAY = 36959 + INT_IMAGE_2D_MULTISAMPLE = 36960 + INT_IMAGE_2D_MULTISAMPLE_ARRAY = 36961 + UNSIGNED_INT_IMAGE_1D = 36962 + UNSIGNED_INT_IMAGE_2D = 36963 + UNSIGNED_INT_IMAGE_3D = 36964 + UNSIGNED_INT_IMAGE_2D_RECT = 36965 + UNSIGNED_INT_IMAGE_CUBE = 36966 + UNSIGNED_INT_IMAGE_BUFFER = 36967 + UNSIGNED_INT_IMAGE_1D_ARRAY = 36968 + UNSIGNED_INT_IMAGE_2D_ARRAY = 36969 + UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY = 36970 + UNSIGNED_INT_IMAGE_2D_MULTISAMPLE = 36971 + UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY = 36972 + MAX_IMAGE_SAMPLES = 36973 + IMAGE_BINDING_FORMAT = 36974 + RGB10_A2UI = 36975 + MIN_MAP_BUFFER_ALIGNMENT = 37052 + IMAGE_FORMAT_COMPATIBILITY_TYPE = 37063 + IMAGE_FORMAT_COMPATIBILITY_BY_SIZE = 37064 + IMAGE_FORMAT_COMPATIBILITY_BY_CLASS = 37065 + MAX_VERTEX_IMAGE_UNIFORMS = 37066 + MAX_TESS_CONTROL_IMAGE_UNIFORMS = 37067 + MAX_TESS_EVALUATION_IMAGE_UNIFORMS = 37068 + MAX_GEOMETRY_IMAGE_UNIFORMS = 37069 + MAX_FRAGMENT_IMAGE_UNIFORMS = 37070 + MAX_COMBINED_IMAGE_UNIFORMS = 37071 + SHADER_STORAGE_BUFFER = 37074 + SHADER_STORAGE_BUFFER_BINDING = 37075 + SHADER_STORAGE_BUFFER_START = 37076 + SHADER_STORAGE_BUFFER_SIZE = 37077 + MAX_VERTEX_SHADER_STORAGE_BLOCKS = 37078 + MAX_GEOMETRY_SHADER_STORAGE_BLOCKS = 37079 + MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS = 37080 + MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS = 37081 + MAX_FRAGMENT_SHADER_STORAGE_BLOCKS = 37082 + MAX_COMPUTE_SHADER_STORAGE_BLOCKS = 37083 + MAX_COMBINED_SHADER_STORAGE_BLOCKS = 37084 + MAX_SHADER_STORAGE_BUFFER_BINDINGS = 37085 + MAX_SHADER_STORAGE_BLOCK_SIZE = 37086 + SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT = 37087 + DEPTH_STENCIL_TEXTURE_MODE = 37098 + MAX_COMPUTE_WORK_GROUP_INVOCATIONS = 37099 + UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER = 37100 + ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER = 37101 + DISPATCH_INDIRECT_BUFFER = 37102 + DISPATCH_INDIRECT_BUFFER_BINDING = 37103 + TEXTURE_2D_MULTISAMPLE = 37120 + PROXY_TEXTURE_2D_MULTISAMPLE = 37121 + TEXTURE_2D_MULTISAMPLE_ARRAY = 37122 + PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY = 37123 + TEXTURE_BINDING_2D_MULTISAMPLE = 37124 + TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY = 37125 + TEXTURE_SAMPLES = 37126 + TEXTURE_FIXED_SAMPLE_LOCATIONS = 37127 + SAMPLER_2D_MULTISAMPLE = 37128 + INT_SAMPLER_2D_MULTISAMPLE = 37129 + UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE = 37130 + SAMPLER_2D_MULTISAMPLE_ARRAY = 37131 + INT_SAMPLER_2D_MULTISAMPLE_ARRAY = 37132 + UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY = 37133 + MAX_COLOR_TEXTURE_SAMPLES = 37134 + MAX_DEPTH_TEXTURE_SAMPLES = 37135 + MAX_INTEGER_SAMPLES = 37136 + MAX_SERVER_WAIT_TIMEOUT = 37137 + OBJECT_TYPE = 37138 + SYNC_CONDITION = 37139 + SYNC_STATUS = 37140 + SYNC_FLAGS = 37141 + SYNC_FENCE = 37142 + SYNC_GPU_COMMANDS_COMPLETE = 37143 + UNSIGNALED = 37144 + SIGNALED = 37145 + ALREADY_SIGNALED = 37146 + TIMEOUT_EXPIRED = 37147 + CONDITION_SATISFIED = 37148 + WAIT_FAILED = 37149 + BUFFER_ACCESS_FLAGS = 37151 + BUFFER_MAP_LENGTH = 37152 + BUFFER_MAP_OFFSET = 37153 + MAX_VERTEX_OUTPUT_COMPONENTS = 37154 + MAX_GEOMETRY_INPUT_COMPONENTS = 37155 + MAX_GEOMETRY_OUTPUT_COMPONENTS = 37156 + MAX_FRAGMENT_INPUT_COMPONENTS = 37157 + CONTEXT_PROFILE_MASK = 37158 + UNPACK_COMPRESSED_BLOCK_WIDTH = 37159 + UNPACK_COMPRESSED_BLOCK_HEIGHT = 37160 + UNPACK_COMPRESSED_BLOCK_DEPTH = 37161 + UNPACK_COMPRESSED_BLOCK_SIZE = 37162 + PACK_COMPRESSED_BLOCK_WIDTH = 37163 + PACK_COMPRESSED_BLOCK_HEIGHT = 37164 + PACK_COMPRESSED_BLOCK_DEPTH = 37165 + PACK_COMPRESSED_BLOCK_SIZE = 37166 + TEXTURE_IMMUTABLE_FORMAT = 37167 + MAX_DEBUG_MESSAGE_LENGTH = 37187 + MAX_DEBUG_LOGGED_MESSAGES = 37188 + DEBUG_LOGGED_MESSAGES = 37189 + DEBUG_SEVERITY_HIGH = 37190 + DEBUG_SEVERITY_MEDIUM = 37191 + DEBUG_SEVERITY_LOW = 37192 + QUERY_BUFFER = 37266 + QUERY_BUFFER_BINDING = 37267 + QUERY_RESULT_NO_WAIT = 37268 + TEXTURE_BUFFER_OFFSET = 37277 + TEXTURE_BUFFER_SIZE = 37278 + TEXTURE_BUFFER_OFFSET_ALIGNMENT = 37279 + COMPUTE_SHADER = 37305 + MAX_COMPUTE_UNIFORM_BLOCKS = 37307 + MAX_COMPUTE_TEXTURE_IMAGE_UNITS = 37308 + MAX_COMPUTE_IMAGE_UNIFORMS = 37309 + MAX_COMPUTE_WORK_GROUP_COUNT = 37310 + MAX_COMPUTE_WORK_GROUP_SIZE = 37311 + COMPRESSED_R11_EAC = 37488 + COMPRESSED_SIGNED_R11_EAC = 37489 + COMPRESSED_RG11_EAC = 37490 + COMPRESSED_SIGNED_RG11_EAC = 37491 + COMPRESSED_RGB8_ETC2 = 37492 + COMPRESSED_SRGB8_ETC2 = 37493 + COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 37494 + COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 37495 + COMPRESSED_RGBA8_ETC2_EAC = 37496 + COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 37497 + ATOMIC_COUNTER_BUFFER = 37568 + ATOMIC_COUNTER_BUFFER_BINDING = 37569 + ATOMIC_COUNTER_BUFFER_START = 37570 + ATOMIC_COUNTER_BUFFER_SIZE = 37571 + ATOMIC_COUNTER_BUFFER_DATA_SIZE = 37572 + ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS = 37573 + ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES = 37574 + ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER = 37575 + ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER = 37576 + ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER = 37577 + ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER = 37578 + ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER = 37579 + MAX_VERTEX_ATOMIC_COUNTER_BUFFERS = 37580 + MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS = 37581 + MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS = 37582 + MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS = 37583 + MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS = 37584 + MAX_COMBINED_ATOMIC_COUNTER_BUFFERS = 37585 + MAX_VERTEX_ATOMIC_COUNTERS = 37586 + MAX_TESS_CONTROL_ATOMIC_COUNTERS = 37587 + MAX_TESS_EVALUATION_ATOMIC_COUNTERS = 37588 + MAX_GEOMETRY_ATOMIC_COUNTERS = 37589 + MAX_FRAGMENT_ATOMIC_COUNTERS = 37590 + MAX_COMBINED_ATOMIC_COUNTERS = 37591 + MAX_ATOMIC_COUNTER_BUFFER_SIZE = 37592 + ACTIVE_ATOMIC_COUNTER_BUFFERS = 37593 + UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX = 37594 + UNSIGNED_INT_ATOMIC_COUNTER = 37595 + MAX_ATOMIC_COUNTER_BUFFER_BINDINGS = 37596 + MESH_OUTPUT_PER_VERTEX_GRANULARITY_NV = 37599 + DEBUG_OUTPUT = 37600 + UNIFORM = 37601 + UNIFORM_BLOCK = 37602 + PROGRAM_INPUT = 37603 + PROGRAM_OUTPUT = 37604 + BUFFER_VARIABLE = 37605 + SHADER_STORAGE_BLOCK = 37606 + IS_PER_PATCH = 37607 + VERTEX_SUBROUTINE = 37608 + TESS_CONTROL_SUBROUTINE = 37609 + TESS_EVALUATION_SUBROUTINE = 37610 + GEOMETRY_SUBROUTINE = 37611 + FRAGMENT_SUBROUTINE = 37612 + COMPUTE_SUBROUTINE = 37613 + VERTEX_SUBROUTINE_UNIFORM = 37614 + TESS_CONTROL_SUBROUTINE_UNIFORM = 37615 + TESS_EVALUATION_SUBROUTINE_UNIFORM = 37616 + GEOMETRY_SUBROUTINE_UNIFORM = 37617 + FRAGMENT_SUBROUTINE_UNIFORM = 37618 + COMPUTE_SUBROUTINE_UNIFORM = 37619 + TRANSFORM_FEEDBACK_VARYING = 37620 + ACTIVE_RESOURCES = 37621 + MAX_NAME_LENGTH = 37622 + MAX_NUM_ACTIVE_VARIABLES = 37623 + MAX_NUM_COMPATIBLE_SUBROUTINES = 37624 + NAME_LENGTH = 37625 + TYPE = 37626 + ARRAY_SIZE = 37627 + OFFSET = 37628 + BLOCK_INDEX = 37629 + ARRAY_STRIDE = 37630 + MATRIX_STRIDE = 37631 + IS_ROW_MAJOR = 37632 + ATOMIC_COUNTER_BUFFER_INDEX = 37633 + BUFFER_BINDING = 37634 + BUFFER_DATA_SIZE = 37635 + NUM_ACTIVE_VARIABLES = 37636 + ACTIVE_VARIABLES = 37637 + REFERENCED_BY_VERTEX_SHADER = 37638 + REFERENCED_BY_TESS_CONTROL_SHADER = 37639 + REFERENCED_BY_TESS_EVALUATION_SHADER = 37640 + REFERENCED_BY_GEOMETRY_SHADER = 37641 + REFERENCED_BY_FRAGMENT_SHADER = 37642 + REFERENCED_BY_COMPUTE_SHADER = 37643 + TOP_LEVEL_ARRAY_SIZE = 37644 + TOP_LEVEL_ARRAY_STRIDE = 37645 + LOCATION = 37646 + LOCATION_INDEX = 37647 + FRAMEBUFFER_DEFAULT_WIDTH = 37648 + FRAMEBUFFER_DEFAULT_HEIGHT = 37649 + FRAMEBUFFER_DEFAULT_LAYERS = 37650 + FRAMEBUFFER_DEFAULT_SAMPLES = 37651 + FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS = 37652 + MAX_FRAMEBUFFER_WIDTH = 37653 + MAX_FRAMEBUFFER_HEIGHT = 37654 + MAX_FRAMEBUFFER_LAYERS = 37655 + MAX_FRAMEBUFFER_SAMPLES = 37656 + LOCATION_COMPONENT = 37706 + TRANSFORM_FEEDBACK_BUFFER_INDEX = 37707 + TRANSFORM_FEEDBACK_BUFFER_STRIDE = 37708 + CLIP_ORIGIN = 37724 + CLIP_DEPTH_MODE = 37725 + NEGATIVE_ONE_TO_ONE = 37726 + ZERO_TO_ONE = 37727 + CLEAR_TEXTURE = 37733 + NUM_SAMPLE_COUNTS = 37760 + MAX_MESH_TOTAL_MEMORY_SIZE_NV = 38198 + MAX_TASK_TOTAL_MEMORY_SIZE_NV = 38199 + MAX_MESH_OUTPUT_VERTICES_NV = 38200 + MAX_MESH_OUTPUT_PRIMITIVES_NV = 38201 + MAX_TASK_OUTPUT_COUNT_NV = 38202 + MAX_MESH_WORK_GROUP_SIZE_NV = 38203 + MAX_TASK_WORK_GROUP_SIZE_NV = 38204 + MAX_DRAW_MESH_TASKS_COUNT_NV = 38205 + MESH_WORK_GROUP_SIZE_NV = 38206 + TASK_WORK_GROUP_SIZE_NV = 38207 + MESH_OUTPUT_PER_PRIMITIVE_GRANULARITY_NV = 38211 + SHADER_BINARY_FORMAT_SPIR_V = 38225 + SPIR_V_BINARY = 38226 + SPIR_V_EXTENSIONS = 38227 + NUM_SPIR_V_EXTENSIONS = 38228 + MAX_MESH_VIEWS_NV = 38231 + MESH_SHADER_NV = 38233 + TASK_SHADER_NV = 38234 + MESH_VERTICES_OUT_NV = 38265 + MESH_PRIMITIVES_OUT_NV = 38266 + MESH_OUTPUT_TYPE_NV = 38267 + MESH_SUBROUTINE_NV = 38268 + TASK_SUBROUTINE_NV = 38269 + MESH_SUBROUTINE_UNIFORM_NV = 38270 + TASK_SUBROUTINE_UNIFORM_NV = 38271 + UNIFORM_BLOCK_REFERENCED_BY_MESH_SHADER_NV = 38300 + UNIFORM_BLOCK_REFERENCED_BY_TASK_SHADER_NV = 38301 + ATOMIC_COUNTER_BUFFER_REFERENCED_BY_MESH_SHADER_NV = 38302 + ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TASK_SHADER_NV = 38303 + REFERENCED_BY_MESH_SHADER_NV = 38304 + REFERENCED_BY_TASK_SHADER_NV = 38305 + MAX_MESH_WORK_GROUP_INVOCATIONS_NV = 38306 + MAX_TASK_WORK_GROUP_INVOCATIONS_NV = 38307 + MULTISAMPLE_BIT_ARB = 536870912 + INVALID_INDEX = 4294967295 + ALL_SHADER_BITS = 4294967295 + ALL_BARRIER_BITS = 4294967295 + TIMEOUT_IGNORED = 18446744073709551615 + + def clear_color(self, r: float, g: float, b: float, a: float): ... + def clear(self, mask: int): ... diff --git a/core/src/toga/widgets/gl/openglview.py b/core/src/toga/widgets/gl/openglview.py new file mode 100644 index 0000000000..3dfd826b97 --- /dev/null +++ b/core/src/toga/widgets/gl/openglview.py @@ -0,0 +1,55 @@ +from __future__ import annotations + +from typing import ( + TYPE_CHECKING, + Any, + Protocol, +) + +from toga.handlers import wrapped_handler + +from ..base import StyleT, Widget + +if TYPE_CHECKING: + from .openglcontext import OpenGLContext + + +class OnRenderHandler(Protocol): + def __call__( + self, widget: OpenGLView, context: OpenGLContext, **kwargs: Any + ) -> None: + """A handler invoked when the OpenGLView needs to re-draw its content. + + :param widget: The canvas that was resized. + :param context: The OpenGLContext. + :param kwargs: Ensures compatibility with arguments added in future versions. + """ + + +class OpenGLView(Widget): + def __init__( + self, + on_render: OnRenderHandler | None, + id: str | None = None, + style: StyleT | None = None, + **kwargs, + ): + self.on_render = None + + super().__init__(id, style, **kwargs) + + self.on_render = on_render + + def _create(self): + return self.factory.OpenGLView(interface=self) + + def redraw(self): + self._impl.redraw() + + @property + def on_render(self) -> OnRenderHandler: + return self._on_render + + @on_render.setter + def on_render(self, handler: OnRenderHandler | None): + self._on_render = wrapped_handler(self, handler) diff --git a/examples/opengl/CHANGELOG b/examples/opengl/CHANGELOG new file mode 100644 index 0000000000..c6b095235f --- /dev/null +++ b/examples/opengl/CHANGELOG @@ -0,0 +1 @@ +See Toga releases for change notes. diff --git a/examples/opengl/LICENSE b/examples/opengl/LICENSE new file mode 100644 index 0000000000..f09583bfab --- /dev/null +++ b/examples/opengl/LICENSE @@ -0,0 +1 @@ +Released under the same license as Toga. See the root of the Toga repository for details. diff --git a/examples/opengl/README.md b/examples/opengl/README.md new file mode 100644 index 0000000000..6ea25f8d1b --- /dev/null +++ b/examples/opengl/README.md @@ -0,0 +1,19 @@ +# Button + +Test app for the +[Button widget](https://toga.beeware.org/en/stable/reference/api/widgets/button.html). + +The following button features are present in this example: + +- Simple buttons with a callback function when a click event happens +- A disabled button +- Buttons of various styles + +## Quickstart + +To run this example: + +``` +$ python -m pip install toga +$ python -m button +``` diff --git a/examples/opengl/opengl/__init__.py b/examples/opengl/opengl/__init__.py new file mode 100644 index 0000000000..86826e638c --- /dev/null +++ b/examples/opengl/opengl/__init__.py @@ -0,0 +1,9 @@ +# Examples of valid version strings +# __version__ = '1.2.3.dev1' # Development release 1 +# __version__ = '1.2.3a1' # Alpha Release 1 +# __version__ = '1.2.3b1' # Beta Release 1 +# __version__ = '1.2.3rc1' # RC Release 1 +# __version__ = '1.2.3' # Final Release +# __version__ = '1.2.3.post1' # Post Release 1 + +__version__ = "0.0.1" diff --git a/examples/opengl/opengl/__main__.py b/examples/opengl/opengl/__main__.py new file mode 100644 index 0000000000..fd87db935c --- /dev/null +++ b/examples/opengl/opengl/__main__.py @@ -0,0 +1,4 @@ +from opengl.app import main + +if __name__ == "__main__": + main().main_loop() diff --git a/examples/opengl/opengl/app.py b/examples/opengl/opengl/app.py new file mode 100644 index 0000000000..5f657983b8 --- /dev/null +++ b/examples/opengl/opengl/app.py @@ -0,0 +1,31 @@ +import toga + + +class OpenGLApp(toga.App): + def startup(self): + self.main_window = toga.MainWindow( + size=(800, 500), resizable=True, minimizable=False + ) + + opengl_view = toga.OpenGLView(self.callback_render, flex=1) + + # Create the outer box with 2 rows + outer_box = toga.Box(children=[opengl_view]) + + # Add the content on the main window + self.main_window.content = outer_box + + # Show the main window + self.main_window.show() + + def callback_render(self, widget, context, **kwargs): + context.clear_color(1.0, 0.0, 0.0, 1.0) + context.clear(context.COLOR_BUFFER_BIT) + + +def main(): + return OpenGLApp("OpenGL", "org.beeware.toga.examples.opengl") + + +if __name__ == "__main__": + main().main_loop() diff --git a/examples/opengl/opengl/resources/star.png b/examples/opengl/opengl/resources/star.png new file mode 100644 index 0000000000000000000000000000000000000000..a441f670971fcf66d09369f187b534dbf64df6d5 GIT binary patch literal 4654 zcmZ`-2{@GN+kYubq{W(jI5@J;Skeen3}cJN$QCkVhMA0E>=Gd)>l8wktTnbm_E4d* z9b0x0D!W3KNPMI3JN>_No$s5u-sisG_xHPh_w(G(dtL8!KT&3v^*PuC*Z=_FFhJ-c z>DKA+Vm(S9$Cm6q&3F(nNAD=s4}`H|`&-DX`l#NBGyR^oDd=R`BDi zoli3ssYJ1MMF-v8-R-RXk)$Wa5SoOfR7oFx@KnR)<>jXCI^8l&Y8R9`Y+)Ui*tnl) zpE}y-#vC1NA}QezhM9v8v%-CHUf#VSn%v6cL%2@6HIwr;U`83)26e_;sd&?o$|()ll>NSiv#f_D z`$ayLFqTNH7W$HMu%rnIzt9CJm8q`3cs*~wCoe?`@ao}jeFpZj5!SeG-Td+8N(zH} zVs7q~Kd8rE;k8)Vv3tsTvG_q;p2b6fD9JNRzA|%&0BqIeG~(FN*DdM2O^)mf_V={d zq_g~oKW0bYzHFh8mYrb=(O*Hl$a_@bBR5?mS8shLaQV{dNWR>`H!G^kw3od}sT$BJ z9%Kne&W@J#j!rb^1Hoc8Hr%;={A#SVE0d}7pMi4@X9Oal&uC@)o`s?g29M-6tM6Nm zFL$kZ<25!ozW7z#eI*k7o&L%&kjR%&3_Ur%X#j8>Y@mA)cTGMsJWMya^ooO3{=6P~8DaSu&D^k#@k93YNt4Lv(E zQk5+Qo}OdiJX=U0jF!!DxVet^C!R4f2^InInAnbujaBuQmk^D_mF;Pg!$PPkpz*Dh8`QHM122|ql_8Kl>)YIkDvSwLg`uHo$+t8$h4Z~XmAD9- z>R-_rZ`73chQljYJ#BS7gdbju)Q7;mi9aS?ieyg*eW^9G-1G1Mdb};ODouRRMz3yc zQ9EA$o{WHv&+-V0E1O{MYH4I{?Xh{mPZ&m6RCC3TqAc~K`V&UV^QqZ{)gETfv(n?w zv7HeSb%s-ROibP;f@(w;LldW>;?*K1Bx3ey*1ffTI{FBW~iR`kgxJfUK1 zR%i(fG9@*LmRkf!AcuOZZfx^|h-Dfj!H@(JwH*T^Kpp^j<%Wgj0wDj*(!$Z_JRQ@R zY$2+2S~ok+T1e|>JOh0pFZfvzKcl?=&=okjPezxg&2AAw8y=%EmrV*gdiK4oRn3yp z*`G-uuYRQDq{-K_<8q~)s_lF^-wmo%TQW#&(=Mwc2Kn0bwt2MFC@Fj2XJt}jG57AV zeY3Ulnx-1J7gTAI8jgwhANyW>9(*d=gxi>#cXD=nJH;S>hn33BTl$n5VN>t7ie*4_ z3Vz+2DOq8v8am#l;jyZB9fV0IXPzK&Ws1zA z+ydozYRjvE5riY}vj6tWob2qvoEK9$qZjlhcUv1*^yAFqt@8-YC@Hvw?=es+HELw! z)u;W-M$?w&RO7yajH%T5*ZNuZDi4^*jn2abb^VMN11 zM7alPX&qleB;M*36mGq&E>Y`o?1>DL;-b2^L?CNed14aZ9Pm7fK)-W#^mA9FQUqzc z1$uAqlR}PjwBDJWEx30d{r$W6xvNMdcZ0i5#kfpFTNmc@XDQtvQEHTx<*Y!Nql@DO z00KTi>uC%rE67PJEO%-2t>9Cve9ALx@i9MArG8yyIW2qPoG-LJgnKU7KE-(sh333F z)m(z~+xoCn{Jgi2i9#(am30VQ@6*@s_CDUSb97m&`BR+WQvEwsHMj)Q#`KwwfsxmQ zy7#>A!AD=wjG7_#u$Rjs2%HR$V2x+dpK3fz4sgZiqnqPqv?TMapVLkIOJSJd-EF}o zv4r&M7>-y82qhGca5Jx1+1?&Q5sK%A!nyRdcBaBi=?R;(Is+Ss<)^-%FZSzpLe@GA zDf0%LXfvbbb7cvsyH7pfvJChjN)s7B;75K;;L}4>L(3P_l4L*F7Juxb#P6>^X%d2Z zV^&jwX3A`3Q)-k4JaThyT$ivwUEQA6s$y|)m}UR}pL^ALA7+E3!NpkU;(1?OK2%0*Pg9p*TWjrZ!l zpI&912s~y>*dX6Tmo;QY1iynRMvB?st}WG5_#ctu-bZ z-f=PQ8V5(T=&|jt-dJ;oz^zd}K4@okl|yr80a|moTeWhz=9JVoZtQJZbwemj*_um~D$q?j=6Rv+09)=4jKIiE;`mtDAdBFSgK-tL?*RDHQii3I15-zOOA||TN?K1Dyb>8^_ zfqluJ`C*FM7(k)(KK4^F`X_{HbWbuFxX2NyveAvU)Ao+T9+mIitkv|$@h|<+nOcLs zb7T4Df5r*_nCX&7Qlc{B;^G=sgL;NxxNqByjYb@OyX9BcLU3!~_!hT0ATFcUeWe?b zNn>`qR_n9U;DGJ;Abj5wgwY)DB+NgIrmS-fNCZD17Jq!>EE>4g8r9jmm(^jqH!&4o z+K9RWzhbcg>R&HbFIwg4n>psk588fH9=ZNW4i!_D$sXw_=QH!ZWIyb$(}DsleQ$Lo z-i$=pJXP31Q13~c+O1ohAsxsuOWZ$;A4$0}{xu()8r7&_sgNGgxRWaD`=Nm)jsNbO zM2KqtX1Ab*O1 zf?#&D`#u=F#{%z5uizO}c{6^(7MUCVc9{JLwHuEvg?GsxQ&I?Af21v3-w#$wM2J!u z{h!=I=gqy%zoBzUv9>^HNd7MayoORKlgu6(Mh;#c*;#bgP*HK8>nJTG)#yU+_rKRI*-A#L)O$`+#5+`&z;)Avy zY2P9ja4}<|trSolx%oxT5~{i1`U30HZ(k_M;uA}d~R|3HtKWAWLTdqY06RGp+o1@O6!ca1iJ98~3 zIb69DVd@~KEjfGoMTt`m&UV<}#jThXFzw@9>_Sx{FYty zL@gDnOP2ES^B20$zxUHoBlRc$LYV&5M`F$M=#7!*4% zcJM`p7)=DW=G&9}y=&*tQ7G%y7Be9gzOs!ST+25Y+eMl^Z#~L_{P}^7b9U&nt&DMg zzDI^U#@7t&&J?*AhRuH+6rmCbGW_cOlv?k_E@Fy!=@{;s9Hr(R@4|vC9uX$KIS4Z> zEM%*D%ZAph{&M{4DgOA;nCMuJi4n8cM+YCH0#p-5J?}|+nmB$iD=$zaq676{cN#hf=^Pmz-K@OBGgHZoh~ZtoC@s=geOgOKu% zifP=izo_!C6Blx|cq3!Z`PtrPwWo>mV(US5R`Wg|(lg|#T_&dsy_0x@wKBk&m;f?# zpA}$X-~^5w_80U&z#srH{qg|-%^>*OCoo9=4~LP?0R!|Ap!c%?nE~?4=cfC2BJsds z!%SBJ=-u$IAA&v}-v6>@ct5Nw(b0=U1}Q6?R{(91 zpZPpy{H@9V_{e|!LvG+}6RHz4beQiq{HwlJx^y)+Pdv#DfT*5)*Sz^}iuM1d^uq<{ z2MmDdZxwSA&db-4j0OI+U3-&)19U3qA=L|yJ6svjos9MTl}xGBKI8L0P*XA<>*nR? zbvPApb1M^TtgwDr-kUq$(a9d09uj3SX-|2>J#df+OZEdIBU$*(Ou zEaR^d%7Y>DN@}RT-=>k$ei)t2`#1aFB^onSp8gl(9~EMGzj$~W1Q@_C>y}=+9{OM4 C(nNUx literal 0 HcmV?d00001 diff --git a/examples/opengl/pyproject.toml b/examples/opengl/pyproject.toml new file mode 100644 index 0000000000..670092e89b --- /dev/null +++ b/examples/opengl/pyproject.toml @@ -0,0 +1,70 @@ +[build-system] +requires = ["briefcase"] + +[tool.briefcase] +project_name = "Button Demo" +bundle = "org.beeware.toga.examples" +version = "0.0.1" +url = "https://beeware.org" +license.file = "LICENSE" +author = "Tiberius Yak" +author_email = "tiberius@beeware.org" + +formal_name = "An OpenGL Demo" +description = "A testing app" +requires = [ + "../../travertino", + "../../core", +] + +[tool.briefcase.app.opengl] +sources = ["opengl"] + +[tool.briefcase.app.opengl-qt] +sources = ["opengl", "opengl_qt"] + +#[tool.briefcase.app.opengl.macOS] +#requires = [ +# "../../cocoa", +# "std-nslog>=1.0.0", +#] + +#[tool.briefcase.app.opengl.linux] +#requires = [ +# "../../gtk", +#] + +[tool.briefcase.app.opengl-qt.linux] +requires = [ + "../../qt", +] + +#[tool.briefcase.app.opengl.windows] +#requires = [ +# "../../winforms", +#] + +# Mobile deployments +#[tool.briefcase.app.opengl.iOS] +#requires = [ +# "../../iOS", +# "std-nslog>=1.0.0", +#] + +#[tool.briefcase.app.opengl.android] +#requires = [ +# "../../android", +#] + +#base_theme = "Theme.MaterialComponents.Light.DarkActionBar" + +#build_gradle_dependencies = [ +# "com.google.android.material:material:1.12.0", +#] + +# Web deployment +#[tool.briefcase.app.opengl.web] +#requires = [ +# "../../web", +#] +#style_framework = "Shoelace v2.3" diff --git a/qt/src/toga_qt/widgets/openglview.py b/qt/src/toga_qt/widgets/openglview.py new file mode 100644 index 0000000000..bd826de94b --- /dev/null +++ b/qt/src/toga_qt/widgets/openglview.py @@ -0,0 +1,120 @@ +from PySide6.QtGui import QOpenGLContext +from PySide6.QtOpenGL import QOpenGLShader +from PySide6.QtOpenGLWidgets import QOpenGLWidget +from travertino.size import at_least + +from toga.widgets.gl.openglcontext import OpenGLContext + +from .base import Widget + + +class QtOpenGLShader: + def __init__(self, native_shader: QOpenGLShader): + self.native = native_shader + + +class QtOpenGLContext(OpenGLContext): + """The implementation layer of a Qt OpenGL context.""" + + def __init__(self, native_context: QOpenGLContext): + self.native = native_context + self.functions = native_context.functions() + + def clear_color(self, r: float, g: float, b: float, a: float): + self.functions.glClearColor(r, g, b, a) + + def clear(self, mask: int): + self.functions.glClear(mask) + + def create_shader(self, type: int): + return self.functions.glCreateShader(type) + + def shader_source(self, shader: int, source: str): + self.functions.glShaderSource(shader, source) + + def compile_shader(self, shader: int): + self.functions.glCompileShader(shader) + + def delete_shader(self, shader): + self.functions.glDeleteShader(shader) + + def create_program(self) -> int: + return self.functions.glCreateProgram() + + def attach_shader(self, program: int, shader: int): + self.functions.glAttachShader(program, shader) + + def link_program(self, program: int): + self.functions.glLinkProgram(program) + + def delete_program(self, program): + self.functions.glDeleteProgram(program) + + +class GLWidget(QOpenGLWidget): + def __init__(self, impl, *args, **kwargs): + super().__init__(*args, **kwargs) + self.impl = impl + self.interface = impl.interface + + def initializeGL(self): + pass + + def resizeGL(self, w, h): + self._redraw() + + def paintGL(self): + self._redraw() + + def _redraw(self): + context = QtOpenGLContext(QOpenGLContext.currentContext()) + self.interface.on_render(context) + + +class OpenGLView(Widget): + def create(self): + self.native = GLWidget(self) + + def redraw(self): + self.native.update() + + # Rehint + def rehint(self): + size = self.native.sizeHint() + self.interface.intrinsic.width = at_least( + max(size.width(), self.interface._MIN_WIDTH) + ) + self.interface.intrinsic.height = at_least( + max(size.height(), self.interface._MIN_HEIGHT) + ) + + +# class MainWindow(QMainWindow): +# def __init__(self): +# super().__init__() + +# central = QWidget() +# layout = QVBoxLayout(central) + +# self.gl = GLWidget() +# layout.addWidget(self.gl) + +# self.setCentralWidget(central) +# self.resize(800, 600) + + +# if __name__ == "__main__": +# app = QApplication(sys.argv) + +# # Explicit OpenGL format +# fmt = QSurfaceFormat() +# fmt.setRenderableType(QSurfaceFormat.OpenGL) +# fmt.setProfile(QSurfaceFormat.CoreProfile) +# fmt.setVersion(3, 3) +# fmt.setSwapBehavior(QSurfaceFormat.DoubleBuffer) +# QSurfaceFormat.setDefaultFormat(fmt) + +# w = MainWindow() +# w.show() + +# sys.exit(app.exec()) From b830957921ef77ac831dab9fef450ceb18c53a64 Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Sat, 21 Mar 2026 16:41:41 +0000 Subject: [PATCH 2/5] Android implementation. --- android/pyproject.toml | 1 + .../src/toga_android/widgets/openglview.py | 70 +++++++++++++++++++ examples/opengl/opengl/app.py | 2 +- examples/opengl/pyproject.toml | 16 ++--- qt/pyproject.toml | 1 + 5 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 android/src/toga_android/widgets/openglview.py diff --git a/android/pyproject.toml b/android/pyproject.toml index 50589c93ec..50adc98109 100644 --- a/android/pyproject.toml +++ b/android/pyproject.toml @@ -90,6 +90,7 @@ Label = "toga_android.widgets.label:Label" MapView = "toga_android.widgets.mapview:MapView" MultilineTextInput = "toga_android.widgets.multilinetextinput:MultilineTextInput" NumberInput = "toga_android.widgets.numberinput:NumberInput" +OpenGLView = "toga_android.widgets.openglview:OpenGLView" OptionContainer = "toga_android.widgets.optioncontainer:OptionContainer" PasswordInput = "toga_android.widgets.passwordinput:PasswordInput" ProgressBar = "toga_android.widgets.progressbar:ProgressBar" diff --git a/android/src/toga_android/widgets/openglview.py b/android/src/toga_android/widgets/openglview.py new file mode 100644 index 0000000000..266946f79a --- /dev/null +++ b/android/src/toga_android/widgets/openglview.py @@ -0,0 +1,70 @@ +from android.opengl import GLES20 as GL, GLSurfaceView +from java import dynamic_proxy + +from toga.widgets.gl.openglcontext import OpenGLContext + +from .base import Widget + + +class AndroidOpenGLContext(OpenGLContext): + """The implementation layer of a Qt OpenGL context.""" + + def __init__(self): + self.native = GL + + def clear_color(self, r: float, g: float, b: float, a: float): + self.native.glClearColor(r, g, b, a) + + def clear(self, mask: int): + self.native.glClear(mask) + + def create_shader(self, type: int): + return self.native.glCreateShader(type) + + def shader_source(self, shader: int, source: str): + self.native.glShaderSource(shader, source) + + def compile_shader(self, shader: int): + self.native.glCompileShader(shader) + + def delete_shader(self, shader): + self.native.glDeleteShader(shader) + + def create_program(self) -> int: + return self.native.glCreateProgram() + + def attach_shader(self, program: int, shader: int): + self.native.glAttachShader(program, shader) + + def link_program(self, program: int): + self.native.glLinkProgram(program) + + def delete_program(self, program): + self.native.glDeleteProgram(program) + + +class TogaGLRenderer(dynamic_proxy(GLSurfaceView.Renderer)): + def onSurfaceCreated(self, unused, config): + pass + + def onDrawFrame(self, unused): + self._redraw() + + def onSurfaceChanged(self, unused, width, height): + self._redraw() + + def _redraw(self): + context = AndroidOpenGLContext() + self.interface.on_render(context) + + +class OpenGLView(Widget): + def create(self): + self.native = GLSurfaceView(self._native_activity) + self.renderer = TogaGLRenderer() + self.renderer.interface = self.interface + self.native.setEGLContextClientVersion(2) + self.native.setRenderer(self.renderer) + + def redraw(self): + self.native.invalidate() diff --git a/examples/opengl/opengl/app.py b/examples/opengl/opengl/app.py index 5f657983b8..e759ab37eb 100644 --- a/examples/opengl/opengl/app.py +++ b/examples/opengl/opengl/app.py @@ -19,7 +19,7 @@ def startup(self): self.main_window.show() def callback_render(self, widget, context, **kwargs): - context.clear_color(1.0, 0.0, 0.0, 1.0) + context.clear_color(1.0, 1.0, 0.0, 1.0) context.clear(context.COLOR_BUFFER_BIT) diff --git a/examples/opengl/pyproject.toml b/examples/opengl/pyproject.toml index 670092e89b..44b4dcd2a9 100644 --- a/examples/opengl/pyproject.toml +++ b/examples/opengl/pyproject.toml @@ -51,16 +51,16 @@ requires = [ # "std-nslog>=1.0.0", #] -#[tool.briefcase.app.opengl.android] -#requires = [ -# "../../android", -#] +[tool.briefcase.app.opengl.android] +requires = [ + "../../android", +] -#base_theme = "Theme.MaterialComponents.Light.DarkActionBar" +base_theme = "Theme.MaterialComponents.Light.DarkActionBar" -#build_gradle_dependencies = [ -# "com.google.android.material:material:1.12.0", -#] +build_gradle_dependencies = [ + "com.google.android.material:material:1.12.0", +] # Web deployment #[tool.briefcase.app.opengl.web] diff --git a/qt/pyproject.toml b/qt/pyproject.toml index 46a45a1cf8..97ee5d21f3 100644 --- a/qt/pyproject.toml +++ b/qt/pyproject.toml @@ -84,6 +84,7 @@ MapView = "toga_qt.widgets.mapview:MapView" MultilineTextInput = "toga_qt.widgets.multilinetextinput:MultilineTextInput" NumberInput = "toga_qt.widgets.numberinput:NumberInput" OptionContainer = "toga_qt.widgets.optioncontainer:OptionContainer" +OpenGLView = "toga_qt.widgets.openglview:OpenGLView" PasswordInput = "toga_qt.widgets.passwordinput:PasswordInput" ProgressBar = "toga_qt.widgets.progressbar:ProgressBar" ScrollContainer = "toga_qt.widgets.scrollcontainer:ScrollContainer" From 762269006964ab9f1e4ff4cfd922dc74d2c265f1 Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Sat, 21 Mar 2026 16:48:09 +0000 Subject: [PATCH 3/5] Add Cocoa widget - initialization doesn't seem to be working. --- cocoa/pyproject.toml | 1 + cocoa/src/toga_cocoa/libs/appkit.py | 5 +++ cocoa/src/toga_cocoa/widgets/openglview.py | 49 +++++++++++++--------- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/cocoa/pyproject.toml b/cocoa/pyproject.toml index e413bc2f6b..6ed0b8c7b3 100644 --- a/cocoa/pyproject.toml +++ b/cocoa/pyproject.toml @@ -91,6 +91,7 @@ MapView = "toga_cocoa.widgets.mapview:MapView" MultilineTextInput = "toga_cocoa.widgets.multilinetextinput:MultilineTextInput" NumberInput = "toga_cocoa.widgets.numberinput:NumberInput" OptionContainer = "toga_cocoa.widgets.optioncontainer:OptionContainer" +OpenGLView = "toga_cocoa.widgets.openglview:OpenGLView" PasswordInput = "toga_cocoa.widgets.passwordinput:PasswordInput" ProgressBar = "toga_cocoa.widgets.progressbar:ProgressBar" ScrollContainer = "toga_cocoa.widgets.scrollcontainer:ScrollContainer" diff --git a/cocoa/src/toga_cocoa/libs/appkit.py b/cocoa/src/toga_cocoa/libs/appkit.py index 3faab77c8c..d68f8de4d9 100644 --- a/cocoa/src/toga_cocoa/libs/appkit.py +++ b/cocoa/src/toga_cocoa/libs/appkit.py @@ -518,8 +518,13 @@ class NSLayoutPriority(Enum): NSOpenGLPFARemotePixelBuffer = 91 # can be used to render offline to a pbuffer NSOpenGLPFAAllowOfflineRenderers = 96 # allow use of offline renderers NSOpenGLPFAAcceleratedCompute = 97 # choose a hardware accelerated compute device +NSOpenGLPFAOpenGLProfile = 99 # specify an OpenGL Profile to use NSOpenGLPFAVirtualScreenCount = 128 # number of virtual screens in this format +NSOpenGLProfileVersionLegacy = 0x1000 # choose a Legacy/Pre-OpenGL 3.0 Implementation +NSOpenGLProfileVersion3_2Core = 0x3200 # choose an OpenGL 3.2 Core Implementation +NSOpenGLProfileVersion4_1Core = 0x4100 # choose an OpenGL 4.1 Core Implementation + NSOpenGLCPSwapInterval = 222 ###################################################################### diff --git a/cocoa/src/toga_cocoa/widgets/openglview.py b/cocoa/src/toga_cocoa/widgets/openglview.py index 2258d3640e..41c2eba6a8 100644 --- a/cocoa/src/toga_cocoa/widgets/openglview.py +++ b/cocoa/src/toga_cocoa/widgets/openglview.py @@ -1,8 +1,7 @@ import ctypes +import ctypes.util -import moderngl -from OpenGL import GL -from rubicon.objc import objc_method, objc_property +from rubicon.objc import NSMakeRect, objc_method from travertino.size import at_least from toga.widgets.gl.openglcontext import OpenGLContext @@ -14,51 +13,57 @@ NSOpenGLPFADepthSize, NSOpenGLPFADoubleBuffer, NSOpenGLPFANoRecovery, + NSOpenGLPFAOpenGLProfile, NSOpenGLPFAStencilSize, NSOpenGLPFAWindow, NSOpenGLPixelFormat, + NSOpenGLProfileVersion4_1Core, NSOpenGLView, NSRect, ) from .base import Widget +# possibly use PyOpenGL instead? +GL = ctypes.cdll.LoadLibrary(ctypes.util.find_library("OpenGL")) + class CocoaOpenGLContext(OpenGLContext): def __init__(self, impl): self.impl = impl self.native = impl.native.openGLContext - print(self.native) def clear_color(self, r: float, g: float, b: float, a: float): - GL.glClearColor(r, g, b, a) + GL.glClearColor( + ctypes.c_float(r), ctypes.c_float(g), ctypes.c_float(b), ctypes.c_float(a) + ) print("here") def clear(self, mask: int): GL.glClear(mask) - print("and here") class TogaOpenGLView(NSOpenGLView): - interface = objc_property(object, weak=True) - impl = objc_property(object, weak=True) + # interface = objc_property(object, weak=True) + # impl = objc_property(object, weak=True) @objc_method def drawRect_(self, rect: NSRect) -> None: self.openGLContext.makeCurrentContext() - context = moderngl.create_context() - context.clear(1.0, 0.0, 0.0, 1.0) - # context = CocoaOpenGLContext(self.impl) - # context.native.makeCurrentContext() - # GL.glViewport(0, 0, int(rect.size.width), int(rect.size.height)) - # GL.glClearColor(1.0, 0.0, 0.0, 1.0) - # GL.glClear(GL.GL_COLOR_BUFFER_BIT) - # print('here') - # # self.interface.on_render(context) - self.openGLContext.flushBuffer() + context = self.openGLContext + GL.glViewport(0, 0, int(rect.size.width), int(rect.size.height)) + GL.glClearColor( + ctypes.c_float(1.0), + ctypes.c_float(0.0), + ctypes.c_float(0.0), + ctypes.c_float(1.0), + ) + GL.glClear(0x00004000) + context.flushBuffer() @objc_method def initWithFrame(self, frame: NSRect): + # XXX This doesn't seem to be being called? a = ( NSOpenGLPFANoRecovery, NSOpenGLPFAWindow, @@ -73,16 +78,20 @@ def initWithFrame(self, frame: NSRect): NSOpenGLPFAStencilSize, 8, NSOpenGLPFAAccumSize, + NSOpenGLPFAOpenGLProfile, + NSOpenGLProfileVersion4_1Core, 0, ) attributes = (ctypes.c_uint32 * len(a))(*a) pixel_format = NSOpenGLPixelFormat.alloc().initWithAttributes(attributes) - self.initWithFrame_pixelFormat(frame, pixel_format) + return self.initWithFrame_pixelFormat(frame, pixel_format) class OpenGLView(Widget): def create(self): - self.native = TogaOpenGLView.alloc().init() + # XXX This doesn't seem quite right - rect is arbitrary, but don't know size yet + rect = NSMakeRect(0, 0, 500, 200) + self.native = TogaOpenGLView.alloc().initWithFrame(rect) self.native.interface = self.interface self.native.impl = self From 1f6eb85777b68f2e2f92c62f94b537e8e41c6f2a Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Sat, 21 Mar 2026 18:56:54 +0000 Subject: [PATCH 4/5] Cocoa backend now working (thanks to help from @johnzhou721) --- cocoa/src/toga_cocoa/widgets/openglview.py | 33 ++++++---------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/cocoa/src/toga_cocoa/widgets/openglview.py b/cocoa/src/toga_cocoa/widgets/openglview.py index 41c2eba6a8..88d37c46b0 100644 --- a/cocoa/src/toga_cocoa/widgets/openglview.py +++ b/cocoa/src/toga_cocoa/widgets/openglview.py @@ -1,7 +1,7 @@ import ctypes import ctypes.util -from rubicon.objc import NSMakeRect, objc_method +from rubicon.objc import objc_method, objc_property from travertino.size import at_least from toga.widgets.gl.openglcontext import OpenGLContext @@ -13,11 +13,9 @@ NSOpenGLPFADepthSize, NSOpenGLPFADoubleBuffer, NSOpenGLPFANoRecovery, - NSOpenGLPFAOpenGLProfile, NSOpenGLPFAStencilSize, NSOpenGLPFAWindow, NSOpenGLPixelFormat, - NSOpenGLProfileVersion4_1Core, NSOpenGLView, NSRect, ) @@ -29,10 +27,6 @@ class CocoaOpenGLContext(OpenGLContext): - def __init__(self, impl): - self.impl = impl - self.native = impl.native.openGLContext - def clear_color(self, r: float, g: float, b: float, a: float): GL.glClearColor( ctypes.c_float(r), ctypes.c_float(g), ctypes.c_float(b), ctypes.c_float(a) @@ -44,26 +38,19 @@ def clear(self, mask: int): class TogaOpenGLView(NSOpenGLView): - # interface = objc_property(object, weak=True) - # impl = objc_property(object, weak=True) + interface = objc_property(object, weak=True) + impl = objc_property(object, weak=True) @objc_method def drawRect_(self, rect: NSRect) -> None: self.openGLContext.makeCurrentContext() context = self.openGLContext GL.glViewport(0, 0, int(rect.size.width), int(rect.size.height)) - GL.glClearColor( - ctypes.c_float(1.0), - ctypes.c_float(0.0), - ctypes.c_float(0.0), - ctypes.c_float(1.0), - ) - GL.glClear(0x00004000) + self.interface.on_render(CocoaOpenGLContext()) context.flushBuffer() @objc_method - def initWithFrame(self, frame: NSRect): - # XXX This doesn't seem to be being called? + def initWithFrame_(self, frame: NSRect): a = ( NSOpenGLPFANoRecovery, NSOpenGLPFAWindow, @@ -78,20 +65,16 @@ def initWithFrame(self, frame: NSRect): NSOpenGLPFAStencilSize, 8, NSOpenGLPFAAccumSize, - NSOpenGLPFAOpenGLProfile, - NSOpenGLProfileVersion4_1Core, 0, ) attributes = (ctypes.c_uint32 * len(a))(*a) - pixel_format = NSOpenGLPixelFormat.alloc().initWithAttributes(attributes) - return self.initWithFrame_pixelFormat(frame, pixel_format) + pixel_format = NSOpenGLPixelFormat.alloc().initWithAttributes_(attributes) + return self.initWithFrame_pixelFormat_(frame, pixel_format) class OpenGLView(Widget): def create(self): - # XXX This doesn't seem quite right - rect is arbitrary, but don't know size yet - rect = NSMakeRect(0, 0, 500, 200) - self.native = TogaOpenGLView.alloc().initWithFrame(rect) + self.native = TogaOpenGLView.alloc().init() self.native.interface = self.interface self.native.impl = self From 400e1671b3f4c8c610d3b179083e76ce15c9d01c Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Sun, 22 Mar 2026 00:25:36 +0000 Subject: [PATCH 5/5] Add iOS support; various other tweaks and fixes. --- .../src/toga_android/widgets/openglview.py | 23 ++--- cocoa/pyproject.toml | 2 +- cocoa/src/toga_cocoa/widgets/openglview.py | 34 +++++-- examples/opengl/pyproject.toml | 25 ++--- iOS/pyproject.toml | 1 + iOS/src/toga_iOS/libs/__init__.py | 2 + iOS/src/toga_iOS/libs/glkit.py | 25 +++++ iOS/src/toga_iOS/libs/opengles.py | 18 ++++ iOS/src/toga_iOS/widgets/openglview.py | 91 +++++++++++++++++++ 9 files changed, 190 insertions(+), 31 deletions(-) create mode 100644 iOS/src/toga_iOS/libs/glkit.py create mode 100644 iOS/src/toga_iOS/libs/opengles.py create mode 100644 iOS/src/toga_iOS/widgets/openglview.py diff --git a/android/src/toga_android/widgets/openglview.py b/android/src/toga_android/widgets/openglview.py index 266946f79a..ee9756b749 100644 --- a/android/src/toga_android/widgets/openglview.py +++ b/android/src/toga_android/widgets/openglview.py @@ -9,38 +9,35 @@ class AndroidOpenGLContext(OpenGLContext): """The implementation layer of a Qt OpenGL context.""" - def __init__(self): - self.native = GL - def clear_color(self, r: float, g: float, b: float, a: float): - self.native.glClearColor(r, g, b, a) + GL.glClearColor(r, g, b, a) def clear(self, mask: int): - self.native.glClear(mask) + GL.glClear(mask) def create_shader(self, type: int): - return self.native.glCreateShader(type) + return GL.glCreateShader(type) def shader_source(self, shader: int, source: str): - self.native.glShaderSource(shader, source) + GL.glShaderSource(shader, source) def compile_shader(self, shader: int): - self.native.glCompileShader(shader) + GL.glCompileShader(shader) def delete_shader(self, shader): - self.native.glDeleteShader(shader) + GL.glDeleteShader(shader) def create_program(self) -> int: - return self.native.glCreateProgram() + return GL.glCreateProgram() def attach_shader(self, program: int, shader: int): - self.native.glAttachShader(program, shader) + GL.glAttachShader(program, shader) def link_program(self, program: int): - self.native.glLinkProgram(program) + GL.glLinkProgram(program) def delete_program(self, program): - self.native.glDeleteProgram(program) + GL.glDeleteProgram(program) class TogaGLRenderer(dynamic_proxy(GLSurfaceView.Renderer)): diff --git a/cocoa/pyproject.toml b/cocoa/pyproject.toml index 6ed0b8c7b3..128162fb2d 100644 --- a/cocoa/pyproject.toml +++ b/cocoa/pyproject.toml @@ -90,8 +90,8 @@ Label = "toga_cocoa.widgets.label:Label" MapView = "toga_cocoa.widgets.mapview:MapView" MultilineTextInput = "toga_cocoa.widgets.multilinetextinput:MultilineTextInput" NumberInput = "toga_cocoa.widgets.numberinput:NumberInput" -OptionContainer = "toga_cocoa.widgets.optioncontainer:OptionContainer" OpenGLView = "toga_cocoa.widgets.openglview:OpenGLView" +OptionContainer = "toga_cocoa.widgets.optioncontainer:OptionContainer" PasswordInput = "toga_cocoa.widgets.passwordinput:PasswordInput" ProgressBar = "toga_cocoa.widgets.progressbar:ProgressBar" ScrollContainer = "toga_cocoa.widgets.scrollcontainer:ScrollContainer" diff --git a/cocoa/src/toga_cocoa/widgets/openglview.py b/cocoa/src/toga_cocoa/widgets/openglview.py index 88d37c46b0..db92ffddc9 100644 --- a/cocoa/src/toga_cocoa/widgets/openglview.py +++ b/cocoa/src/toga_cocoa/widgets/openglview.py @@ -1,5 +1,6 @@ import ctypes -import ctypes.util +from ctypes import c_float, cdll +from ctypes.util import find_library from rubicon.objc import objc_method, objc_property from travertino.size import at_least @@ -23,19 +24,40 @@ from .base import Widget # possibly use PyOpenGL instead? -GL = ctypes.cdll.LoadLibrary(ctypes.util.find_library("OpenGL")) +GL = cdll.LoadLibrary(find_library("OpenGL")) class CocoaOpenGLContext(OpenGLContext): def clear_color(self, r: float, g: float, b: float, a: float): - GL.glClearColor( - ctypes.c_float(r), ctypes.c_float(g), ctypes.c_float(b), ctypes.c_float(a) - ) - print("here") + GL.glClearColor(c_float(r), c_float(g), c_float(b), c_float(a)) def clear(self, mask: int): GL.glClear(mask) + def create_shader(self, type: int): + return GL.glCreateShader(type) + + def shader_source(self, shader: int, source: str): + GL.glShaderSource(shader, source) + + def compile_shader(self, shader: int): + GL.glCompileShader(shader) + + def delete_shader(self, shader: int): + GL.glDeleteShader(shader) + + def create_program(self) -> int: + return GL.glCreateProgram() + + def attach_shader(self, program: int, shader: int): + GL.glAttachShader(program, shader) + + def link_program(self, program: int): + GL.glLinkProgram(program) + + def delete_program(self, program): + GL.glDeleteProgram(program) + class TogaOpenGLView(NSOpenGLView): interface = objc_property(object, weak=True) diff --git a/examples/opengl/pyproject.toml b/examples/opengl/pyproject.toml index 44b4dcd2a9..bc19d7d687 100644 --- a/examples/opengl/pyproject.toml +++ b/examples/opengl/pyproject.toml @@ -6,7 +6,10 @@ project_name = "Button Demo" bundle = "org.beeware.toga.examples" version = "0.0.1" url = "https://beeware.org" -license.file = "LICENSE" +license = "BSD-3-Clause" +license-files = [ + "LICENSE", +] author = "Tiberius Yak" author_email = "tiberius@beeware.org" @@ -23,11 +26,11 @@ sources = ["opengl"] [tool.briefcase.app.opengl-qt] sources = ["opengl", "opengl_qt"] -#[tool.briefcase.app.opengl.macOS] -#requires = [ -# "../../cocoa", -# "std-nslog>=1.0.0", -#] +[tool.briefcase.app.opengl.macOS] +requires = [ + "../../cocoa", + "std-nslog>=1.0.0", +] #[tool.briefcase.app.opengl.linux] #requires = [ @@ -45,11 +48,11 @@ requires = [ #] # Mobile deployments -#[tool.briefcase.app.opengl.iOS] -#requires = [ -# "../../iOS", -# "std-nslog>=1.0.0", -#] +[tool.briefcase.app.opengl.iOS] +requires = [ + "../../iOS", + "std-nslog>=1.0.0", +] [tool.briefcase.app.opengl.android] requires = [ diff --git a/iOS/pyproject.toml b/iOS/pyproject.toml index 412506be64..f61d2ae0d5 100644 --- a/iOS/pyproject.toml +++ b/iOS/pyproject.toml @@ -90,6 +90,7 @@ Label = "toga_iOS.widgets.label:Label" MapView = "toga_iOS.widgets.mapview:MapView" MultilineTextInput = "toga_iOS.widgets.multilinetextinput:MultilineTextInput" NumberInput = "toga_iOS.widgets.numberinput:NumberInput" +OpenGLView = "toga_iOS.widgets.openglview:OpenGLView" OptionContainer = "toga_iOS.widgets.optioncontainer:OptionContainer" PasswordInput = "toga_iOS.widgets.passwordinput:PasswordInput" ProgressBar = "toga_iOS.widgets.progressbar:ProgressBar" diff --git a/iOS/src/toga_iOS/libs/__init__.py b/iOS/src/toga_iOS/libs/__init__.py index cd4018fa6f..1e05965682 100644 --- a/iOS/src/toga_iOS/libs/__init__.py +++ b/iOS/src/toga_iOS/libs/__init__.py @@ -2,6 +2,8 @@ from .core_graphics import * # NOQA from .core_location import * # NOQA from .foundation import * # NOQA +from .glkit import * # NOQA +from .opengles import * # NOQA from .mapkit import * # NOQA from .uikit import * # NOQA from .webkit import * # NOQA diff --git a/iOS/src/toga_iOS/libs/glkit.py b/iOS/src/toga_iOS/libs/glkit.py new file mode 100644 index 0000000000..aa8c197017 --- /dev/null +++ b/iOS/src/toga_iOS/libs/glkit.py @@ -0,0 +1,25 @@ +########################################################################## +# System/Library/Frameworks/UIKit.framework +########################################################################## +from ctypes import cdll, util + +from rubicon.objc import ObjCClass + +###################################################################### +glkit = cdll.LoadLibrary(util.find_library("GLKit")) +###################################################################### + +###################################################################### +# GLKView.h +GLKView = ObjCClass("GLKView") + +GLKViewDrawableColorFormatRGBA8888 = 0 +GLKViewDrawableDepthFormat24 = 2 +GLKViewDrawableStencilFormat8 = 1 +GLKViewDrawableMultisample4X = 1 + +EAGLContext = ObjCClass("EAGLContext") + +kEAGLRenderingAPIOpenGLES1 = 1 +kEAGLRenderingAPIOpenGLES2 = 2 +kEAGLRenderingAPIOpenGLES3 = 3 diff --git a/iOS/src/toga_iOS/libs/opengles.py b/iOS/src/toga_iOS/libs/opengles.py new file mode 100644 index 0000000000..d98f316580 --- /dev/null +++ b/iOS/src/toga_iOS/libs/opengles.py @@ -0,0 +1,18 @@ +########################################################################## +# System/Library/Frameworks/UIKit.framework +########################################################################## +from ctypes import cdll, util + +from rubicon.objc import ObjCClass + +###################################################################### +opengles = cdll.LoadLibrary(util.find_library("OpenGLES")) +###################################################################### + +###################################################################### +# EAGL.h +EAGLContext = ObjCClass("EAGLContext") + +kEAGLRenderingAPIOpenGLES1 = 1 +kEAGLRenderingAPIOpenGLES2 = 2 +kEAGLRenderingAPIOpenGLES3 = 3 diff --git a/iOS/src/toga_iOS/widgets/openglview.py b/iOS/src/toga_iOS/widgets/openglview.py new file mode 100644 index 0000000000..b5d686cccc --- /dev/null +++ b/iOS/src/toga_iOS/widgets/openglview.py @@ -0,0 +1,91 @@ +from ctypes import c_float + +from rubicon.objc import objc_method, objc_property +from travertino.size import at_least + +from toga.widgets.gl.openglcontext import OpenGLContext +from toga_iOS.libs import ( + CGRect, + CGSize, + EAGLContext, + GLKView, + GLKViewDrawableColorFormatRGBA8888, + GLKViewDrawableDepthFormat24, + GLKViewDrawableMultisample4X, + GLKViewDrawableStencilFormat8, + kEAGLRenderingAPIOpenGLES2, + opengles as GL, +) + +from .base import Widget + + +class iOSOpenGLContext(OpenGLContext): + def clear_color(self, r: float, g: float, b: float, a: float): + GL.glClearColor(c_float(r), c_float(g), c_float(b), c_float(a)) + + def clear(self, mask: int): + GL.glClear(mask) + + def create_shader(self, type: int): + return GL.glCreateShader(type) + + def shader_source(self, shader: int, source: str): + GL.glShaderSource(shader, source) + + def compile_shader(self, shader: int): + GL.glCompileShader(shader) + + def delete_shader(self, shader: int): + GL.glDeleteShader(shader) + + def create_program(self) -> int: + return GL.glCreateProgram() + + def attach_shader(self, program: int, shader: int): + GL.glAttachShader(program, shader) + + def link_program(self, program: int): + GL.glLinkProgram(program) + + def delete_program(self, program): + GL.glDeleteProgram(program) + + +class TogaGLKView(GLKView): + interface = objc_property(object, weak=True) + impl = objc_property(object, weak=True) + + @objc_method + def drawRect_(self, rect: CGRect) -> None: + self.interface.on_render(iOSOpenGLContext()) + + +class OpenGLView(Widget): + def create(self): + self.native = TogaGLKView.alloc().init() + self.native.interface = self.interface + self.native.impl = self + self.native.context = EAGLContext.alloc().initWithAPI_( + kEAGLRenderingAPIOpenGLES2 + ) + + # # Configure renderbuffers created by the view + self.native.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888 + self.native.drawableDepthFormat = GLKViewDrawableDepthFormat24 + self.native.drawableStencilFormat = GLKViewDrawableStencilFormat8 + + # # Enable multisampling + self.native.drawableMultisample = GLKViewDrawableMultisample4X + + # Add the layout constraints + self.add_constraints() + + def redraw(self): + self.native.needsDisplay = True + + # Rehint + def rehint(self): + fitting_size = self.native.systemLayoutSizeFittingSize(CGSize(0, 0)) + self.interface.intrinsic.width = at_least(fitting_size.width) + self.interface.intrinsic.height = at_least(fitting_size.height)