"""Shared isolated HTTP sessions; callers attach hooks before navigating to url.""" import argparse from contextlib import contextmanager import os from pathlib import Path import sys from urllib.parse import quote from server import DIST, isolated_server GPU_ARGS = ['--use-angle=vulkan', '--enable-features=Vulkan,VulkanFromANGLE', '--enable-gpu', '--ignore-gpu-blocklist', '--enable-gpu-rasterization', '--enable-unsafe-webgpu'] SOFT_ARGS = ['--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] DEFAULT_GPU = 'real' def gpu_option(parser): parser.add_argument('--gpu', choices=['real', 'soft'], default=os.environ.get('DEEPGRAIN_GPU', DEFAULT_GPU)) def consume_gpu_option(): """Keep the older scripts' positional arguments.""" parser = argparse.ArgumentParser(add_help=False) gpu_option(parser) options, remaining = parser.parse_known_args() os.environ['DEEPGRAIN_GPU'] = options.gpu sys.argv[1:] = remaining return options.gpu @contextmanager def launch(*, gpu=None, browser_name='chromium', viewport=None, page_path=None, args=()): from playwright.sync_api import sync_playwright gpu = gpu or os.environ.get('DEEPGRAIN_GPU', DEFAULT_GPU) if gpu not in ('real', 'soft'): raise ValueError('GPU must be real or soft') path = Path(page_path).resolve() if page_path else DIST / 'index.html' with isolated_server(path.parent) as base, sync_playwright() as p: flags = (GPU_ARGS if gpu == 'real' else SOFT_ARGS) if browser_name == 'chromium' else [] browser = getattr(p, browser_name).launch(args=[*flags, *args]) try: context = browser.new_context(viewport=viewport or {'width': 1280, 'height': 760}) page = context.new_page() if gpu == 'soft': page.add_init_script('window.__allowSoftwareGL = true;') yield browser, page, base + '/' + quote(path.name) finally: browser.close() def installed(browser_name): from playwright.sync_api import sync_playwright with sync_playwright() as p: return Path(getattr(p, browser_name).executable_path).is_file() def capabilities(page): page.wait_for_function('CAPS.ready') return page.evaluate("""() => { const gl = document.createElement('canvas').getContext('webgl2'); const dbg = gl && gl.getExtension('WEBGL_debug_renderer_info'); return { isolated: CAPS.isolated, webgpu: CAPS.webgpu, adapterInfo: CAPS.adapterInfo, renderer: gl ? gl.getParameter(dbg ? dbg.UNMASKED_RENDERER_WEBGL : gl.RENDERER) : null }; }""")