From 75f60508ef898c8f286bf9d7680f3e73b1ab00d4 Mon Sep 17 00:00:00 2001 From: Ib Green Date: Thu, 20 Jan 2022 06:55:35 -0800 Subject: [PATCH] wip --- modules/webgl/src/adapter/resources/video.ts | 43 +++++++++++++ .../src/adapter/resources/webgl-video.ts | 60 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 modules/webgl/src/adapter/resources/video.ts create mode 100644 modules/webgl/src/adapter/resources/webgl-video.ts diff --git a/modules/webgl/src/adapter/resources/video.ts b/modules/webgl/src/adapter/resources/video.ts new file mode 100644 index 0000000000..aceec524a3 --- /dev/null +++ b/modules/webgl/src/adapter/resources/video.ts @@ -0,0 +1,43 @@ +import {Texture, ExternalTexture} from "@luma.gl/api"; + +// @ts-expect-error +const {HAVE_CURRENT_DATA, HAVE_METADATA} = HTMLVideoElement; + +type ResourceProps = {}; + +export type ExternalTextureProps = ResourceProps & { + source: HTMLVideoElement; + colorSpace?: 'srgb'; +} + +abstract class Video { + protected _video: HTMLVideoElement; + protected _videoLoaded: boolean = false; + protected _lastTime: number = -1 + + constructor(props) { + if (this._video.readyState >= HAVE_METADATA) { + this._videoLoaded = true; + } else { + this._video.addEventListener('loadeddata', () => { + this._videoLoaded = true; + this._initializeTexture(); + }); + } + + lastTime: this._video.readyState >= HAVE_CURRENT_DATA ? this._video.currentTime : -1 + } + + abstract getCurrentFrame(): Texture | ExternalTexture; + + abstract _initializeTexture(): void; + + /** Check if video has advanced and a texture should be generated */ + protected _updateTime(): boolean { + if (this._lastTime === this._video.currentTime || this._video.readyState < HAVE_CURRENT_DATA) { + return false; + } + this._lastTime = this._video.currentTime; + return true; + } +} diff --git a/modules/webgl/src/adapter/resources/webgl-video.ts b/modules/webgl/src/adapter/resources/webgl-video.ts new file mode 100644 index 0000000000..91a866eed5 --- /dev/null +++ b/modules/webgl/src/adapter/resources/webgl-video.ts @@ -0,0 +1,60 @@ +import {ExternalTexture} from "@luma.gl/api/"; +import Video from './video'; + + +export default class WEBGLVideo extends Video { + constructor(props) { + super(props); + } + + _initializeTexture() { + + } + + getCurrentFrame(): ExternalTexture { + // @ts-expect-error + if (lastTime === this._video.currentTime || this._video.readyState < HTMLVideoElement.HAVE_CURRENT_DATA) { + return; + } + this.setSubImageData({ + data: this._video, + parameters + }); + if (this.mipmaps) { + this.generateMipmap(); + } + this._video.lastTime = this._video.currentTime; + } +} + +export default class WebGPUVideo extends Video { + readonly device: WebGPUDevice; + readonly handle: GPUExternalTexture; + sampler: WebGPUSampler; + + constructor(device: WebGPUDevice, props: ExternalTextureProps) { + super(device, props); + this.device = device; + this.handle = this.props.handle || this.device.handle.importExternalTexture({ + source: props.source, + colorSpace: props.colorSpace + }); + this.sampler = null; + } + + destroy(): void { + // External textures are destroyed automatically, + // as a microtask, instead of manually or upon garbage collection like other resources. + // this.handle.destroy(); + } + + getCurrentFrame(): ExternalTexture { + return new WEBGPUExternalTexture(this.device, this.props); + } + /** Set default sampler */ + setSampler(sampler: Sampler | SamplerProps): this { + // We can accept a sampler instance or set of props; + this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler); + return this; + } +}