@lightningjs/renderer
Version:
Lightning 3 Renderer
232 lines • 7.66 kB
JavaScript
/*
* If not stated otherwise in this file or this component's LICENSE file the
* following copyright and licenses apply:
*
* Copyright 2023 Comcast Cable Communications Management, LLC.
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { EventEmitter } from '../../common/EventEmitter.js';
export var TextureType;
(function (TextureType) {
TextureType[TextureType["generic"] = 0] = "generic";
TextureType[TextureType["color"] = 1] = "color";
TextureType[TextureType["image"] = 2] = "image";
TextureType[TextureType["noise"] = 3] = "noise";
TextureType[TextureType["renderToTexture"] = 4] = "renderToTexture";
TextureType[TextureType["subTexture"] = 5] = "subTexture";
})(TextureType || (TextureType = {}));
/**
* Represents a source of texture data for a CoreContextTexture.
*
* @remarks
* Texture sources are used to populate a CoreContextTexture when that texture
* is loaded. Texture data retrieved by the CoreContextTexture by the
* `getTextureData` method. It's the responsibility of the concerete `Texture`
* subclass to implement this method appropriately.
*/
export class Texture extends EventEmitter {
txManager;
/**
* The dimensions of the texture
*
* @remarks
* Until the texture data is loaded for the first time the value will be
* `null`.
*/
_dimensions = null;
_error = null;
/**
* Texture states that are considered transitional and should be skipped during cleanup
*/
static TRANSITIONAL_TEXTURE_STATES = ['fetching', 'fetched', 'loading'];
// aggregate state
state = 'initial';
renderableOwners = new Set();
renderable = false;
type = TextureType.generic;
preventCleanup = false;
ctxTexture;
textureData = null;
constructor(txManager) {
super();
this.txManager = txManager;
}
get dimensions() {
return this._dimensions;
}
get error() {
return this._error;
}
/**
* Add/remove an owner to/from the Texture based on its renderability.
*
* @remarks
* Any object can own a texture, be it a CoreNode or even the state object
* from a Text Renderer.
*
* When the reference to the texture that an owner object holds is replaced
* or cleared it must call this with `renderable=false` to release the owner
* association.
*
* @param owner
* @param renderable
*/
setRenderableOwner(owner, renderable) {
const oldSize = this.renderableOwners.size;
if (renderable === true) {
if (this.renderableOwners.has(owner) === false) {
// Add the owner to the set
this.renderableOwners.add(owner);
}
const newSize = this.renderableOwners.size;
if (newSize > oldSize && newSize === 1) {
this.renderable = true;
this.onChangeIsRenderable?.(true);
this.load();
}
}
else {
this.renderableOwners.delete(owner);
const newSize = this.renderableOwners.size;
if (newSize < oldSize && newSize === 0) {
this.renderable = false;
this.onChangeIsRenderable?.(false);
this.txManager.orphanTexture(this);
}
}
}
load() {
this.txManager.loadTexture(this);
}
/**
* Load the core context texture for this Texture.
* The ctxTexture is created by the renderer and lives on the GPU.
*
* @returns
*/
loadCtxTexture() {
if (this.ctxTexture === undefined) {
this.ctxTexture = this.txManager.renderer.createCtxTexture(this);
}
return this.ctxTexture;
}
/**
* Free the core context texture for this Texture.
*
* @remarks
* The ctxTexture is created by the renderer and lives on the GPU.
*/
free() {
this.ctxTexture?.free();
}
/**
* Destroy the texture.
*
* @remarks
* This method is called when the texture is no longer needed and should be
* cleaned up.
*/
destroy() {
// Only free GPU resources if we're in a state where they exist
if (this.state === 'loaded') {
this.free();
}
// Always free texture data regardless of state
this.freeTextureData();
}
/**
* Free the source texture data for this Texture.
*
* @remarks
* The texture data is the source data that is used to populate the CoreContextTexture.
* e.g. ImageData that is downloaded from a URL.
*/
freeTextureData() {
this.textureData = null;
}
setState(state, errorOrDimensions) {
if (this.state === state) {
return;
}
let payload = null;
if (state === 'loaded') {
if (errorOrDimensions !== undefined &&
'width' in errorOrDimensions === true &&
'height' in errorOrDimensions === true &&
errorOrDimensions.width !== undefined &&
errorOrDimensions.height !== undefined) {
this._dimensions = errorOrDimensions;
}
payload = this._dimensions;
}
else if (state === 'failed') {
this._error = errorOrDimensions;
payload = this._error;
}
// emit the new state
this.state = state;
this.emit(state, payload);
}
/**
* Get the texture data for this texture.
*
* @remarks
* This method is called by the CoreContextTexture when the texture is loaded.
* The texture data is then used to populate the CoreContextTexture.
*
* @returns
* The texture data for this texture.
*/
async getTextureData() {
if (this.textureData === null) {
this.textureData = await this.getTextureSource();
}
return this.textureData;
}
/**
* Make a cache key for this texture.
*
* @remarks
* Each concrete `Texture` subclass must implement this method to provide an
* appropriate cache key for the texture type including the texture's
* properties that uniquely identify a copy of the texture. If the texture
* type does not support caching, then this method should return `false`.
*
* @param props
* @returns
* A cache key for this texture or `false` if the texture type does not
* support caching.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
static makeCacheKey(props) {
return false;
}
/**
* Resolve the default values for the texture's properties.
*
* @remarks
* Each concrete `Texture` subclass must implement this method to provide
* default values for the texture's optional properties.
*
* @param props
* @returns
* The default values for the texture's properties.
*/
static resolveDefaults(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
props) {
return {};
}
}
//# sourceMappingURL=Texture.js.map