diff --git a/examples/tests/clear-color-setting.ts b/examples/tests/clear-color-setting.ts new file mode 100644 index 00000000..9cc75081 --- /dev/null +++ b/examples/tests/clear-color-setting.ts @@ -0,0 +1,70 @@ +/* + * 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 type { INode, RendererMain } from '@lightningjs/renderer'; +import type { ExampleSettings } from '../common/ExampleSettings.js'; +import { PageContainer } from '../common/PageContainer.js'; + +export async function automation(settings: ExampleSettings) { + // Snapshot all the pages + await (await test(settings)).snapshotPages(); +} + +export default async function test(settings: ExampleSettings) { + const { renderer } = settings; + const pageContainer = new PageContainer(settings, { + width: renderer.settings.appWidth, + height: renderer.settings.appHeight, + title: 'Dynamic Settings clearColor Tests', + }); + + pageContainer.pushPage(createTestCase(renderer, 'red', 0xff0000ff)); + pageContainer.pushPage(createTestCase(renderer, 'green', 0x00ff00ff)); + pageContainer.pushPage(createTestCase(renderer, 'transparent', 0x00000000)); + + await delay(200); + pageContainer.finalizePages(); + return pageContainer; +} + +function createTestCase( + renderer: RendererMain, + colorName: 'red' | 'green' | 'transparent', + color: number, +) { + return async function (page: INode) { + renderer.createTextNode({ + mount: 0.5, + width: 400, + height: 400, + text: `Test passes if the background appears as ${colorName}`, + fontFamily: 'Ubuntu', + fontSize: 50, + x: renderer.settings.appWidth / 2, + y: renderer.settings.appHeight / 2, + parent: page, + }); + + renderer.setClearColor(color); + }; +} + +function delay(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} diff --git a/src/core/Stage.ts b/src/core/Stage.ts index 572d2490..ee72e858 100644 --- a/src/core/Stage.ts +++ b/src/core/Stage.ts @@ -266,6 +266,11 @@ export class Stage { } } + setClearColor(color: number) { + this.renderer.updateClearColor(color); + this.renderRequested = true; + } + updateFrameTime() { const newFrameTime = getTimeStamp(); this.lastFrameTime = this.currentFrameTime; diff --git a/src/core/renderers/CoreRenderer.ts b/src/core/renderers/CoreRenderer.ts index 84691ebf..16160746 100644 --- a/src/core/renderers/CoreRenderer.ts +++ b/src/core/renderers/CoreRenderer.ts @@ -110,4 +110,5 @@ export abstract class CoreRenderer { abstract renderToTexture(node: CoreNode): void; abstract getBufferInfo(): BufferInfo | null; abstract getDefShaderCtr(): BaseShaderController; + abstract updateClearColor(color: number): void; } diff --git a/src/core/renderers/canvas/CanvasCoreRenderer.ts b/src/core/renderers/canvas/CanvasCoreRenderer.ts index 67d91489..d4c53ab6 100644 --- a/src/core/renderers/canvas/CanvasCoreRenderer.ts +++ b/src/core/renderers/canvas/CanvasCoreRenderer.ts @@ -331,4 +331,13 @@ export class CanvasCoreRenderer extends CoreRenderer { getBufferInfo(): null { return null; } + + /** + * Updates the clear color of the canvas renderer. + * + * @param color - The color to set as the clear color. + */ + updateClearColor(color: number) { + this.clearColor = color ? getRgbaComponents(color) : undefined; + } } diff --git a/src/core/renderers/webgl/WebGlCoreRenderer.ts b/src/core/renderers/webgl/WebGlCoreRenderer.ts index 515d0588..4b505a34 100644 --- a/src/core/renderers/webgl/WebGlCoreRenderer.ts +++ b/src/core/renderers/webgl/WebGlCoreRenderer.ts @@ -32,6 +32,7 @@ import { type CoreWebGlExtensions, getWebGlParameters, getWebGlExtensions, + type WebGlColor, } from './internal/RendererUtils.js'; import { WebGlCoreCtxTexture } from './WebGlCoreCtxTexture.js'; import { Texture, TextureType } from '../../textures/Texture.js'; @@ -86,6 +87,11 @@ export class WebGlCoreRenderer extends CoreRenderer { defaultShader: WebGlCoreShader; quadBufferCollection: BufferCollection; + clearColor: WebGlColor = { + raw: 0x00000000, + normalized: [0, 0, 0, 0], + }; + /** * White pixel texture used by default when no texture is specified. */ @@ -127,10 +133,10 @@ export class WebGlCoreRenderer extends CoreRenderer { options.contextSpy, ); const glw = (this.glw = new WebGlContextWrapper(gl)); - - const color = getNormalizedRgbaComponents(clearColor); glw.viewport(0, 0, canvas.width, canvas.height); - glw.clearColor(color[0]!, color[1]!, color[2]!, color[3]!); + + this.updateClearColor(clearColor); + glw.setBlend(true); glw.blendFunc(glw.ONE, glw.ONE_MINUS_SRC_ALPHA); @@ -754,9 +760,9 @@ export class WebGlCoreRenderer extends CoreRenderer { node.hasRTTupdates = false; } - const color = getNormalizedRgbaComponents(this.stage.options.clearColor); + const clearColor = this.clearColor.normalized; // Restore the default clear color - glw.clearColor(color[0]!, color[1]!, color[2]!, color[3]!); + glw.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); // Bind the default framebuffer glw.bindFramebuffer(null); @@ -784,4 +790,28 @@ export class WebGlCoreRenderer extends CoreRenderer { override getDefShaderCtr(): BaseShaderController { return this.defShaderCtrl; } + + /** + * Updates the WebGL context's clear color and clears the color buffer. + * + * @param color - The color to set as the clear color, represented as a 32-bit integer. + */ + updateClearColor(color: number) { + if (this.clearColor.raw === color) { + return; + } + const glw = this.glw; + const normalizedColor = getNormalizedRgbaComponents(color); + glw.clearColor( + normalizedColor[0], + normalizedColor[1], + normalizedColor[2], + normalizedColor[3], + ); + this.clearColor = { + raw: color, + normalized: normalizedColor, + }; + glw.clear(); + } } diff --git a/src/core/renderers/webgl/internal/RendererUtils.ts b/src/core/renderers/webgl/internal/RendererUtils.ts index 78efb1cb..41dabcce 100644 --- a/src/core/renderers/webgl/internal/RendererUtils.ts +++ b/src/core/renderers/webgl/internal/RendererUtils.ts @@ -146,3 +146,8 @@ export function isHTMLImageElement(obj: unknown): obj is HTMLImageElement { obj.constructor.name === 'HTMLImageElement' ); } + +export interface WebGlColor { + raw: number; + normalized: [number, number, number, number]; +} diff --git a/src/main-api/Renderer.ts b/src/main-api/Renderer.ts index 75d8123c..0e557917 100644 --- a/src/main-api/Renderer.ts +++ b/src/main-api/Renderer.ts @@ -658,4 +658,13 @@ export class RendererMain extends EventEmitter { rerender() { throw new Error('Not implemented'); } + + /** + * Sets the clear color for the stage. + * + * @param color - The color to set as the clear color. + */ + setClearColor(color: number) { + this.stage.setClearColor(color); + } } diff --git a/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-1.png b/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-1.png new file mode 100644 index 00000000..fd9819ec Binary files /dev/null and b/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-1.png differ diff --git a/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-2.png b/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-2.png new file mode 100644 index 00000000..fbd6e939 Binary files /dev/null and b/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-2.png differ diff --git a/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-3.png b/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-3.png new file mode 100644 index 00000000..332dad55 Binary files /dev/null and b/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-3.png differ