Skip to content

Commit

Permalink
Update main canvas size when a dom target changes size
Browse files Browse the repository at this point in the history
  • Loading branch information
jespertheend committed May 10, 2024
1 parent 0a9b433 commit 542388d
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 5 deletions.
27 changes: 27 additions & 0 deletions src/rendering/renderers/webGl/WebGlRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export class WebGlRenderer extends Renderer {
return this.#gl;
}

Check warning on line 37 in src/rendering/renderers/webGl/WebGlRenderer.js

View check run for this annotation

Codecov / codecov/patch

src/rendering/renderers/webGl/WebGlRenderer.js#L28-L37

Added lines #L28 - L37 were not covered by tests

/** @type {Set<WebGlRendererDomTarget>} */
#domTargets = new Set();

/** @type {WeakMap<import("../../Material.js").Material, CachedMaterialData>} */
#cachedMaterialData = new WeakMap();

Expand Down Expand Up @@ -102,6 +105,30 @@ export class WebGlRenderer extends Renderer {
this.#isInit = true;
}

/**
* @override
*/
createDomTarget() {
const domTarget = super.createDomTarget();
this.#domTargets.add(domTarget);
domTarget.onResize(() => {
if (!this.#canvas) return;

Check warning on line 115 in src/rendering/renderers/webGl/WebGlRenderer.js

View check run for this annotation

Codecov / codecov/patch

src/rendering/renderers/webGl/WebGlRenderer.js#L115

Added line #L115 was not covered by tests
let width = 1;
let height = 1;
for (const target of this.#domTargets) {
width = Math.max(width, target.width);
height = Math.max(height, target.height);
}
if (this.#canvas.width != width) {
this.#canvas.width = width;
}
if (this.#canvas.height != height) {
this.#canvas.height = height;
}
});
return domTarget;
}

/**
* @override
* @param {WebGlRendererDomTarget} domTarget
Expand Down
12 changes: 12 additions & 0 deletions src/rendering/renderers/webGl/WebGlRendererDomTarget.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ export class WebGlRendererDomTarget extends RendererDomTarget {
#canvas;
#ctx;

/** @type {Set<() => void>} */
#onResizeCbs = new Set();

/**
* @param {import("./WebGlRenderer.js").WebGlRenderer} renderer
*/
Expand Down Expand Up @@ -33,6 +36,15 @@ export class WebGlRendererDomTarget extends RendererDomTarget {
super.resize(w, h);
this.#canvas.width = w;
this.#canvas.height = h;
this.#onResizeCbs.forEach((cb) => cb());
}

/**
* Registers a callback that is fired when `resize` is called.
* @param {() => void} cb
*/
onResize(cb) {
this.#onResizeCbs.add(cb);
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/rendering/renderers/webGpu/WebGpuRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ export class WebGpuRenderer extends Renderer {
await promise;
}

/**
* @override
*/
createDomTarget() {
const domTarget = super.createDomTarget();
this.configureSwapChainAsync(domTarget);
Expand Down
50 changes: 48 additions & 2 deletions test/unit/src/rendering/renderers/webGl/WebGlRenderer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ Deno.test({
const domTarget = renderer.createDomTarget();

const { camComponent } = createCam();
renderer.render(domTarget, camComponent);
domTarget.render(camComponent);

const commandLog = assertHasSingleContext();
const { commandLog } = assertHasSingleContext();
commandLog.assertCount(5);

assertEquals(commandLog.log, [
Expand Down Expand Up @@ -58,6 +58,52 @@ Deno.test({
},
});

Deno.test({
name: "Main canvas resizes to that of the largest dom target",
async fn() {
await runWithWebGlMocksAsync(async () => {
const renderer = new WebGlRenderer();
await renderer.init();

const { commandLog, canvas } = assertHasSingleContext();

const domTargetA = renderer.createDomTarget();
domTargetA.resize(100, 200);
assertEquals(canvas.width, 100);
assertEquals(canvas.height, 200);

const domTargetB = renderer.createDomTarget();
domTargetB.resize(300, 400);
assertEquals(canvas.width, 300);
assertEquals(canvas.height, 400);

const { camComponent } = createCam();
domTargetA.render(camComponent);
domTargetB.render(camComponent);

const commands1 = commandLog.getFilteredArgs("viewport");
assertEquals(commands1, [
[0, 200, 100, 200],
[0, 0, 300, 400],
]);
commandLog.clear();

domTargetB.resize(1, 1);
assertEquals(canvas.width, 100);
assertEquals(canvas.height, 200);

domTargetA.render(camComponent);
domTargetB.render(camComponent);

const commands2 = commandLog.getFilteredArgs("viewport");
assertEquals(commands2, [
[0, 0, 100, 200],
[0, 199, 1, 1],
]);
});
},
});

testTypes({
name: "CustomMaterialData callback arguments have the correct types",
fn() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,30 @@ export class WebGlCommandLog {
/** @type {CommandLogEntry[]} */
log = [];

clear() {
this.log = [];
}

/**
* @param {number} count
*/
assertCount(count) {
assertEquals(this.log.length, count);
}

/**
* @param {...string} commands
*/
getFilteredCommands(...commands) {
return this.log.filter((c) => commands.includes(c.name));
}

/**
* @param {...string} commands
*/
getFilteredArgs(...commands) {
return this.log.filter((c) => commands.includes(c.name)).map((c) => c.args);
}
}

export function createWebGlRenderingContext() {
Expand Down
6 changes: 3 additions & 3 deletions test/unit/src/rendering/renderers/webGl/shared/webGlMocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createWebGlRenderingContext } from "./WebGlRenderingContext.js";
const oldDocument = globalThis.document;
let installed = false;

/** @type {{context: WebGLRenderingContext, commandLog: import("./WebGlRenderingContext.js").WebGlCommandLog}[]} */
/** @type {{canvas: HTMLCanvasElement, context: WebGLRenderingContext, commandLog: import("./WebGlRenderingContext.js").WebGlCommandLog}[]} */
let createdContexts = [];

export function installWebGlMocks() {
Expand Down Expand Up @@ -35,7 +35,7 @@ export function installWebGlMocks() {
if (contextId == "webgl") {
if (!webGlContextSupported) return null;
const { context, commandLog } = createWebGlRenderingContext();
createdContexts.push({ context, commandLog });
createdContexts.push({ canvas, context, commandLog });
return context;
} else if (contextId == "2d") {
if (!context2dSupported) return null;
Expand Down Expand Up @@ -90,5 +90,5 @@ export function assertHasSingleContext() {
if (createdContexts.length != 1) {
throw new Error("Expected exactly one webgl context to be created");
}
return createdContexts[0].commandLog;
return createdContexts[0];
}

0 comments on commit 542388d

Please sign in to comment.